psycopg2 标识符中的模式名称

问题描述 投票:0回答:3

我想使用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"

编辑:澄清架构前缀

python postgresql psycopg2
3个回答
11
投票

施工

sql.Identifier('myschema.mytable')

被视为单个带引号的标识符,从生成的查询中可以看出。 请参阅@gg的答案,了解自 2.8 版本以来如何在 Psycopg 中处理合格标识符。

(对于旧版本)您应该将架构和表名称作为单独的标识符传递以进行格式化:

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

请注意,模式和表名称必须完全匹配,大小写和全部匹配,因为

psycopg2
SQL 字符串组合工具 会生成带引号的标识符,并且带引号的标识符区分大小写。


4
投票

但是我的 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"

即您需要一个单独的模式标识符和单独的由

.
连接的表。


3
投票

版本 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

© www.soinside.com 2019 - 2024. All rights reserved.