Postgresql 中的奇怪行为

Posted

技术标签:

【中文标题】Postgresql 中的奇怪行为【英文标题】:Strange behaviour in Postgresql 【发布时间】:2012-02-02 21:22:28 【问题描述】:

我是 Postgresql 的新手,我正在尝试从 mysql 迁移我的应用程序。 我有一个具有以下结构的表:

                            Table "public.tbl_point"
          Column         |         Type          | Modifiers | Storage  | Description
 ------------------------+-----------------------+-----------+----------+-------------
  Tag_Id                 | integer               | not null  | plain    |
  Tag_Name               | character varying(30) | not null  | extended |
  Quality                | integer               | not null  | plain    |
  Execute                | integer               | not null  | plain    |
  Output_Index           | integer               | not null  | plain    |
  Last_Update            | abstime               |           | plain    |
Indexes:
"tbl_point_pkey" PRIMARY KEY, btree ("Tag_Id")
Triggers:
add_current_date_to_tbl_point BEFORE UPDATE ON tbl_point FOR EACH ROW EXECUTE PROCEDURE update_tbl_point()
Has OIDs: no

当我使用 libpq 通过 C 程序运行查询时:

UPDATE tbl_point SET "Execute"=0 WHERE "Tag_Id"=0

我得到以下输出:

ERROR:  record "new" has no field "last_update"
CONTEXT:  PL/pgSQL function "update_tbl_point" line 3 at assignment

当我尝试使用 pgAdminIII 更改“执行”或任何其他列的值时,我得到完全相同的错误。

如果我将列名从“Last_Update”更改为“last_update”,一切正常。

我在我的数据库中的其他表中发现了同样的问题,并且该列始终与 abstime 或 timestamp 列一起出现。

【问题讨论】:

【参考方案1】:

您的 update_tbl_point 函数可能正在执行以下操作:

new.last_update = current_timestamp;

但它应该使用new."Last_Update" 所以修复你的触发函数。

列名是 normalized to lower case in PostgreSQL(与 SQL 标准所说的相反),但双引号的标识符保持大小写:

引用标识符也使其区分大小写,而未引用的名称总是折叠为小写。例如,标识符 FOO、foo 和“foo”在 PostgreSQL 中被认为是相同的,但“Foo”和“FOO”与这三个不同并且彼此不同。 (在 PostgreSQL 中将不带引号的名称折叠为小写与 SQL 标准不兼容,SQL 标准说不带引号的名称应折叠为大写。因此,根据标准, foo 应该等效于 "FOO" 而不是 "foo"。如果如果您想编写可移植的应用程序,建议您始终引用特定名称或永远不要引用它。)

所以,如果你这样做:

create table pancakes (
    Eggs integer not null
)

那么您可以执行以下任何操作:

update pancakes set eggs = 11;
update pancakes set Eggs = 11;
update pancakes set EGGS = 11;

它会起作用,因为所有三种形式都标准化为eggs。但是,如果您这样做:

create table pancakes (
    "Eggs" integer not null
)

那么你可以这样做:

update pancakes set "Eggs" = 11;

但不是这个:

update pancakes set eggs = 11;

PostgreSQL 的通常做法是在任何地方都使用小写标识符,这样您就不必担心它。我也建议在其他数据库中使用相同的命名方案,必须引用所有内容只会在 SQL 中留下一堆双引号(标准)、反引号(MySQL)和括号(SQL Server),而这不会结交任何朋友。

【讨论】:

谢谢我的朋友!你的解释是完美的!亚历山德拉。

以上是关于Postgresql 中的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

postgresql,奇怪的 OFFSET/LIMIT 行为(记录顺序)

PostgreSQL 与 array_to_json 的奇怪行为

将一个奇怪的 Mysql 查询更改为使用 group_concat 的 Postgresql

PostgreSQL 中 VALUES 子句的行为

postgres 错误:Postgresql 11.6 中的列不存在错误

Postgresql:如何为postgres中的相同时间戳选择“媒体”列中的最大值?