为什么 PostgreSQL 不喜欢大写的 table 名称?
Why PostgreSQL does not like UPPERCASE table names?
我最近尝试在 PostgreSQL 中创建一些全大写的 tables。但是,为了查询它们,我需要将 table 名称放在引号“TABLE_NAME”中。有什么办法可以避免这种情况并告诉 postgres 正常使用大写名称吗?
更新
此查询创建一个 table 小写 table_name
create table TABLE_NAME
(
id integer,
name varchar(255)
)
但是,此查询创建了一个 table,名称为大写 "TABLE_NAME"
create table "TABLE_NAME"
(
id integer,
name varchar(255)
)
问题是引号现在是名字的一部分!!
在我的例子中,我没有手动创建 tables,另一个应用程序创建了 table 并且名称是大写字母。当我想通过 Geoserver 使用 CQL 过滤器时,这会导致问题。
如果你希望 postgres 保留关系名称的大小写,请将 table 名称放入双引号中。
Quoting an identifier also makes it case-sensitive, whereas unquoted
names are always folded to lower case. For example, the identifiers
FOO, foo, and "foo" are considered the same by PostgreSQL, but "Foo"
and "FOO" are different from these three and each other. (The folding
of unquoted names to lower case in PostgreSQL is incompatible with the
SQL standard, which says that unquoted names should be folded to upper
case. Thus, foo should be equivalent to "FOO" not "foo" according to
the standard. If you want to write portable applications you are
advised to always quote a particular name or never quote it.)
来自 docs(强调我的)
带引号的示例:
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)
因此,如果您使用引号创建 table,则不应跳过引号查询。但是,如果您跳过引号创建对象,名称将折叠为小写,因此在查询中将使用大写名称 - 这样您 "won't notice" 它。
问题暗示双引号在用于强制 PostgreSQL 识别标识符名称的大小写时实际上成为标识符名称的一部分。那是不正确的。实际情况是,如果您使用双引号来强制使用大小写,那么您必须始终使用双引号来引用该标识符。
背景:
在 PostgreSQL 中,标识符名称总是折叠成小写,除非您用双引号将标识符名称括起来。这可能会导致混淆。
考虑一下如果您 运行 这两个语句依次出现会发生什么:
CREATE TABLE my_table (
t_id serial,
some_value text
);
这将创建一个名为 my_table
的 table。
现在,尝试 运行 这个:
CREATE TABLE My_Table (
t_id serial,
some_value text
);
PostgreSQL 忽略大写(因为 table 名称没有被引号包围)并尝试创建另一个 table 称为 my_table
。当发生这种情况时,它会抛出一个错误:
ERROR: relation "my_table" already exists
要用大写字母制作 table,您必须 运行:
CREATE TABLE "My_Table" (
t_id serial,
some_value text
);
现在您的数据库中有两个 table:
Schema | Name | Type | Owner
--------+---------------------------+-------+----------
public | My_Table | table | postgres
public | my_table | table | postgres
访问 My_Table
的唯一方法是用双引号将标识符名称括起来,如:
SELECT * FROM "My_Table"
如果您将标识符不加引号,PostgreSQL 会将其折叠为小写并查询 my_table
.
简单来说,Postgres 将(双引号)""
中的数据区分大小写。并保持小写。
示例:我们可以创建名称为 DETAILS 和 details 的 2 列,并在查询时:
select "DETAILS"
return DETAILS
列数据和
select details/DETAILS/Details/"details"
returns 详细列数据。
我最近尝试在 PostgreSQL 中创建一些全大写的 tables。但是,为了查询它们,我需要将 table 名称放在引号“TABLE_NAME”中。有什么办法可以避免这种情况并告诉 postgres 正常使用大写名称吗?
更新
此查询创建一个 table 小写 table_name
create table TABLE_NAME
(
id integer,
name varchar(255)
)
但是,此查询创建了一个 table,名称为大写 "TABLE_NAME"
create table "TABLE_NAME"
(
id integer,
name varchar(255)
)
问题是引号现在是名字的一部分!! 在我的例子中,我没有手动创建 tables,另一个应用程序创建了 table 并且名称是大写字母。当我想通过 Geoserver 使用 CQL 过滤器时,这会导致问题。
如果你希望 postgres 保留关系名称的大小写,请将 table 名称放入双引号中。
Quoting an identifier also makes it case-sensitive, whereas unquoted names are always folded to lower case. For example, the identifiers FOO, foo, and "foo" are considered the same by PostgreSQL, but "Foo" and "FOO" are different from these three and each other. (The folding of unquoted names to lower case in PostgreSQL is incompatible with the SQL standard, which says that unquoted names should be folded to upper case. Thus, foo should be equivalent to "FOO" not "foo" according to the standard. If you want to write portable applications you are advised to always quote a particular name or never quote it.)
来自 docs(强调我的)
带引号的示例:
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)
因此,如果您使用引号创建 table,则不应跳过引号查询。但是,如果您跳过引号创建对象,名称将折叠为小写,因此在查询中将使用大写名称 - 这样您 "won't notice" 它。
问题暗示双引号在用于强制 PostgreSQL 识别标识符名称的大小写时实际上成为标识符名称的一部分。那是不正确的。实际情况是,如果您使用双引号来强制使用大小写,那么您必须始终使用双引号来引用该标识符。
背景:
在 PostgreSQL 中,标识符名称总是折叠成小写,除非您用双引号将标识符名称括起来。这可能会导致混淆。
考虑一下如果您 运行 这两个语句依次出现会发生什么:
CREATE TABLE my_table (
t_id serial,
some_value text
);
这将创建一个名为 my_table
的 table。
现在,尝试 运行 这个:
CREATE TABLE My_Table (
t_id serial,
some_value text
);
PostgreSQL 忽略大写(因为 table 名称没有被引号包围)并尝试创建另一个 table 称为 my_table
。当发生这种情况时,它会抛出一个错误:
ERROR: relation "my_table" already exists
要用大写字母制作 table,您必须 运行:
CREATE TABLE "My_Table" (
t_id serial,
some_value text
);
现在您的数据库中有两个 table:
Schema | Name | Type | Owner
--------+---------------------------+-------+----------
public | My_Table | table | postgres
public | my_table | table | postgres
访问 My_Table
的唯一方法是用双引号将标识符名称括起来,如:
SELECT * FROM "My_Table"
如果您将标识符不加引号,PostgreSQL 会将其折叠为小写并查询 my_table
.
简单来说,Postgres 将(双引号)""
中的数据区分大小写。并保持小写。
示例:我们可以创建名称为 DETAILS 和 details 的 2 列,并在查询时:
select "DETAILS"
return DETAILS
列数据和
select details/DETAILS/Details/"details"
returns 详细列数据。