Postgresql中的奇怪行为

时间:2012-01-05 00:11:43

标签: postgresql quoted-identifier

我是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 个答案:

答案 0 :(得分:13)

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

new.last_update = current_timestamp;

但它应该使用new."Last_Update"所以修复你的触发器功能。

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

  

引用标识符也会使其区分大小写,而不带引号的名称始终折叠为小写。例如,PostgreSQL认为标识符FOO,foo和“foo”是相同的,但是“Foo”和“FOO”与这三个和彼此不同。 (在PostgreSQL中将不带引号的名称折叠为小写与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),而不是让你成为朋友。