39

我最近尝试在 PostgreSQL 中以大写名称创建一些表。但是,为了查询它们,我需要将表名放在引号“TABLE_NAME”中。有什么办法可以避免这种情况并告诉 postgres 正常使用大写名称?

更新

此查询使用小写的table_name创建一个表

create table TABLE_NAME 
(
id integer,
name varchar(255)
)

但是,此查询会创建一个具有大写名称“TABLE_NAME”的表

create table "TABLE_NAME"
(
id integer,
name varchar(255)
)

问题是引号现在是名称的一部分!在我的情况下,我不手动创建表,另一个应用程序创建表并且名称是大写字母。当我想通过 Geoserver使用CQL过滤器时,这会导致问题。

4

3 回答 3

50

如果您希望 postgres 保留关系名称的大小写,请将表名放在双引号中。

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

来自文档(强调我的)

引用示例:

t=# create table "UC_TNAME" (i int);
CREATE TABLE
t=# \dt+ UC

t=# \dt+ "UC_TNAME"
                      List of relations
 Schema |   Name   | Type  |  Owner   |  Size   | Description
--------+----------+-------+----------+---------+-------------
 public | UC_TNAME | table | postgres | 0 bytes |
(1 row)

不引用的例子:

t=# create table UC_TNAME (i int);
CREATE TABLE
t=# \dt+ UC_TNAME
                      List of relations
 Schema |   Name   | Type  |  Owner   |  Size   | Description
--------+----------+-------+----------+---------+-------------
 public | uc_tname | table | postgres | 0 bytes |
(1 row)

因此,如果您使用引号创建表,则不应跳过引号查询它。但是,如果您跳过创建对象的引号,则名称将折叠为小写,因此在查询中将使用大写名称 - 这样您“不会注意到”它。

于 2017-03-30T08:13:41.287 回答
13

这个问题意味着双引号,当用于强制 PostgreSQL 识别标识符名称的大小写时,实际上成为标识符名称的一部分。这是不正确的。确实发生的情况是,如果您使用双引号强制大小写,那么您必须始终使用双引号来引用该标识符。

背景:

在 PostgreSQL 中,标识符的名称总是折叠为小写,除非您用双引号将标识符名称括起来。这可能会导致混乱。

考虑一下如果按顺序运行这两个语句会发生什么:

CREATE TABLE my_table (
    t_id serial,
    some_value text
);

这将创建一个名为my_table.

现在,尝试运行:

CREATE TABLE My_Table (
    t_id serial,
    some_value text
);

PostgreSQL 忽略大写(因为表名没有被引号包围)并尝试创建另一个名为my_table. 发生这种情况时,它会引发错误:

ERROR:  relation "my_table" already exists

要使用大写字母制作表格,您必须运行:

CREATE TABLE "My_Table" (
    t_id serial,
    some_value text
);

现在您的数据库中有两个表:

 Schema |           Name            | Type  |  Owner   
--------+---------------------------+-------+----------
 public | My_Table                  | table | postgres
 public | my_table                  | table | postgres

唯一的访问方法My_Table是用双引号将标识符名称括起来,如下所示:

SELECT * FROM "My_Table"

如果您不加引号,那么 PostgreSQL 会将其折叠为小写并查询my_table

于 2017-03-30T12:28:44.790 回答
2

简单来说,Postgres 将(双引号)中的数据""视为区分大小写。并保留为小写。

示例:我们可以在查询时创建名称为 DETAILS 和 details 的 2 列:

select "DETAILS" 

返回DETAILS列数据和

select details/DETAILS/Details/"details"

返回详细信息列数据。

于 2018-10-29T05:29:05.357 回答