web-dev-qa-db-ja.com

テーブルエイリアスを使用した更新リクエスト

このリクエストを実行する:

update table t1 set t1.column = 0 where t1.column2 = 1234

このエラーを取得する:

リレーション「テーブル」の列「t1」は存在しません

このリクエストはMySQLで正常に実行されます。
なぜPostgreSQLでこのエラーが発生するのですか?

12
justesting

それがあなたの望む構文かどうかはわかりません。 構文でUPDATE を確認します

現在、それは

[ WITH [ RECURSIVE ] with_query [, ...] ]
UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ]
    SET { column_name = { expression | DEFAULT } |
          ( column_name [, ...] ) = ( { expression | DEFAULT } [, ...] ) |
          ( column_name [, ...] ) = ( sub-SELECT )
        } [, ...]
    [ FROM from_list ]
    [ WHERE condition | WHERE CURRENT OF cursor_name ]
    [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

したがって、table t1を指定すると、tableという名前のテーブルとして解析されます。実際には、それを行うには引用符"table" t1で囲む必要があります。

  • 設計上の注意として、しないでください。実際には、 SQLキーワード は何も指定しないでください。
  • しかし、あなたが楽しみを持ち、何が起こっているのかを見たい場合は、私たちがプレイできます。

テキストデータを作成してみましょう

CREATE TABLE "table" AS
SELECT x AS column, x AS column2
FROM generate_series(1,12345) AS t(x);

これで、元のクエリを試し、元の結果を取得できます。

UPDATE "table" t1 SET t1.column=0 WHERE t1.column2=1234;
ERROR:  column "t1" of relation "table" does not exist
LINE 1: UPDATE "table" t1 SET t1.column=0 WHERE t1.column2=1234;

そして、それはあなたが得ている問題です。テーブルと同様に、SQLキーワードを使用する場合は、引用符で囲む必要があります。興味深いことに、ここではそれだけでは不十分です。

UPDATE "table" t1 SET t1."column"=0 WHERE t1.column2=1234;
ERROR:  column "t1" of relation "table" does not exist
LINE 1: UPDATE "table" t1 SET t1."column"=0 WHERE t1.column2=1234;

さらに、列が予約済みキーワードであるかどうかに関係なく、テーブルのエイリアスはSETリストではサポートされませんのようです。

UPDATE "table" t1 SET "column"=0 WHERE t1.column2=1234;

現在の理由設計どおりの動作

なぜエイリアスを使用できないのですか、IRCのxocolatlが役立ちます。

<xocolatl> EvanCarroll:=の左側にあるエイリアスを使用できない理由は複合型のためにです

<xocolatl> EvanCarroll:バグではなくWADです

したがって、カスタムの複合型を持つテーブルをCREATEするコードでは、UPDATEを実行します。

CREATE TYPE foo AS ( x int, y int );

CREATE TABLE foobar AS
  SELECT v::foo AS mycol
  FROM ( VALUES (1,2), (2,100) ) AS v;

UPDATE foobar SET mycol.x = 9;

したがって、.を許可する構文はmycol.type-addressであり、tablealias.col-nameではありません。

あいまいな構文問題の解決

それが意味をなさない場合、この動作以外の動作はあいまいな構文を与えるでしょう。

CREATE TYPE foo AS ( mycol int, x int );

CREATE TABLE mytable AS
  SELECT v::foo AS mycol, 1 AS x
  FROM ( VALUES (1,2), (2,100) ) AS v;

UPDATE mytable AS mycol SET mycol.x = 9;

mycol.xは何を指しますか? notがあいまいなため、テーブル参照とテーブルエイリアスは無効になっているため、mycolという名前の複合型は、テーブルmytableで常に100%の時間です。

9
Evan Carroll

それはPostgresの奇妙さです。 UPDATE のドキュメントに記載されているように、テーブル名はターゲット列に使用しないでください。

column_name

table_nameという名前のテーブルの列の名前。列名は、必要に応じて、サブフィールド名または配列添え字で修飾できます。 ターゲット列の指定にテーブルの名前を含めないでください—たとえば、UPDATE table_name SET table_name.col = 1は無効

UPDATE句で更新できるテーブルは1つだけなので、ステートメントを誤って解釈する余地はありません。

7
ypercubeᵀᴹ