Psycopg2 不喜欢以小写字母开头的表名

9 投票
3 回答
13559 浏览
提问于 2025-04-15 22:23

我在Windows XP上运行ActiveState的ActivePython 2.6.5.12和PostgreSQL 9.0 Beta 1。

当我创建一个表名首字母大写(比如说Books)时,使用psycopg2执行查询语句execute("SELECT * FROM Books")时,会出现“编程错误:关系"books"不存在”的错误信息。如果我执行execute("SELECT * FROM books"),也会出现同样的错误。不过,如果我把表名改成首字母小写(比如说books),那么上面的任意一个查询语句都能正常工作。

表名是不是应该首字母小写?这是一个设置、特性还是bug?我是不是漏掉了什么明显的东西?

3 个回答

4

我经常需要使用Psycopg2来处理一些别人创建的表,这些表的列名有很多大小写混合的情况。

我找到的解决办法是使用

from psycopg2.extensions import AsIs

然后把列名放到一个变量里,比如:

column_name = '"Column_Mixed_Case"'#Mind the '" quotes combination !

接着把这个变量传递给SQL,像这样:

data = AsIs(column_name)
sql = "select %s from table"
cur.execute(sql,data)
11

补充一下其他回答,PostgreSQL在处理标识符(比如表名和列名)时的大小写敏感性行为是这样的:

  • 如果名字没有加引号,它会被转换成小写。如果加了引号,就不会改变。
  • 然后,会尝试进行大小写敏感的匹配

这个规则不仅适用于查询,也适用于模式操作,特别是创建表的时候。

黄金法则是保持一致性

如果你想写可移植的应用程序,建议你要么总是加引号,要么从不加引号。

出现的问题,可能是因为在创建表和列的时候加了引号(所以它们没有被转换成小写)。因此,现在在所有查询中都必须加引号(并且要区分大小写)。

通常情况下,一切都按预期工作。

db=# create table Xxx (id integer); -- unquoted, will be converted to lowercase
CREATE TABLE
db=# select * from xXx;    -- this works ok
id
----
(0 rows)
db=# create table "Xxxx" (id integer);  -- will be left untouched
CREATE TABLE
db=# select * from xxxx;                -- bad
ERROR:  relation "xxxx" does not exist
LINE 1: select * from xxxx;
db=# select * from Xxxx;                -- bad
ERROR:  relation "xxxx" does not exist
LINE 1: select * from Xxxx;
^
db=# select * from "Xxxx";               -- ok
id
----
(0 rows)

db=# \dt *xx*
List of relations
Schema | Name | Type  |  Owner
--------+------+-------+----------
public | Xxxx | table | postgres
public | xxx  | table | postgres
9

请阅读“标识符和关键字”这部分手册,特别是关于“带引号的标识符”的内容。

撰写回答