セーフモードでのmysqlの削除


92

テーブルインストラクターがいて、給与が範囲内にあるレコードを削除したい直感的な方法は次のとおりです。

delete from instructor where salary between 13000 and 15000;

ただし、セーフモードでは、主キー(ID)を指定せずにレコードを削除することはできません。

だから私は次のSQLを書きます:

delete from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

ただし、エラーがあります。

You can't specify target table 'instructor' for update in FROM clause

私が書くとき私は混乱しています

select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

エラーは発生しません。

私の質問は:

  1. このエラーメッセージは実際には何を意味し、なぜ私のコードが間違っているのですか?
  2. このコードを書き直してセーフモードで動作させる方法は?

ありがとう!


セーフモードをオンのままにしますか?そして、mySqlワークベンチを使用していますか?
wribit 2014

あなたの両方の質問に対する答えはイエスです。また、jdbcを使用してPKなしでmysqlデータベースのレコードを削除しても、エラーが発生しないことに驚いています。では、セーフモードはmysqlワークベンチ専用ですか?
roland luo 2014

1
いいえ-mySQLワークベンチでオフにしたい場合は、その方法を説明できたので、私は尋ねていました。個人的に私はそれをオフにして作業します... IDを持っている必要があることは安全性の面で非常に優れています-しかし開発の面では、それは苦痛であることがわかりました
wribit 2014

回答:


233

ぐるぐる回って、人気のある答えは「セーフモードをオフにするだけ」のようです

SET SQL_SAFE_UPDATES = 0;
DELETE FROM instructor WHERE salary BETWEEN 13000 AND 15000;
SET SQL_SAFE_UPDATES = 1;

正直なところ、セーフモードで走る習慣をつけたことはありません。それでも、問題が発生するたびにデータベース構成を変更する必要があると想定しているため、この回答に完全に満足しているわけではありません。

したがって、2番目のクエリはマークに近づきますが、別の問題が発生します。MySQLはサブクエリにいくつかの制限を適用し、その1つは、サブクエリでテーブルから選択しているときにテーブルを変更できないことです。

MySQLマニュアルからの引用、サブクエリの制限

通常、テーブルを変更して、サブクエリで同じテーブルから選択することはできません。たとえば、この制限は次の形式のステートメントに適用されます。

DELETE FROM t WHERE ... (SELECT ... FROM t ...);
UPDATE t ... WHERE col = (SELECT ... FROM t ...);
{INSERT|REPLACE} INTO t (SELECT ... FROM t ...);

例外:FROM句で変更されたテーブルのサブクエリを使用している場合、前述の禁止事項は適用されません。例:

UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);

ここでは、FROM句のサブクエリの結果が一時テーブルとして格納されているため、tの更新が行われるまでに、tの関連する行がすでに選択されています。

その最後のビットがあなたの答えです。一時テーブルでターゲットIDを選択し、そのテーブルのIDを参照して削除します。

DELETE FROM instructor WHERE id IN (
  SELECT temp.id FROM (
    SELECT id FROM instructor WHERE salary BETWEEN 13000 AND 15000
  ) AS temp
);

SQLFiddleデモ


6
説明ありがとうございます!ただし、mysqlワークベンチでコードを試しましたが、「安全な更新モードを使用していて、KEY列を使用するWHEREなしでテーブルを更新しようとしました」と表示されます。
roland luo 2014

それは予想外です。主キーは別の名前ですか?ID私の答えはを使用していますが、あなたの質問は名前が付けられていることを示しているようidです。
2014

はい、IDに変更しましたが動作しません。ID = '1'のインストラクターから削除しようとしましたが、IDが主キーになるように機能します
roland luo 2014

1
@rolandluo久しぶりですが、回避策を見つけていただければと思います。明らかにこの方法は他の状況でも機能したので、なぜあなたのケースが違うのだろうか。サーバーやバージョンに固有の何か、おそらく?
2015

19

MySQLをだまして、実際に主キー列を指定していると思わせることができます。これにより、セーフモードを「上書き」できます。

自動インクリメントの数値主キーを備えたテーブルがあるとすると、次のことができます。

DELETE FROM tbl WHERE id <> 0

12

Mysqlワークベンチ6.3.4.0でセーフモードをオフにする

[編集]メニュー=> [設定] => [SQLエディター]:その他のセクション:[安全な更新]をクリックして...オプションのチェックを外します

ワークベンチ設定


2
「このコードを書き直してセーフモードで動作させるにはどうすればよいですか?」==>あなたの答えはセーフモードを無効にする方法を教えてくれます;)
ByteHamster 2016

2
申し訳ありませんが、私はその質問を完全に誤解しました。Mysqlワークベンチを使用してテーブルから削除できなかったときにこのトピックを見つけました。mysqlワークベンチを使用したコメントにも同様の質問がありましたが、コメントを作成できません。私は...それは、将来の参考のためにここにこれを書くには良い場所だと、思った
ピーター・B

0

私にははるかに簡単な解決策があります、それは私のために働いています。これも回避策ですが、使用できる可能性があり、設定を変更する必要はありません。決して存在しない値を使用できると思います。それをWHERE句で使用します。

MyTableから削除WHEREMyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

私もその解決策があまり好きではないので、私はここにいますが、それは機能し、それが答えられたものよりも優れているようです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.