如何使用 SQLAlchemy 选择 PostgreSQL 系统列?

Rob*_*wie 6 sql postgresql sqlalchemy

Postgresql 在每个表上隐式定义了多个列,例如xmaxctid(参见文档)。

假设我的 SQLALchemy 表定义没有指定这些列,有没有办法使用核心 sql 功能(即不是 SA 的 ORM 部分)来选择它们?

xmax由于表定义中未明确定义,以下内容不起作用。

table = sa.Table(
    "mytable",
    metadata,
    sa.Column("col_a", sa.BIGINT),
    sa.Column("date", sa.DATE),
)

s = sa.select([table.c.xmax])
result = engine.execute(s)
Run Code Online (Sandbox Code Playgroud)

xmax具体来说,我的要求是在更新插入的条款中引用returning

insert(mytable).returning((mytable.c.xmax == 0).label("inserted"))
Run Code Online (Sandbox Code Playgroud)

Leo*_*ael 6

如果您不想更改现有的表声明,可以使用该函数(注意中的sqlalchemy.column()小写):ccolumn

xmax = sa.column('xmax')
sa.insert(mytable).returning((xmax == 0).label("inserted"))
Run Code Online (Sandbox Code Playgroud)

然而,如果你的 SQL 语句从多个表中选择(例如在一个连接中),那么 PostgreSQL 会抱怨它不知道xmax你正在谈论哪一列:

ProgrammingError: (psycopg2.ProgrammingError) column "xmax" does not exist
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以使用(不幸的是未记录的)_selectable参数:

xmax = sa.column('xmax', _selectable=mytable)
sa.insert(mytable).returning((xmax == 0).label("inserted"))
Run Code Online (Sandbox Code Playgroud)

它在连接表查询中以及仅从一个表中进行选择的情况下都有效,因此您可以根据需要随时使用它。


Ant*_*tis 4

一种选择是在 SA 表定义中声明xmax为系统列:

table = sa.Table(
    # ...,
    sa.Column("xmax", sa.TEXT, system=True),
)
Run Code Online (Sandbox Code Playgroud)

table.c.xmax这将允许您像任何其他列一样访问(因此您的建议table.c.xmax == 0应该可以工作)。该system=True标志告诉 SA 在发出 时不要尝试显式创建 xmax 列CREATE TABLE

(我在这里使用了sa.TEXT一些解决方法,因为sqlalchemy.dialects.postgresql没有提供XID数据类型,并且显然xid无法转换为数字类型。)