LoginSignup
0
0

More than 1 year has passed since last update.

MySQLではDELETEやUPDATE文のサブクエリで更新対象のテーブルを指定できない

Last updated at Posted at 2021-08-13

例題

以下のテーブルのうち、

コード 日付
1 20210801
1 20210802
2 20210701
2 20210702
3 20210801
3 20210802
3 20210803
4 20210601

UPDATEのケース:コード内で日付が最大のレコード以外の日付を0に更新する
DELETEのケース:コード内で日付が最大のレコード以外のレコードを削除する
以上の条件で更新の対象となるレコードは以下の通り

コード 日付 対象
1 20210801
1 20210802
2 20210701
2 20210702
3 20210801
3 20210802
3 20210803
4 20210601

スキーマ

CREATE TABLE `テーブル`
    (`コード` int, `日付` int);

INSERT INTO `テーブル`
VALUES
    (1, 20210801),
    (1, 20210802),
    (2, 20210701),
    (2, 20210702),
    (3, 20210801),
    (3, 20210802),
    (3, 20210803),
    (4, 20210601);

対象レコードを抽出するSELECT文

SELECT *
FROM テーブル AS Z
WHERE 日付 < (SELECT MAX(日付)
              FROM テーブル AS A
              WHERE A.コード = Z.コード
              )
コード 日付
1 20210801
2 20210701
3 20210801
3 20210802

一般的なSQLの構文

UPDATE文

UPDATE テーブル AS Z
SET 日付 = 0
WHERE 日付 < (SELECT MAX(日付)
              FROM テーブル AS A
              WHERE A.コード = Z.コード
              );

DELETE文

DELETE
FROM テーブル AS Z
WHERE 日付 < (SELECT MAX(日付)
              FROM テーブル AS A
              WHERE A.コード = Z.コード
              );

上記はMySQLでは以下のエラーとなります
You can't specify target table 'Z' for update in FROM clause
DeepLで翻訳すると
FROM句で更新対象のテーブル'Z'を指定できない

MySQLでの対処方法

サブクエリ部分を1階層深くして、更新文のFROM句で指定したテーブルをサブクエリで直接参照しないようにします

UPDATE文

UPDATE テーブル AS Z
SET 日付 = 0
WHERE (コード,日付) IN(SELECT *
                      FROM (SELECT コード, 日付
                            FROM テーブル AS Z
                            WHERE 日付 < (SELECT MAX(日付)
                                          FROM テーブル AS A
                                          WHERE A.コード = Z.コード
                                         )
                           ) SUB
                      );

DELETE文

DELETE 
FROM テーブル
WHERE (コード,日付) IN(SELECT *
                      FROM (SELECT コード, 日付
                            FROM テーブル AS Z
                            WHERE 日付 < (SELECT MAX(日付)
                                          FROM テーブル AS A
                                          WHERE A.コード = Z.コード
                                         )
                           ) SUB
                     );
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0