MySQL エラー 1093: FROM 句で更新対象テーブルを指定できない - 原因と解決方法

2024-04-04

エラー 1093: FROM 句で更新対象テーブルを指定できない - 詳細解説

MySQL で UPDATE クエリを実行時に、FROM 句で指定したテーブルを更新しようとすると、エラー 1093 "Can't specify target table for update in FROM clause" が発生します。これは、サブクエリを使用するなど、いくつかの状況で起こり得ます。

原因

このエラーは、以下のいずれかの理由で発生します。

  • サブクエリで更新対象テーブルを参照: サブクエリで更新対象テーブルを参照する場合、MySQL は更新対象テーブルをロックできません。
  • JOIN と UPDATE の組み合わせ: JOINUPDATE を組み合わせる場合、FROM 句で指定されたすべてのテーブルが更新対象となります。
  • 一時テーブルの使用: 一時テーブルを更新しようとすると、エラーが発生します。

解決方法

このエラーを解決するには、以下の方法があります。

サブクエリを使用せずに、UPDATE クエリを直接実行します。

例:

# サブクエリを使用する
UPDATE users
SET email = (SELECT email FROM other_table WHERE id = 1)
WHERE id = 2;

# サブクエリを使用しない
UPDATE users
SET email = '[email protected]'
WHERE id = 2;

JOINUPDATE を組み合わせる場合は、UPDATE 句で更新対象テーブルを明示的に指定します。

# 間違った例
UPDATE users
JOIN other_table ON users.id = other_table.user_id
SET users.email = '[email protected]'
WHERE other_table.id = 1;

# 正しい例
UPDATE users
SET email = '[email protected]'
WHERE users.id IN (SELECT user_id FROM other_table WHERE id = 1);
# 一時テーブルを使用する
CREATE TEMPORARY TABLE tmp_users AS
SELECT * FROM users;

UPDATE tmp_users
SET email = '[email protected]'
WHERE id = 2;

# 一時テーブルを使用しない
UPDATE users
SET email = '[email protected]'
WHERE id = 2;

その他の解決方法

上記の方法で解決できない場合は、以下の方法も検討できます。

  • ALIAS を使用して、サブクエリで更新対象テーブルに別名を付ける。
  • UPDATE クエリを複数に分けて実行する。
  • ストアドプロシージャを使用する。

補足

  • このエラーは、MySQL だけでなく、他のデータベースでも発生する可能性があります。
  • エラーメッセージの詳細を確認することで、エラーの原因を特定しやすくなります。

この情報は参考情報として提供されており、特定の状況に対する専門的なアドバイスとして解釈されるべきではありません。




サブクエリを使用しない

# users テーブルの email カラムを更新

UPDATE users
SET email = '[email protected]'
WHERE id = 2;

JOIN と UPDATE を適切に組み合わせる

# users テーブルの email カラムを、other_table の id カラムに基づいて更新

UPDATE users
SET email = other_table.email
FROM users
JOIN other_table ON users.id = other_table.user_id
WHERE other_table.id = 1;

一時テーブルを使用しない

# users テーブルの email カラムを更新

UPDATE users
SET email = '[email protected]'
WHERE id = 2;
# users テーブルの email カラムを更新

UPDATE users u
SET email = (SELECT email FROM other_table WHERE id = 1)
WHERE u.id = 2;
# users テーブルの email カラムを更新

# 1. users テーブルの id 2 のレコードを取得
SELECT * FROM users WHERE id = 2;

# 2. 取得したレコードの email カラムを更新
UPDATE users
SET email = '[email protected]'
WHERE id = 2;
# ストアドプロシージャを作成

DELIMITER //

CREATE PROCEDURE update_user_email(
  IN user_id INT,
  IN new_email VARCHAR(255)
)
BEGIN
  UPDATE users
  SET email = new_email
  WHERE id = user_id;
END //

DELIMITER ;

# ストアドプロシージャを実行

CALL update_user_email(2, '[email protected]');
  • このサンプルコードは、あくまでも参考情報として提供されています。
  • 実際のコードは、ご自身の環境に合わせて変更する必要があります。



エラー 1093: FROM 句で更新対象テーブルを指定できない - その他の方法

WITH 句を使用すると、サブクエリを CTE (Common Table Expression) として定義し、その CTE を UPDATE クエリで参照できます。

WITH t AS (
  SELECT * FROM users
)
UPDATE t
SET email = '[email protected]'
WHERE id = 2;

LATERAL JOIN は、サブクエリを FROM 句ではなく JOIN 句で使用できる機能です。

UPDATE users
SET email = t.email
FROM users
LATERAL JOIN (
  SELECT email FROM other_table WHERE id = 1
) t;

CASE 式を使用すると、条件に応じて異なる値を更新できます。

UPDATE users
SET email = CASE WHEN id = 1 THEN '[email protected]'
                 WHEN id = 2 THEN '[email protected]'
                 ELSE email
                 END
WHERE id IN (1, 2);

UPDATE トリガーを使用すると、UPDATE クエリが実行される前に、自動的に別のテーブルを更新できます。

CREATE TRIGGER update_user_email
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
  UPDATE other_table
  SET email = NEW.email
  WHERE user_id = OLD.id;
END;
  • 上記の方法は、状況によっては有効な解決策となる可能性があります。

mysql subquery sql-delete


DROP TABLEステートメントとCREATE TABLEステートメント

MySQLでは、ALTER TABLEステートメントを使用して、既存のテーブルから列を削除することができます。この操作は、テーブル構造を変更するDDL(Data Definition Language)操作の一つです。手順以下の手順で、ALTER TABLEを使って存在する列を削除することができます。...


MySQL JOINチュートリアル:1つのテーブルからすべての列、別のテーブルからいくつかの列を選択

このチュートリアルでは、MySQLの SELECT ステートメントと JOIN 句を使用して、1つのテーブルからすべての列を選択し、別のテーブルからいくつかの列を選択する方法を説明します。前提条件MySQLデータベースサーバーとクライアントツール...


MySQL: すべてのフィールドにインデックスを作成しない理由と、高速化するためのその他の方法

インデックス作成・更新のコスト:インデックスの作成には時間がかかり、ストレージ領域も消費されます。データ更新のたびにインデックスも更新する必要があり、処理速度が低下します。特に更新頻度の高いテーブルの場合、インデックスによる影響が顕著になります。...


MariaDBにおけるセッション変数とグローバル変数の詳細解説:mysql、mariadb、haproxy関連

MariaDBでは、セッション変数とグローバル変数の2種類のシステム変数が存在します。それぞれ異なるスコープを持ち、MariaDBの動作に影響を与えます。本記事では、**「mysql」「mariadb」「haproxy」**に関連する文脈において、セッション変数とグローバル変数の違いを分かりやすく解説します。...


【保存版】MySQL/MariaDBテーブルの主キー設定:追加、変更、削除の全手順

主キーを追加するタイミングテーブル作成後: この場合も、多くの場合で主キーはクラスタ化インデックスになりますが、以下の例外が発生する可能性があります。既存のインデックスと競合する場合: 既存のインデックスがテーブルのデータと同じ順序で並んでいる場合、新しい主キーはクラスタ化インデックスにならず、非クラスタ化インデックスになる可能性があります。innodb_file_per_table テーブルオプションが有効な場合: このオプションが有効な場合、テーブルは個々のファイルに保存され、主キーは必ずしもクラスタ化インデックスとはなりません。...


SQL SQL SQL SQL Amazon で見る



MySQL エラー 1093: FROM 句で更新のターゲット テーブルを指定できません

このエラーは、MySQL で UPDATE 文を実行時に発生します。原因は、FROM 句で指定されたテーブルと同じテーブルをUPDATE 対象としている場合です。原因:MySQL は、UPDATE 文で FROM 句で指定されたテーブルを直接更新することはできません。これは、更新処理中にデータの整合性が失われる可能性があるためです。