postgresql psycopg2标识符中的架构名称

x33g5p2x  于 2023-04-05  发布在  PostgreSQL
关注(0)|答案(3)|浏览(107)

我想使用psycopg2的sql子模块来编写干净的动态SQL:

from psycopg2 import sql
...
cursor.execute(sql.SQL("SELECT * FROM {}").format(sql.Identifier('myschema.mytable'))

这将创建以下查询:

SELECT * FROM "myschema.mytable"

这里我得到一个Relation "myschema.mytable" not found.异常。
如何正确地处理模式名?下面的语句可以工作,但是如何用psycopg2创建它们呢?

SELECT * FROM myschema.mytable
SELECT * FROM myschema."mytable"
SELECT * FROM "myschema"."mytable"

编辑:澄清的架构前缀

pxyaymoc

pxyaymoc1#

该结构

sql.Identifier('myschema.mytable')

被视为一个单引号标识符,从生成的查询中可以看出。您应该将模式和表名作为单独的标识符传递,以格式化:

cursor.execute(sql.SQL("SELECT * FROM {}.{}").format(
    sql.Identifier('myschema'),
    sql.Identifier('mytable'))

注意,模式和表名必须完全匹配,大小写必须完全匹配,因为psycopg2SQL string composition tools生成带引号的标识符,而带引号的标识符区分大小写。

pengsaosao

pengsaosao2#

但是我的PostgreSQL数据库中的表是故意不加引号的,这意味着mytable存在,但“mytable”不存在。
你误解了引号的作用。在你的例子中(即表名中没有特殊字符的情况下),双引号唯一的作用是使名称区分大小写。如果你有一个名为MyTable的表,那么

SELECT * FROM mytable;

因为它不区分大小写,而

SELECT * FROM "mytable";

因为它区分大小写。但是

SELECT * FROM "MyTable";

会起作用,这就是你要找的。
另一个问题(@IljaEverilä在评论中指出)是这样的:

SELECT * FROM "myschema.mytable"

postgres将其视为一个名为myschema.mytable的表,因为你引用了整个内容。我假设这就是你要找的:

SELECT * FROM "myschema"."mytable"

也就是说,你需要一个单独的模式标识符和一个单独的由.连接的表。

emeijp43

emeijp433#

版本2.8(2019年4月4日发布)起,您可以将多个字符串传递给sql.Identifier,以表示一个限定标识符(例如模式名+表名)。

cursor.execute(
    sql.SQL("SELECT * FROM {table}").format(
        table=sql.Identifier("myschema", "mytable")
    )
)

# SELECT * FROM "myschema"."mytable"

参见:https://www.psycopg.org/docs/sql.html#psycopg2.sql.Identifier

相关问题