ことの発端
PostgreSQL 9.6環境で、下記UPDATE文を実行したところ、
UPDATE
table1
SET
table1.column1 = table2.column1
FROM
table2
WHERE
table2.table1_id = table1.id
;
下記エラーが発生した。
Error: ERROR: column "table1" of relation "table1" does not exist
なぜ?
公式リファレンスでSET句の左辺の仕様を読んだところ
table_nameで指名されたテーブル内の列名です。 必要に応じて、列名を副フィールド名や配列の指示子で修飾することも可能です。
対象列の指定にはテーブル名を含めないでください。 たとえば、UPDATE table_name SET table_name.col = 1は無効です。
と書かれており、エイリアスの使用が禁止されていることがわかった。
なるほど、と思いつつ、
- 別にエイリアスを使用したところで処理には影響ないのでは?
- なぜSET句の左辺だけエイリアスの使用が禁止されているのか?
という疑問が残ったので、腹落ちするまで調べてみた。
結論
- エイリアスを使用できる = 任意のテーブル内のカラムを参照できる
- エイリアスを使用できない = 特定のテーブル内のカラムしか参照できない
という解釈で腹落ち。
PostgreSQLのUPDATE文は 同時に複数テーブルを更新できない という制約があるため、SET句の左辺に記述できるカラムは、必然的にUPDATE句で指定したテーブル内のカラムになる。
つまり、特定のテーブル内のカラムしか参照できないため、エイリアスを使用できない制約にしている(のではないか)。
おまけ
MySQLやSQL Serverでも同じ仕様なのか気になり、SET句の左辺でエイリアスを使用してUPDATE文を実行したところ、 正常に更新された。
MySQL 5.7の場合
UPDATE
table1, table2
SET
table1.column1 = table2.column1
WHERE
table2.table1_id = table1.id
;
SQL Server 2017 Standardの場合
UPDATE
table1
SET
table1.column1 = table2.column1
FROM
table2
WHERE
table2.table1_id = table1.id
;
MySQLの場合、UPDATE句に複数テーブルを記述することができるので、「そりゃできるよな」という所感だが、SQL ServerはPostgreSQLと同じUPDATE文なため、少しばかり違和感を覚える。
普段SELECT文を書く際にテーブル名.カラム名で記述しているため、SQL Serverの仕様の方が(個人的には)しっくりくる。
ただ、そもそもUPDATE句で指定したテーブル内のカラムしか更新できないのであれば、 エイリアスの使用を禁止した方が、他テーブルを参照できてしまうという曖昧さを潰せる というメリットもあるなぁ、という気づきも今回の調査で得ることができた。