使用表别名更新请求

jus*_*ing 16 postgresql update

执行这个请求:

update table t1 set t1.column = 0 where t1.column2 = 1234
Run Code Online (Sandbox Code Playgroud)

收到此错误:

关系“表”的“t1”列不存在

这个请求在 MySQL 中运行良好。
为什么我会在 PostgreSQL 中收到此错误?

Eva*_*oll 14

我不确定这是否是您想要的语法。检查你的语法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 ] [, ...] ]
Run Code Online (Sandbox Code Playgroud)

因此,如果您提供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);
Run Code Online (Sandbox Code Playgroud)

现在我们可以尝试您的原始查询并获得您的原始结果,

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;
Run Code Online (Sandbox Code Playgroud)

这就是你遇到的问题。与表一样,如果要使用 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;
Run Code Online (Sandbox Code Playgroud)

除此之外,似乎SET list 中不支持表别名,无论该列是否为保留关键字。

UPDATE "table" t1 SET "column"=0 WHERE t1.column2=1234;
Run Code Online (Sandbox Code Playgroud)

为什么它目前按设计工作

为什么你不能使用别名,来自 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;
Run Code Online (Sandbox Code Playgroud)

所以允许的语法.是 is mycol.type-address, not 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;
Run Code Online (Sandbox Code Playgroud)

什么是mycol.x参考呢?由于它没有歧义,表引用和表别名被禁用,因此它绝对是 100% 的时间mycol在 table 上命名为,的复合类型mytable

  • @justesting 请。MySQL 在实现 SQL 的方式上有更多的怪异之处。 (2认同)

ype*_*eᵀᴹ 10

这是 Postgres 的奇怪之处。如 的文档中所述UPDATE,表名不应用于目标列。

column_name

由 命名的表中列的名称table_name。如果需要,可以使用子字段名称或数组下标来限定列名称。不要在目标列的规范中包含表的名称- 例如,UPDATE table_name SET table_name.col = 1无效。

一个UPDATE子句中只能更新一张表,因此没有对语句进行误解的余地。