質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.75%

  • PHP

    19173questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    5509questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • INSERT

    44questions

    INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

  • DELETE

    20questions

    ファイルシステムからファイル、データベースからレコードを削除することまたはメモリ内のオブジェクトの割り当てを取り消すことをさします。もしくは、HTTPプロトコルのDELETEを指すこともあります。

MySQLでDELETEを行った後のINSERT

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 609

metamonsan

score 3

前提・実現したいこと

phpとMySQL1を利用して簡易掲示板を作っています。
入力データをMySQLに保存し、そこからデータを取得・表示させる流れです。

その中で、削除機能、編集機能を実装しようとしているのですが、そのうち削除機能に問題がありまして、質問させていただきます。

発生している問題・エラーメッセージ

DELETEを行ってから新しく投稿をINSERTで入力すると、DELETEした配列部分に入ってしまいます。
例えば

1,内容
2,内容
3,内容


となっているうちの2を削除してから新規投稿すると

1,内容
4,内容
3,内容


となってしまいます。その後は3の後ろに5、6、…と続きますが、削除を繰り返すともっとずれてしまいます。
これを修正したいです。

該当のソースコード

周辺がごちゃごちゃしていて見にくくなってしまうので、該当部分だけ記載します。

//投稿部分
$sql='INSERT INTO kadai(name,comment,date,pass) VALUES(:name,:comment,now(),:pass)';

$stmt=$pdo->prepare($sql);

stmt->bindParam(":name",$name,PDO::PARAM_STR);
$stmt->bindParam(":comment",$comment,PDO::PARAM_STR);
$stmt->bindParam(":pass",$pass,PDO::PARAM_STR);

$name=$_POST["name"];
$comment=$_POST["comment"];
$pass=$_POST["password"];

$stmt->execute();

…

//削除部分
$sql="DELETE FROM kadai WHERE id=:id";

$stmt=$pdo->prepare($sql);

$stmt->bindParam(":id",$id,PDO::PARAM_INT);

$id=$_POST["deletenumber"];

$stmt->execute();


投稿部分、削除部分をhtmlに設置したそれぞれのボタンを押したときで条件分岐させています。

試したこと

ずれないようにするために、以下のことを考えました。
・UPDATEで内容を「削除済み」に書き換え、表示する際の条件分岐で「削除済み」となっているものをはじく
⇒これだと、番号が残ってしまっているため編集ボタンと干渉してしまうということと、万が一「削除済み」というコメントを投稿した際に意図せずはじかれる可能性があるかな…と感じました。
・UPDATEで番号を上書きし、表示の条件分岐ではじく
⇒具体的には、番号を0にUPDATEすればいいかなと考えていますが、送信された番号をWHEREを使って指定するやり方がよくわからないので実装できていません。

自分でも深く理解できていないため、わかりにくい文章になってしまい申し訳ありません。よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

まず順番の話はPHPでSELECTして取り出した後の話をしてますか?

MySQLに限らないと思うんですが(適当)ORDERで指定しない限りSELECTの順番は保証されないと言う前提があります。
(要するに新しく追加したレコードが最後、もしくは最初に取得される事は保証されない)

ですのでDELETEしてからINSERTするのであれば例えばですが、AUTOINCREMENTでID列を作っておいてからSELECT時にORDER BY IDとかやるなどの順番が保証される処置が必要だと思います。
コレだと質問で言うと2を削除してからINSERTすると必ず4が追加されるのでORDER BYすれば必ずそのじゅんばんになります。

もしくはDATETIMEやTIMESTAMPの列を準備して追加・更新時に時間を更新するとか(この場合は時間順と言うことになりますが)並び替えしたい順番を保証する列を作成するのが常道かと思います。

何にせよ自分の中の前提(悪い言い方をすれば決めつけ)を破棄して、多少面倒でも間違いないやり方をしていく方が後からトラブルは少なくなり、修正しやすくなると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/17 02:21

    SELECT ORDER BYで取得することで無事解決しました。

    「DELETE後のINSERTに問題がある!」と決めつけて情報を集めていたために、まったくヒットしなかったようでした。単純に取得の並び替えの問題だったのですね。
    状況の言いかえなど、もっと広い視点で検索をかけていこうと思います。

    ありがとうございました。

    キャンセル

+1

勝手にIDが増えていくのはIDフィールドにAUTO_INCREMENT属性
が付与されているからと思われます。

AUTO_INCREMENT属性がついているIDの場合、テーブル自体に次に振られるべきIDが記録されており、insertされる度に1増えていき、レコードが削除されても減ることはありません。

なのでたとえば、
3件追加→3件削除→1件追加 とした場合、テーブルに残るのはID4のレコードになります。

よくある解決方法としては、

  1. IDに欠番が発生することを気にしない
    下手にIDを再利用すると色々面倒なこと(例えば、このIDを他のテーブルでのデータ連結に使用している場合)が起こる可能性が増えるので、IDに欠番が発生しても気にしないという方法はよくあります。(個人的には特に理由がない限りは一番お勧めです)
  2. 論理削除する。
    例えば、is_deleteフィールドを設けて、削除したことにしたいレコードについてis_deleteフィールドに1を入れてupdateする。といった方法です。これは今回考えられている方法に近いと思います。これもよくある実装かと思います。
  3. 自力でIDを採番する
    deleteは現状のまま行い、insertするタイミングで空いているIDを自力で探して、IDを指定してinsertします。1番目のお勧め理由によって個人的には嫌いな方法です。
  4. deleteしたタイミングでIDを詰める。途中のIDを削除した場合に、それより後ろのIDをすべて-1してupdateします。普通はやらないです。

あたりかなと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/17 02:18

    ありがとうございます。
    聞き方がわかりにくくて大変申し訳なかったのですが、とにかく番号の若い順から表示されるようにしたかったのです。

    とはいえ、どこかで詰めずに削除されたというメッセージだけ表示させられないか…とは考えておりました。初心者であるために2以降は非常にややこしそうに見えますね…素直にこのまま詰めていきたいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.75%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    19173questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    5509questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • INSERT

    44questions

    INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

  • DELETE

    20questions

    ファイルシステムからファイル、データベースからレコードを削除することまたはメモリ内のオブジェクトの割り当てを取り消すことをさします。もしくは、HTTPプロトコルのDELETEを指すこともあります。