1. ホーム
  2. mysql

[解決済み] セーフモードでのmysqlの削除

2022-11-29 15:29:11

質問

私は講師のテーブルを持っており、私は範囲内の給与を持っているレコードを削除したい。 直感的な方法は次のようなものです。

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. セーフモードで動作させるには、このコードをどのように書き直せばよいのでしょうか。

ありがとうございます。

どのように解決するのですか?

ググってみると、一般的な回答は以下のようです。 セーフ モードをオフにするだけです。 :

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

正直に言うと、私はこれまでセーフモードで実行する習慣があったとは言えません。それでも、この回答は、問題に遭遇するたびにデータベースの設定を変更する必要があると仮定しているだけなので、完全に安心できるわけではありません。

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のデモ .