为啥 PostgreSQL 不喜欢大写的表名?

Posted

技术标签:

【中文标题】为啥 PostgreSQL 不喜欢大写的表名?【英文标题】:Why PostgreSQL does not like UPPERCASE table names?为什么 PostgreSQL 不喜欢大写的表名? 【发布时间】:2017-08-24 00:46:27 【问题描述】:

我最近尝试在 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 过滤器时,这会导致问题。

【问题讨论】:

请向我们展示您的CREATE TABLE声明。 postgresql.org/docs/current/static/… ***.com/questions/6311096/…HTH 有一个很好的答案和解释 【参考方案1】:

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

引用标识符也使其区分大小写,而 不加引号 名称总是折叠成小写。例如,标识符 PostgreSQL 认为 FOO、foo 和 "foo" 相同,但 "Foo" 和“FOO”与这三个和彼此不同。 (折叠 在 PostgreSQL 中将不带引号的名称转换为小写与 SQL 标准,它说不带引号的名称应该折叠到大写 案子。因此,foo 应该等价于 "FOO" 而不是 "foo" 根据 标准。如果你想编写可移植的应用程序,你是 建议总是引用特定名称或从不引用它。)

来自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)

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

【讨论】:

你没有完全解释清楚。因此,当他使用大写创建时,它卡住了,但是当他使用大写查询时,它变成了小写并且不起作用。对吗? 我引用了文档 - 他们说“建议您始终引用特定名称或永远不要引用它。”我相信这意味着“当您创建不带引号的表时,无论如何您都可以选择不带引号的表。如果您使用引号创建,则在查询时使用引号”。还是你说的不一样? 但是OP不应该能够使用大写或小写访问他的表吗?我想他一定是用引号创建了表格,不是吗? 带引号 - 他应该。我相信他可以访问,但不喜欢他需要在表名周围加上引号并询问他是否可以跳过引号,只使用大写。 天哪,我喜欢这个网站。在这之后我终于可以睡觉了,哈哈。谢谢!【参考方案2】:

这个问题暗示双引号,当用于强制 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

【讨论】:

【参考方案3】:

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

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

select "DETAILS" 

返回DETAILS列数据和

select details/DETAILS/Details/"details"

返回详细信息列数据。

【讨论】:

这基本上意味着 postgres 中的所有查询都默认转换为小写字母。但是,如果你想创建一个大写字母的列,那么你必须在“”中指定它。而获取大写Column(DETAILS)的数据,需要在(双引号)""中指定列名。因此 postgres 将引号中的数据视为区分大小写并给出预期的列(DETAILS)值。

以上是关于为啥 PostgreSQL 不喜欢大写的表名?的主要内容,如果未能解决你的问题,请参考以下文章

postgreSQL 创建user表时引发的表名大写与双引号问题

PostgreSQL字段名和表名大小写的问题

PostgreSQL COPY 命令中动态生成的表名

为啥 MariaDB 不接受我的字符串变量作为我的 sql 查询中的表名?

如何在 PostgreSQL 中仅获取数据库的表名

Windows 中的 MySQL 小写表名 Unix 上的大写名称