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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

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

PHP

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

Q&A

解決済

2回答

2955閲覧

[mysql][pdo]レコードを削除してから挿入を1文で表現したい

coinbura

総合スコア106

MySQL

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

PHP

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

0グッド

0クリップ

投稿2018/04/21 06:36

以下の2つのsql文を実行しようとしています。

$sql = "DELETE FROM datatable WHERE hoge <= 2;" $sql .= "INSERT INTO datatable(id,hoge) VALUES(1,3);" $stmt = $pdo->query($sql);

挙動としては、削除が完全に終わってから挿入する事を想定しています。

今現在、これを実行すると正しく動作しているように思えるのですが、レコード量が膨大になるとまた違うものなのでしょうか?
「;」で区切って複数のSQLを実行させる場合、そのふたつは同期処理なのでしょうか?

また、2つのSQL文を両方実行する方法が、これくらいしか見つけきれなかったのでこうしたのですが、他に良い方法があれば教えていただければ幸いです。

よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

複数のSQLを一連の操作(1つの塊)として扱いたい場合、トランザクションを用いるのが良いかと思います。

  1. トランザクション開始
  2. SQL実行
  3. SQL実行
  4. コミット(またはロールバック)

トランザクション開始以降のSQL実行は、「4. コミット」されることで実際に結果が確定されます。
(「ロールバック」するとなかったことにされる)

コメントを受けての追記 4/23

質問の意図を読み違えて、混乱させてしまったかもしれません。

挙動としては、削除が完全に終わってから挿入する事を想定しています。
今現在、これを実行すると正しく動作しているように思えるのですが、レコード量が膨大になるとまた違うものなのでしょうか?

この点については、SQLは順番に実行されるのでDELETE文実行完了後、INSERT文が実行されることになります。
ただし、システム開発においてはエラー時の処理も考慮し、SELECT文以外のSQL実行時にはトランザクションを利用することが多いかと思います。そのため、トランザクションの利用を検討されることをおすすめします。

また、;の利用以外でのSQLの複数実行は以下のように実装できます。
(変数名(sql1,sql2)があまりよろしくないですが、実装イメージとしてご確認ください)
例として、DELETE文とINSERT文が一塊りとなるよう、トランザクションを使っています。

php

1 2// トランザクション開始 3$pdo->beginTransaction(); 4 5try { 6 7 // DELETE実行 8 $sql1 = "DELETE FROM datatable WHERE hoge <= 2" 9 $stmt = $pdo->query($sql1); 10 11 // INSERT実行 12 $sql2 = "INSERT INTO datatable(id,hoge) VALUES(1,3)" 13 $stmt = $pdo->query($sql2); 14 15 // DELETE文とINSERT文が正常に実行できた場合は 16 // コミット 17 $pdo->commit(); 18 19} catch (PDOException $e) { 20 // SQL実行時にエラーが発生した場合は 21 // ロールバック 22 $pdo->rollback(); 23 24 // エラー処理を記述(ログ出力とか、throw e;とか) 25}

投稿2018/04/21 08:08

編集2018/04/23 00:59
takyafumin

総合スコア2335

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

coinbura

2018/04/22 17:54

なるほど。そういう仕組みがあったのですね。 今回は、1つの塊として扱うというより、 削除が完全に終わってから挿入する、ことを想定しているので、 トランザクション開始 SQL実行 コミット(またはロールバック) トランザクション開始 SQL実行 コミット(またはロールバック) という手順にする、ということでいいんですかね?
coinbura

2018/04/25 16:11

なるほど!「;」区切りは同期処理で良かったんですね! そして、サンプルまでありがとうございます!! 無事、トランザクション処理を用いて、目的の動作をするコードを書く事ができました。 とても勉強になりました。 多謝!
takyafumin

2018/04/25 16:35

解決して何よりです。これからも頑張ってください!
guest

0

takyafuminさんの記載のとおり、トランザクションを使うべきです。

トランザクションを理解するにはATMを想像するとわかりやすいかもしれません。
たとえば家族で共有している銀行のカードがあったとして、100万貯金があったとします。
親が20万入金した場合、100万→120万となります。
そのあと子が5万出金した場合、120万→115万となります。

この入金と出金が(トランザクションを使わずに)同時に行われた場合、下記のようなことが起こり得ます。

  1. 親が20万入金する前の準備処理として、システムが100万という残高を読み込む
  2. 子が5万出金する際の準備処理として、システムが100万という残高を読み込む
  3. システムは、親が入金した20万を残高100万に足して、120万とする。
  4. システムは、子が出金した5万を残高100万から減算して95万とする。

正しい残高は115万なのに、95万円となってしまうわけです。
これを防ぐためには、1と3、2と4をそれぞれひとまとまりの処理として割り込みがされないようにする必要があるのですが、
それが行う仕組みがトランザクションになります。

トランザクションはとても複雑なので、本を読んで理解するよりは、実際に自分で実験してみて理解することをおすすめします。

投稿2018/04/21 08:53

py4s-tnk

総合スコア201

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

coinbura

2018/04/22 18:03

丁寧なご説明ありがとうございます。 つまり、「;」で区切って複数のSQLを実行させる場合、その複数の処理は非同期なので、トランザクション処理で割り込みが起こらないようにしなければいけない。ということで良かったでしょうか?
py4s-tnk

2018/04/23 00:20

はい、その通りです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問