PostgreSQL

支持 PostgreSQL 数据库。

下表总结了当前数据库发布版本的支持级别。

支持的 PostgreSQL 版本

支持类型

版本

受支持版本

9.6+

尽力支持

9+

DBAPI 支持

以下方言/DBAPI 选项可用。请参阅各个 DBAPI 部分以获取连接信息。

序列/SERIAL/IDENTITY

PostgreSQL 支持序列,SQLAlchemy 使用序列作为为基于整数的主键列创建新主键值的默认方法。创建表时,SQLAlchemy 将为基于整数的主键列发出 SERIAL 数据类型,这将生成与该列对应的序列和服务器端默认值。

要指定用于主键生成的特定命名序列,请使用 Sequence() 构造

Table(
    "sometable",
    metadata,
    Column(
        "id", Integer, Sequence("some_id_seq", start=1), primary_key=True
    ),
)

当 SQLAlchemy 发出单个 INSERT 语句时,为了满足“最后插入标识符”可用的约定,RETURNING 子句被添加到 INSERT 语句中,该子句指定应在语句完成后返回主键列。RETURNING 功能仅在使用 PostgreSQL 8.2 或更高版本时才生效。作为回退方法,序列(无论是显式指定还是通过 SERIAL 隐式指定)都会预先独立执行,返回的值将用于后续插入。请注意,当使用 “executemany” 语义执行 insert() 构造时,“最后插入标识符” 功能不适用;在这种情况下,既不会发出 RETURNING 子句,也不会预先执行序列。

PostgreSQL 10 及更高版本的 IDENTITY 列

PostgreSQL 10 及更高版本具有取代 SERIAL 使用的新 IDENTITY 功能。Identity 构造在 Column 中可用于控制其行为

from sqlalchemy import Table, Column, MetaData, Integer, Computed

metadata = MetaData()

data = Table(
    "data",
    metadata,
    Column(
        "id", Integer, Identity(start=42, cycle=True), primary_key=True
    ),
    Column("data", String),
)

上面 Table 对象的 CREATE TABLE 将是

CREATE TABLE data (
    id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 42 CYCLE),
    data VARCHAR,
    PRIMARY KEY (id)
)

在版本 1.4 中更改: Column 中添加了 Identity 构造,以指定自增列的选项。

注意

以前版本的 SQLAlchemy 没有内置对 IDENTITY 渲染的支持,并且可以使用以下编译钩子来替换 SERIAL 的出现

from sqlalchemy.schema import CreateColumn
from sqlalchemy.ext.compiler import compiles


@compiles(CreateColumn, "postgresql")
def use_identity(element, compiler, **kw):
    text = compiler.visit_create_column(element, **kw)
    text = text.replace("SERIAL", "INT GENERATED BY DEFAULT AS IDENTITY")
    return text

使用上述方法,如下表所示

t = Table(
    "t", m, Column("id", Integer, primary_key=True), Column("data", String)
)

将在后端数据库上生成为

CREATE TABLE t (
    id INT GENERATED BY DEFAULT AS IDENTITY,
    data VARCHAR,
    PRIMARY KEY (id)
)

服务器端游标

psycopg2、asyncpg 方言支持服务器端游标,其他方言也可能支持。

通过使用 Connection.execution_options.stream_results 连接执行选项,可以在每个语句的基础上启用服务器端游标

with engine.connect() as conn:
    result = conn.execution_options(stream_results=True).execute(
        text("select * from table")
    )

请注意,某些类型的 SQL 语句可能不支持服务器端游标;通常,只有返回行的 SQL 语句才应与此选项一起使用。

版本 1.4 中已弃用: 方言级别的 server_side_cursors 标志已弃用,将在未来版本中删除。请使用 Connection.stream_results 执行选项以获得非缓冲游标支持。

事务隔离级别

大多数 SQLAlchemy 方言都支持使用 create_engine.isolation_level 参数在 create_engine() 级别以及在 Connection 级别通过 Connection.execution_options.isolation_level 参数设置事务隔离级别。

对于 PostgreSQL 方言,此功能通过使用 DBAPI 特定的功能来实现,例如 psycopg2 的隔离级别标志,它会将隔离级别设置嵌入到 "BEGIN" 语句中,或者对于没有直接支持的 DBAPI,通过在 DBAPI 发出的 "BEGIN" 语句之前发出 SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL <level>。对于特殊的 AUTOCOMMIT 隔离级别,使用 DBAPI 特定的技术,这通常是 DBAPI 连接对象上的 .autocommit 标志。

要使用 create_engine() 设置隔离级别

engine = create_engine(
    "postgresql+pg8000://scott:tiger@localhost/test",
    isolation_level="REPEATABLE READ",
)

要使用按连接执行选项进行设置

with engine.connect() as conn:
    conn = conn.execution_options(isolation_level="REPEATABLE READ")
    with conn.begin():
        ...  # work with transaction

还有更多用于隔离级别配置的选项,例如链接到主 Engine 的 “子引擎” 对象,每个对象都应用不同的隔离级别设置。有关背景信息,请参阅 设置事务隔离级别,包括 DBAPI 自动提交 中的讨论。

大多数 PostgreSQL 方言上的 isolation_level 的有效值包括

  • READ COMMITTED

  • READ UNCOMMITTED

  • REPEATABLE READ

  • SERIALIZABLE

  • AUTOCOMMIT

设置 READ ONLY / DEFERRABLE

大多数 PostgreSQL 方言都支持设置事务的 “READ ONLY” 和 “DEFERRABLE” 特性,这是对隔离级别设置的补充。这两个属性可以与隔离级别结合或独立建立,方法是将 postgresql_readonlypostgresql_deferrable 标志与 Connection.execution_options() 一起传递。下面的示例说明了同时传递 "SERIALIZABLE" 隔离级别以及设置 “READ ONLY” 和 “DEFERRABLE”

with engine.connect() as conn:
    conn = conn.execution_options(
        isolation_level="SERIALIZABLE",
        postgresql_readonly=True,
        postgresql_deferrable=True,
    )
    with conn.begin():
        ...  # work with transaction

请注意,某些 DBAPI(如 asyncpg)仅支持 SERIALIZABLE 隔离的 “readonly”。

在版本 1.4 中新增: 添加了对 postgresql_readonlypostgresql_deferrable 执行选项的支持。

临时表 / 连接池的资源重置

SQLAlchemy Engine 对象使用的 QueuePool 连接池实现包括 返回时重置 行为,当连接返回到池时,它将调用 DBAPI .rollback() 方法。虽然此回滚将清除先前事务使用的直接状态,但它不涵盖更广泛的会话级别状态,包括临时表以及其他服务器状态,例如预处理语句句柄和语句缓存。PostgreSQL 数据库包含各种可用于重置此状态的命令,包括 DISCARDRESETDEALLOCATEUNLISTEN

要安装这些命令中的一个或多个作为执行返回时重置的方式,可以使用 PoolEvents.reset() 事件钩子,如下例所示。该实现将结束正在进行的事务,并使用 CLOSERESETDISCARD 命令丢弃临时表;有关每个语句作用的背景信息,请参阅 PostgreSQL 文档。

create_engine.pool_reset_on_return 参数设置为 None,以便自定义方案可以完全替换默认行为。自定义钩子实现无论如何都会调用 .rollback(),因为通常重要的是 DBAPI 自身对提交/回滚的跟踪将与事务状态保持一致

from sqlalchemy import create_engine
from sqlalchemy import event

postgresql_engine = create_engine(
    "postgresql+pyscopg2://scott:tiger@hostname/dbname",
    # disable default reset-on-return scheme
    pool_reset_on_return=None,
)


@event.listens_for(postgresql_engine, "reset")
def _reset_postgresql(dbapi_connection, connection_record, reset_state):
    if not reset_state.terminate_only:
        dbapi_connection.execute("CLOSE ALL")
        dbapi_connection.execute("RESET ALL")
        dbapi_connection.execute("DISCARD TEMP")

    # so that the DBAPI itself knows that the connection has been
    # reset
    dbapi_connection.rollback()

在版本 2.0.0b3 中更改: PoolEvents.reset() 事件添加了额外的状态参数,并额外确保为所有 “重置” 事件调用该事件,使其适合作为自定义 “重置” 处理程序的位置。使用 PoolEvents.checkin() 处理程序的先前方案仍然可用。

另请参阅

返回时重置 - 在 连接池 文档中

在连接时设置备用搜索路径

PostgreSQL search_path 变量指的是在 SQL 语句中引用特定表或其他对象时将隐式引用的模式名称列表。如下节 远程模式表内省和 PostgreSQL search_path 中详述,SQLAlchemy 通常围绕将此变量保持在其默认值 public 的概念进行组织,但是,为了在自动使用连接时将其设置为任何任意名称或名称,可以使用以下事件处理程序为池中的所有连接调用 “SET SESSION search_path” 命令,如 为新连接设置默认模式 中所述

from sqlalchemy import event
from sqlalchemy import create_engine

engine = create_engine("postgresql+psycopg2://scott:tiger@host/dbname")


@event.listens_for(engine, "connect", insert=True)
def set_search_path(dbapi_connection, connection_record):
    existing_autocommit = dbapi_connection.autocommit
    dbapi_connection.autocommit = True
    cursor = dbapi_connection.cursor()
    cursor.execute("SET SESSION search_path='%s'" % schema_name)
    cursor.close()
    dbapi_connection.autocommit = existing_autocommit

使用 .autocommit DBAPI 属性使配方复杂化的原因是,当调用 SET SESSION search_path 指令时,它在任何事务范围之外调用,因此当 DBAPI 连接回滚时,它不会被还原。

远程模式表内省和 PostgreSQL search_path

最佳实践总结部分

search_path 变量保持为其默认值 public,没有任何其他模式名称。确保用于连接的用户名 匹配远程模式,或确保从 search_path删除 "$user" 令牌。对于其他模式名称,请在 Table 定义中显式命名它们。或者,postgresql_ignore_search_path 选项将导致所有反射的 Table 对象都设置 Table.schema 属性。

PostgreSQL 方言可以从任何模式反射表,如 从其他模式反射表 中所述。

在所有情况下,SQLAlchemy 在反射表时做的第一件事是 确定当前数据库连接的默认模式。它使用 PostgreSQL current_schema() 函数来执行此操作,如下所示,使用 PostgreSQL 客户端会话(即使用 psql 工具)

test=> select current_schema();
current_schema
----------------
public
(1 row)

上面我们看到,在 PostgreSQL 的普通安装中,默认模式名称是名称 public

但是,如果您的数据库用户名 与模式名称匹配,则 PostgreSQL 的默认行为是 使用该名称作为默认模式。下面,我们使用用户名 scott 登录。当我们创建一个名为 scott 的模式时,它会隐式更改默认模式

test=> select current_schema();
current_schema
----------------
public
(1 row)

test=> create schema scott;
CREATE SCHEMA
test=> select current_schema();
current_schema
----------------
scott
(1 row)

current_schema() 的行为源自 PostgreSQL 搜索路径 变量 search_path,在现代 PostgreSQL 版本中,它默认为此

test=> show search_path;
search_path
-----------------
"$user", public
(1 row)

在上面,如果存在默认模式,"$user" 变量将注入当前用户名作为默认模式。否则,将使用 public

当反射 Table 对象时,如果它存在于 current_schema() 函数指示的模式中,则 分配给 Table 的 “.schema” 属性的模式名称是 Python “None” 值。否则,“.schema” 属性将分配该模式的字符串名称。

关于这些 Table 对象通过外键约束引用的表,必须决定如何在这些远程表中表示 .schema,在这种情况下,远程模式名称也是当前 search_path 的成员。

默认情况下,PostgreSQL 方言模仿 PostgreSQL 自己的 pg_get_constraintdef() 内置过程鼓励的行为。当名称也在 PostgreSQL 模式搜索路径中时,此函数返回特定外键约束的示例定义,并从该定义中省略引用的模式名称。下面的交互说明了此行为

test=> CREATE TABLE test_schema.referred(id INTEGER PRIMARY KEY);
CREATE TABLE
test=> CREATE TABLE referring(
test(>         id INTEGER PRIMARY KEY,
test(>         referred_id INTEGER REFERENCES test_schema.referred(id));
CREATE TABLE
test=> SET search_path TO public, test_schema;
test=> SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM
test-> pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n
test-> ON n.oid = c.relnamespace
test-> JOIN pg_catalog.pg_constraint r  ON c.oid = r.conrelid
test-> WHERE c.relname='referring' AND r.contype = 'f'
test-> ;
               pg_get_constraintdef
---------------------------------------------------
 FOREIGN KEY (referred_id) REFERENCES referred(id)
(1 row)

上面,我们创建了一个表 referred 作为远程模式 test_schema 的成员,但是当我们向 PG search_path 添加 test_schema,然后要求 pg_get_constraintdef() 获取 FOREIGN KEY 语法时,test_schema 未包含在该函数的输出中。

另一方面,如果我们将搜索路径设置回典型的默认值 public

test=> SET search_path TO public;
SET

现在,对 pg_get_constraintdef() 的相同查询为我们返回完全限定的模式名称

test=> SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM
test-> pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n
test-> ON n.oid = c.relnamespace
test-> JOIN pg_catalog.pg_constraint r  ON c.oid = r.conrelid
test-> WHERE c.relname='referring' AND r.contype = 'f';
                     pg_get_constraintdef
---------------------------------------------------------------
 FOREIGN KEY (referred_id) REFERENCES test_schema.referred(id)
(1 row)

默认情况下,SQLAlchemy 将使用 pg_get_constraintdef() 的返回值来确定远程模式名称。也就是说,如果我们的 search_path 设置为包含 test_schema,并且我们按如下方式调用表反射过程

>>> from sqlalchemy import Table, MetaData, create_engine, text
>>> engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test")
>>> with engine.connect() as conn:
...     conn.execute(text("SET search_path TO test_schema, public"))
...     metadata_obj = MetaData()
...     referring = Table("referring", metadata_obj, autoload_with=conn)
<sqlalchemy.engine.result.CursorResult object at 0x101612ed0>

上面的过程会将 referred 表传递到 MetaData.tables 集合中,该表在命名时 没有 模式

>>> metadata_obj.tables["referred"].schema is None
True

要更改反射的行为,以便无论 search_path 设置如何都保持引用的模式,请使用 postgresql_ignore_search_path 选项,该选项可以指定为 TableMetaData.reflect() 的方言特定参数

>>> with engine.connect() as conn:
...     conn.execute(text("SET search_path TO test_schema, public"))
...     metadata_obj = MetaData()
...     referring = Table(
...         "referring",
...         metadata_obj,
...         autoload_with=conn,
...         postgresql_ignore_search_path=True,
...     )
<sqlalchemy.engine.result.CursorResult object at 0x1016126d0>

现在,我们将 test_schema.referred 存储为模式限定的

>>> metadata_obj.tables["test_schema.referred"].schema
'test_schema'

另请参阅

模式限定反射与默认模式的交互 - 从后端无关的角度讨论该问题

模式搜索路径 - 在 PostgreSQL 网站上。

INSERT/UPDATE…RETURNING

该方言支持 PG 8.2 的 INSERT..RETURNINGUPDATE..RETURNINGDELETE..RETURNING 语法。INSERT..RETURNING 默认用于单行 INSERT 语句,以便获取新生成的主键标识符。要指定显式的 RETURNING 子句,请在每个语句的基础上使用 _UpdateBase.returning() 方法

# INSERT..RETURNING
result = (
    table.insert().returning(table.c.col1, table.c.col2).values(name="foo")
)
print(result.fetchall())

# UPDATE..RETURNING
result = (
    table.update()
    .returning(table.c.col1, table.c.col2)
    .where(table.c.name == "foo")
    .values(name="bar")
)
print(result.fetchall())

# DELETE..RETURNING
result = (
    table.delete()
    .returning(table.c.col1, table.c.col2)
    .where(table.c.name == "foo")
)
print(result.fetchall())

INSERT…ON CONFLICT (Upsert)

从 9.5 版本开始,PostgreSQL 允许通过 INSERT 语句的 ON CONFLICT 子句将行“upsert”(更新或插入)到表中。只有当候选行不违反任何唯一约束时,才会插入该行。如果发生唯一约束冲突,则可以执行辅助操作,可以是 “DO UPDATE”,表示应更新目标行中的数据,也可以是 “DO NOTHING”,表示静默跳过此行。

冲突是使用现有的唯一约束和索引来确定的。这些约束可以使用 DDL 中声明的名称来识别,也可以通过声明构成索引的列和条件来推断。

SQLAlchemy 通过 PostgreSQL 特定的 insert() 函数提供 ON CONFLICT 支持,该函数提供了生成方法 Insert.on_conflict_do_update()Insert.on_conflict_do_nothing()

>>> from sqlalchemy.dialects.postgresql import insert
>>> insert_stmt = insert(my_table).values(
...     id="some_existing_id", data="inserted value"
... )
>>> do_nothing_stmt = insert_stmt.on_conflict_do_nothing(index_elements=["id"])
>>> print(do_nothing_stmt)
INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT (id) DO NOTHING
>>> do_update_stmt = insert_stmt.on_conflict_do_update( ... constraint="pk_my_table", set_=dict(data="updated value") ... ) >>> print(do_update_stmt)
INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT ON CONSTRAINT pk_my_table DO UPDATE SET data = %(param_1)s

另请参阅

INSERT .. ON CONFLICT - 在 PostgreSQL 文档中。

指定目标

这两种方法都使用命名约束或列推断来提供冲突的“目标”

  • Insert.on_conflict_do_update.index_elements 参数指定一个序列,其中包含字符串列名、Column 对象和/或 SQL 表达式元素,这些元素将标识唯一索引

    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
    ...     index_elements=["id"], set_=dict(data="updated value")
    ... )
    >>> print(do_update_stmt)
    
    INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT (id) DO UPDATE SET data = %(param_1)s
    >>> do_update_stmt = insert_stmt.on_conflict_do_update( ... index_elements=[my_table.c.id], set_=dict(data="updated value") ... ) >>> print(do_update_stmt)
    INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT (id) DO UPDATE SET data = %(param_1)s
  • 当使用 Insert.on_conflict_do_update.index_elements 推断索引时,还可以通过指定使用 Insert.on_conflict_do_update.index_where 参数来推断部分索引

    >>> stmt = insert(my_table).values(user_email="a@b.com", data="inserted data")
    >>> stmt = stmt.on_conflict_do_update(
    ...     index_elements=[my_table.c.user_email],
    ...     index_where=my_table.c.user_email.like("%@gmail.com"),
    ...     set_=dict(data=stmt.excluded.data),
    ... )
    >>> print(stmt)
    
    INSERT INTO my_table (data, user_email) VALUES (%(data)s, %(user_email)s) ON CONFLICT (user_email) WHERE user_email LIKE %(user_email_1)s DO UPDATE SET data = excluded.data
  • Insert.on_conflict_do_update.constraint 参数用于直接指定索引,而不是推断索引。这可以是 UNIQUE 约束、PRIMARY KEY 约束或 INDEX 的名称

    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
    ...     constraint="my_table_idx_1", set_=dict(data="updated value")
    ... )
    >>> print(do_update_stmt)
    
    INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT ON CONSTRAINT my_table_idx_1 DO UPDATE SET data = %(param_1)s
    >>> do_update_stmt = insert_stmt.on_conflict_do_update( ... constraint="my_table_pk", set_=dict(data="updated value") ... ) >>> print(do_update_stmt)
    INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT ON CONSTRAINT my_table_pk DO UPDATE SET data = %(param_1)s
  • Insert.on_conflict_do_update.constraint 参数也可以引用代表约束的 SQLAlchemy 构造,例如 UniqueConstraintPrimaryKeyConstraintIndexExcludeConstraint。在这种用法中,如果约束具有名称,则直接使用该名称。否则,如果约束未命名,则将使用推断,其中约束的表达式和可选的 WHERE 子句将在构造中拼写出来。此用法尤其方便引用 Table 的命名或未命名主键,使用 Table.primary_key 属性

    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
    ...     constraint=my_table.primary_key, set_=dict(data="updated value")
    ... )
    >>> print(do_update_stmt)
    
    INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT (id) DO UPDATE SET data = %(param_1)s

SET 子句

ON CONFLICT...DO UPDATE 用于执行对已存在行的更新,使用新值以及来自提议插入的值的任意组合。这些值使用 Insert.on_conflict_do_update.set_ 参数指定。此参数接受一个字典,其中包含 UPDATE 的直接值

>>> stmt = insert(my_table).values(id="some_id", data="inserted value")
>>> do_update_stmt = stmt.on_conflict_do_update(
...     index_elements=["id"], set_=dict(data="updated value")
... )
>>> print(do_update_stmt)
INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT (id) DO UPDATE SET data = %(param_1)s

警告

Insert.on_conflict_do_update() 方法考虑 Python 端的默认 UPDATE 值或生成函数,例如使用 Column.onupdate 指定的那些。除非在 Insert.on_conflict_do_update.set_ 字典中手动指定这些值,否则不会为 ON CONFLICT 样式的 UPDATE 执行这些值。

使用排除的 INSERT 值进行更新

为了引用建议的插入行,特殊别名 Insert.excluded 可作为 Insert 对象的属性使用;此对象是一个 ColumnCollection,其别名包含目标表的所有列

>>> stmt = insert(my_table).values(
...     id="some_id", data="inserted value", author="jlh"
... )
>>> do_update_stmt = stmt.on_conflict_do_update(
...     index_elements=["id"],
...     set_=dict(data="updated value", author=stmt.excluded.author),
... )
>>> print(do_update_stmt)
INSERT INTO my_table (id, data, author) VALUES (%(id)s, %(data)s, %(author)s) ON CONFLICT (id) DO UPDATE SET data = %(param_1)s, author = excluded.author

额外的 WHERE 条件

Insert.on_conflict_do_update() 方法还接受使用 Insert.on_conflict_do_update.where 参数的 WHERE 子句,这将限制接收 UPDATE 的行

>>> stmt = insert(my_table).values(
...     id="some_id", data="inserted value", author="jlh"
... )
>>> on_update_stmt = stmt.on_conflict_do_update(
...     index_elements=["id"],
...     set_=dict(data="updated value", author=stmt.excluded.author),
...     where=(my_table.c.status == 2),
... )
>>> print(on_update_stmt)
INSERT INTO my_table (id, data, author) VALUES (%(id)s, %(data)s, %(author)s) ON CONFLICT (id) DO UPDATE SET data = %(param_1)s, author = excluded.author WHERE my_table.status = %(status_1)s

使用 DO NOTHING 跳过行

如果发生与唯一约束或排除约束的任何冲突,则可以使用 ON CONFLICT 完全跳过插入行;下面使用 Insert.on_conflict_do_nothing() 方法对此进行说明

>>> stmt = insert(my_table).values(id="some_id", data="inserted value")
>>> stmt = stmt.on_conflict_do_nothing(index_elements=["id"])
>>> print(stmt)
INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT (id) DO NOTHING

如果 DO NOTHING 在没有指定任何列或约束的情况下使用,则其效果是跳过任何发生的唯一约束或排除约束冲突的 INSERT

>>> stmt = insert(my_table).values(id="some_id", data="inserted value")
>>> stmt = stmt.on_conflict_do_nothing()
>>> print(stmt)
INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s) ON CONFLICT DO NOTHING

FROM ONLY …

该方言支持 PostgreSQL 的 ONLY 关键字,用于仅定位继承层次结构中的特定表。这可以用于生成 SELECT ... FROM ONLYUPDATE ONLY ...DELETE FROM ONLY ... 语法。它使用 SQLAlchemy 的 hints 机制

# SELECT ... FROM ONLY ...
result = table.select().with_hint(table, "ONLY", "postgresql")
print(result.fetchall())

# UPDATE ONLY ...
table.update(values=dict(foo="bar")).with_hint(
    "ONLY", dialect_name="postgresql"
)

# DELETE FROM ONLY ...
table.delete().with_hint("ONLY", dialect_name="postgresql")

PostgreSQL 特定的索引选项

Index 构造的几个扩展可用于 PostgreSQL 方言。

覆盖索引

postgresql_include 选项为给定的字符串名称渲染 INCLUDE(colname)

Index("my_index", table.c.x, postgresql_include=["y"])

将索引渲染为 CREATE INDEX my_index ON table (x) INCLUDE (y)

请注意,此功能需要 PostgreSQL 11 或更高版本。

1.4 版本新增。

部分索引

部分索引向索引定义添加条件,以便将索引应用于行的子集。这些可以使用 postgresql_where 关键字参数在 Index 上指定

Index("my_index", my_table.c.id, postgresql_where=my_table.c.value > 10)

运算符类

PostgreSQL 允许为索引的每一列指定一个运算符类(请参阅 https://postgresql.ac.cn/docs/current/interactive/indexes-opclass.html)。Index 构造允许通过 postgresql_ops 关键字参数指定这些运算符类

Index(
    "my_index",
    my_table.c.id,
    my_table.c.data,
    postgresql_ops={"data": "text_pattern_ops", "id": "int4_ops"},
)

请注意,postgresql_ops 字典中的键是 Column 的 “key” 名称,即用于从 Table.c 集合访问它的名称,该名称可以配置为与数据库中表示的列的实际名称不同。

如果 postgresql_ops 要用于复杂的 SQL 表达式(例如函数调用),则要应用于列,它必须被赋予一个标签,该标签在字典中按名称标识,例如:

Index(
    "my_index",
    my_table.c.id,
    func.lower(my_table.c.data).label("data_lower"),
    postgresql_ops={"data_lower": "text_pattern_ops", "id": "int4_ops"},
)

运算符类也受 ExcludeConstraint 构造的支持,使用 ExcludeConstraint.ops 参数。有关详细信息,请参阅该参数。

1.3.21 版本新增: 增加了对 ExcludeConstraint 的运算符类的支持。

索引类型

PostgreSQL 提供了几种索引类型:B-Tree、Hash、GiST 和 GIN,以及用户创建自己的索引类型的功能(请参阅 https://postgresql.ac.cn/docs/current/static/indexes-types.html)。这些可以使用 postgresql_using 关键字参数在 Index 上指定

Index("my_index", my_table.c.data, postgresql_using="gin")

传递给关键字参数的值将简单地传递到基础 CREATE INDEX 命令,因此它必须是您的 PostgreSQL 版本有效的索引类型。

索引存储参数

PostgreSQL 允许在索引上设置存储参数。可用的存储参数取决于索引使用的索引方法。可以使用 postgresql_with 关键字参数在 Index 上指定存储参数

Index("my_index", my_table.c.data, postgresql_with={"fillfactor": 50})

PostgreSQL 允许定义在其中创建索引的表空间。可以使用 postgresql_tablespace 关键字参数在 Index 上指定表空间

Index("my_index", my_table.c.data, postgresql_tablespace="my_tablespace")

请注意,相同的选项在 Table 上也可用。

使用 CONCURRENTLY 的索引

通过将标志 postgresql_concurrently 传递给 Index 构造,支持 PostgreSQL 索引选项 CONCURRENTLY

tbl = Table("testtbl", m, Column("data", Integer))

idx1 = Index("test_idx1", tbl.c.data, postgresql_concurrently=True)

上面的索引构造将为 CREATE INDEX 渲染 DDL,假设检测到 PostgreSQL 8.2 或更高版本,或者对于无连接方言,则渲染为

CREATE INDEX CONCURRENTLY test_idx1 ON testtbl (data)

对于 DROP INDEX,假设检测到 PostgreSQL 9.2 或更高版本,或者对于无连接方言,它将发出

DROP INDEX CONCURRENTLY test_idx1

当使用 CONCURRENTLY 时,PostgreSQL 数据库要求语句在事务块之外调用。Python DBAPI 强制即使对于单个语句,也存在事务,因此要使用此构造,必须使用 DBAPI 的 “autocommit” 模式

metadata = MetaData()
table = Table("foo", metadata, Column("id", String))
index = Index("foo_idx", table.c.id, postgresql_concurrently=True)

with engine.connect() as conn:
    with conn.execution_options(isolation_level="AUTOCOMMIT"):
        table.create(conn)

另请参阅

事务隔离级别

PostgreSQL 索引反射

每当使用 UNIQUE CONSTRAINT 构造时,PostgreSQL 数据库都会隐式创建 UNIQUE INDEX。当使用 Inspector 检查表时,Inspector.get_indexes()Inspector.get_unique_constraints() 将分别报告这两种构造;对于索引,如果检测到索引正在镜像约束,则索引条目中将存在键 duplicates_constraint。当使用 Table(..., autoload_with=engine) 执行反射时,当检测到 UNIQUE INDEX 正在镜像 UniqueConstraintTable.constraints 集合中时,不会Table.indexes 中返回 UNIQUE INDEX。

特殊反射选项

用于 PostgreSQL 后端的 InspectorPGInspector 的实例,它提供了其他方法

from sqlalchemy import create_engine, inspect

engine = create_engine("postgresql+psycopg2://127.0.0.1/test")
insp = inspect(engine)  # will be a PGInspector

print(insp.get_enums())
对象名称 描述

PGInspector

class sqlalchemy.dialects.postgresql.base.PGInspector
method sqlalchemy.dialects.postgresql.base.PGInspector.get_domains(schema: str | None = None) List[ReflectedDomain]

返回 DOMAIN 对象的列表。

每个成员都是一个包含以下字段的字典

  • name - 域的名称

  • schema - 域的模式名称。

  • visible - 布尔值,指示此域在默认搜索路径中是否可见。

  • type - 由此域定义的类型。

  • nullable - 指示此域是否可以为 NULL

  • default - 域的默认值,如果域没有默认值,则为 None

  • constraints - 约束 - 由该域定义的约束字典列表。每个元素约束两个键:约束的 name (名称)和包含约束文本的 check (检查)。

参数:

schema – 模式名称。如果为 None,则使用默认模式(通常为 ‘public’)。也可以设置为 '*' 以指示加载所有模式的域。

2.0 版本新增。

method sqlalchemy.dialects.postgresql.base.PGInspector.get_enums(schema: str | None = None) List[ReflectedEnum]

返回 ENUM 对象的列表。

每个成员都是一个包含以下字段的字典

  • name - 枚举的名称

  • schema - 枚举的模式名称。

  • visible - 布尔值,指示此枚举在默认搜索路径中是否可见。

  • labels - 应用于枚举的字符串标签列表。

参数:

schema – 模式名称。如果为 None,则使用默认模式(通常为 ‘public’)。也可以设置为 '*' 以指示加载所有模式的枚举。

method sqlalchemy.dialects.postgresql.base.PGInspector.get_foreign_table_names(schema: str | None = None) List[str]

返回 FOREIGN TABLE (外部表)名称的列表。

行为类似于 Inspector.get_table_names() 的行为,但该列表仅限于报告 relkind 值为 f 的表。

method sqlalchemy.dialects.postgresql.base.PGInspector.get_table_oid(table_name: str, schema: str | None = None) int

返回给定表名称的 OID。

参数:
  • table_name – 表的字符串名称。对于特殊引用,请使用 quoted_name

  • schema – 字符串模式名称;如果省略,则使用数据库连接的默认模式。对于特殊引用,请使用 quoted_name

method sqlalchemy.dialects.postgresql.base.PGInspector.has_type(type_name: str, schema: str | None = None, **kw: Any) bool

如果数据库在提供的模式中具有指定的类型,则返回 True。

参数:
  • type_name – 要检查的类型。

  • schema – 模式名称。如果为 None,则使用默认模式(通常为 ‘public’)。也可以设置为 '*' 以在所有模式中检查。

2.0 版本新增。

PostgreSQL 表选项

PostgreSQL 方言直接支持几个 CREATE TABLE 选项,与 Table 构造结合使用

  • INHERITS (继承):

    Table("some_table", metadata, ..., postgresql_inherits="some_supertable")
    
    Table("some_table", metadata, ..., postgresql_inherits=("t1", "t2", ...))
  • ON COMMIT (在提交时):

    Table("some_table", metadata, ..., postgresql_on_commit="PRESERVE ROWS")
  • PARTITION BY (分区依据):

    Table(
        "some_table",
        metadata,
        ...,
        postgresql_partition_by="LIST (part_column)",
    )

    1.2.6 版本新增。

  • TABLESPACE (表空间):

    Table("some_table", metadata, ..., postgresql_tablespace="some_tablespace")

    以上选项也适用于 Index 构造。

  • USING (使用):

    Table("some_table", metadata, ..., postgresql_using="heap")

    2.0.26 版本新增。

  • WITH OIDS (使用 OID):

    Table("some_table", metadata, ..., postgresql_with_oids=True)
  • WITHOUT OIDS (不使用 OID):

    Table("some_table", metadata, ..., postgresql_with_oids=False)

另请参阅

PostgreSQL CREATE TABLE options - 在 PostgreSQL 文档中。

PostgreSQL 约束选项

以下选项受 PostgreSQL 方言支持,并与选定的约束构造结合使用

  • NOT VALID (无效):此选项适用于 CHECK (检查)和 FOREIGN KEY (外键)约束,当通过 ALTER TABLE 将约束添加到现有表时,并且具有在 ALTER 操作期间不扫描现有行以针对正在添加的约束的效果。

    当使用 SQL 迁移工具(例如 Alembic)渲染 ALTER TABLE 构造时,可以在创建约束的操作中将 postgresql_not_valid 参数指定为额外的关键字参数,如下面的 Alembic 示例所示

    def update():
        op.create_foreign_key(
            "fk_user_address",
            "address",
            "user",
            ["user_id"],
            ["id"],
            postgresql_not_valid=True,
        )

    该关键字最终由 CheckConstraintForeignKeyConstraintForeignKey 构造直接接受;当使用像 Alembic 这样的工具时,方言特定的关键字参数将从迁移操作指令传递到这些构造。

    CheckConstraint("some_field IS NOT NULL", postgresql_not_valid=True)
    
    ForeignKeyConstraint(
        ["some_id"], ["some_table.some_id"], postgresql_not_valid=True
    )

    1.4.32 版本新增。

    另请参阅

    PostgreSQL ALTER TABLE options - 在 PostgreSQL 文档中。

表值、表值函数和列值函数、行和元组对象

PostgreSQL 大量使用了现代 SQL 形式,例如表值函数、表和行作为值。这些构造通常用作 PostgreSQL 对复杂数据类型(如 JSON、ARRAY 和其他数据类型)支持的一部分。SQLAlchemy 的 SQL 表达式语言对大多数表值和行值形式具有原生支持。

表值函数

许多 PostgreSQL 内置函数旨在用于 SELECT 语句的 FROM 子句中,并且能够返回表行或表行集。例如,PostgreSQL 的大部分 JSON 函数(例如 json_array_elements()json_object_keys()json_each_text()json_each()json_to_record()json_populate_recordset())使用这种形式。SQLAlchemy 中的这些 SQL 函数调用形式可以使用 FunctionElement.table_valued() 方法,结合从 func 命名空间生成的 Function 对象。

以下是 PostgreSQL 参考文档中的示例

  • json_each():

    >>> from sqlalchemy import select, func
    >>> stmt = select(
    ...     func.json_each('{"a":"foo", "b":"bar"}').table_valued("key", "value")
    ... )
    >>> print(stmt)
    
    SELECT anon_1.key, anon_1.value FROM json_each(:json_each_1) AS anon_1
  • json_populate_record():

    >>> from sqlalchemy import select, func, literal_column
    >>> stmt = select(
    ...     func.json_populate_record(
    ...         literal_column("null::myrowtype"), '{"a":1,"b":2}'
    ...     ).table_valued("a", "b", name="x")
    ... )
    >>> print(stmt)
    
    SELECT x.a, x.b FROM json_populate_record(null::myrowtype, :json_populate_record_1) AS x
  • json_to_record() - 此形式使用 PostgreSQL 特定的派生列别名形式,我们可以使用带有类型的 column() 元素来生成它们。FunctionElement.table_valued() 方法生成 TableValuedAlias 构造,TableValuedAlias.render_derived() 方法设置派生列规范。

    >>> from sqlalchemy import select, func, column, Integer, Text
    >>> stmt = select(
    ...     func.json_to_record('{"a":1,"b":[1,2,3],"c":"bar"}')
    ...     .table_valued(
    ...         column("a", Integer),
    ...         column("b", Text),
    ...         column("d", Text),
    ...     )
    ...     .render_derived(name="x", with_types=True)
    ... )
    >>> print(stmt)
    
    SELECT x.a, x.b, x.d FROM json_to_record(:json_to_record_1) AS x(a INTEGER, b TEXT, d TEXT)
  • WITH ORDINALITY (带序号)- SQL 标准的一部分,WITH ORDINALITY 向函数的输出添加序号计数器,并被包括 unnest()generate_series() 在内的有限的 PostgreSQL 函数集接受。FunctionElement.table_valued() 方法为此目的接受关键字参数 with_ordinality,它接受将应用于 “ordinality” (序号)列的字符串名称。

    >>> from sqlalchemy import select, func
    >>> stmt = select(
    ...     func.generate_series(4, 1, -1)
    ...     .table_valued("value", with_ordinality="ordinality")
    ...     .render_derived()
    ... )
    >>> print(stmt)
    
    SELECT anon_1.value, anon_1.ordinality FROM generate_series(:generate_series_1, :generate_series_2, :generate_series_3) WITH ORDINALITY AS anon_1(value, ordinality)

1.4.0b2 版本新增。

另请参阅

表值函数 - 在 SQLAlchemy 统一教程

列值函数

与表值函数类似,列值函数也存在于 FROM 子句中,但作为单个标量值传递到列子句中。PostgreSQL 函数(如 json_array_elements()unnest()generate_series())可以使用这种形式。列值函数可以使用 FunctionElement.column_valued() 方法,该方法属于 FunctionElement

  • json_array_elements():

    >>> from sqlalchemy import select, func
    >>> stmt = select(
    ...     func.json_array_elements('["one", "two"]').column_valued("x")
    ... )
    >>> print(stmt)
    
    SELECT x FROM json_array_elements(:json_array_elements_1) AS x
  • unnest() - 为了生成 PostgreSQL ARRAY 文字,可以使用 array() 构造。

    >>> from sqlalchemy.dialects.postgresql import array
    >>> from sqlalchemy import select, func
    >>> stmt = select(func.unnest(array([1, 2])).column_valued())
    >>> print(stmt)
    
    SELECT anon_1 FROM unnest(ARRAY[%(param_1)s, %(param_2)s]) AS anon_1

    该函数当然可以针对类型为 ARRAY 的现有表绑定列使用。

    >>> from sqlalchemy import table, column, ARRAY, Integer
    >>> from sqlalchemy import select, func
    >>> t = table("t", column("value", ARRAY(Integer)))
    >>> stmt = select(func.unnest(t.c.value).column_valued("unnested_value"))
    >>> print(stmt)
    
    SELECT unnested_value FROM unnest(t.value) AS unnested_value

行类型

可以使用 func.ROWsqlalchemy.func 命名空间,或使用 tuple_() 构造来近似内置的 ROW 渲染支持。

>>> from sqlalchemy import table, column, func, tuple_
>>> t = table("t", column("id"), column("fk"))
>>> stmt = (
...     t.select()
...     .where(tuple_(t.c.id, t.c.fk) > (1, 2))
...     .where(func.ROW(t.c.id, t.c.fk) < func.ROW(3, 7))
... )
>>> print(stmt)
SELECT t.id, t.fk FROM t WHERE (t.id, t.fk) > (:param_1, :param_2) AND ROW(t.id, t.fk) < ROW(:ROW_1, :ROW_2)

传递给函数的表类型

PostgreSQL 支持将表作为参数传递给函数,这被称为 “记录” 类型。SQLAlchemy FromClause 对象(如 Table)使用 FromClause.table_valued() 方法支持这种特殊形式,该方法类似于 FunctionElement.table_valued() 方法,不同之处在于列的集合已经由 FromClause 本身建立。

>>> from sqlalchemy import table, column, func, select
>>> a = table("a", column("id"), column("x"), column("y"))
>>> stmt = select(func.row_to_json(a.table_valued()))
>>> print(stmt)
SELECT row_to_json(a) AS row_to_json_1 FROM a

1.4.0b2 版本新增。

ARRAY 类型

PostgreSQL 方言支持数组,既支持作为多维列类型,也支持作为数组文字。

JSON 类型

PostgreSQL 方言支持 JSON 和 JSONB 数据类型,包括 psycopg2 的原生支持以及对 PostgreSQL 所有特殊运算符的支持。

HSTORE 类型

支持 PostgreSQL HSTORE 类型以及 hstore 文字。

ENUM 类型

PostgreSQL 具有独立创建的 TYPE 结构,用于实现枚举类型。这种方法在 SQLAlchemy 方面引入了显著的复杂性,涉及何时应该 CREATE 和 DROP 此类型。类型对象也是一个独立的可反射实体。应参考以下各节:

将 ENUM 与 ARRAY 结合使用

目前,后端 DBAPI 尚不支持 ENUM 和 ARRAY 的组合。在 SQLAlchemy 1.3.17 之前,需要特殊的解决方法才能使此组合工作,如下所述。

在 1.3.17 版本中变更:ENUM 和 ARRAY 的组合现在由 SQLAlchemy 的实现直接处理,无需任何解决方法。

from sqlalchemy import TypeDecorator
from sqlalchemy.dialects.postgresql import ARRAY


class ArrayOfEnum(TypeDecorator):
    impl = ARRAY

    def bind_expression(self, bindvalue):
        return sa.cast(bindvalue, self)

    def result_processor(self, dialect, coltype):
        super_rp = super(ArrayOfEnum, self).result_processor(dialect, coltype)

        def handle_raw_string(value):
            inner = re.match(r"^{(.*)}$", value).group(1)
            return inner.split(",") if inner else []

        def process(value):
            if value is None:
                return None
            return super_rp(handle_raw_string(value))

        return process

例如:

Table(
    "mydata",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("data", ArrayOfEnum(ENUM("a", "b", "c", name="myenum"))),
)

此类型未作为内置类型包含,因为它将与突然决定在新版本中直接支持 ENUM 的 ARRAY 的 DBAPI 不兼容。

将 JSON/JSONB 与 ARRAY 结合使用

与使用 ENUM 类似,在 SQLAlchemy 1.3.17 之前,对于 JSON/JSONB 的 ARRAY,我们需要渲染适当的 CAST。当前的 psycopg2 驱动程序可以正确地适应结果集,而无需任何特殊步骤。

在 1.3.17 版本中变更:JSON/JSONB 和 ARRAY 的组合现在由 SQLAlchemy 的实现直接处理,无需任何解决方法。

class CastingArray(ARRAY):
    def bind_expression(self, bindvalue):
        return sa.cast(bindvalue, self)

例如:

Table(
    "mydata",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("data", CastingArray(JSONB)),
)

Range 和 Multirange 类型

psycopg、pg8000 和 asyncpg 方言支持 PostgreSQL range 和 multirange 类型;psycopg2 方言仅支持 range 类型。

2.0.17 版本新增:为 pg8000 方言添加了 range 和 multirange 支持。需要 pg8000 1.29.8 或更高版本。

传递到数据库的数据值可以作为字符串值传递,也可以使用 Range 数据对象传递。

2.0 版本新增:添加了后端无关的 Range 对象,用于指示范围。psycopg2 特定的 range 类不再公开,仅在特定方言内部使用。

例如,一个完全类型化的模型示例,使用 TSRANGE 数据类型

from datetime import datetime

from sqlalchemy.dialects.postgresql import Range
from sqlalchemy.dialects.postgresql import TSRANGE
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column


class Base(DeclarativeBase):
    pass


class RoomBooking(Base):
    __tablename__ = "room_booking"

    id: Mapped[int] = mapped_column(primary_key=True)
    room: Mapped[str]
    during: Mapped[Range[datetime]] = mapped_column(TSRANGE)

为了表示上面 during 列的数据,Range 类型是一个简单的 dataclass,它将表示范围的边界。下面说明了将行插入到上面的 room_booking 表中

from sqlalchemy import create_engine
from sqlalchemy.orm import Session

engine = create_engine("postgresql+psycopg://scott:tiger@pg14/dbname")

Base.metadata.create_all(engine)

with Session(engine) as session:
    booking = RoomBooking(
        room="101", during=Range(datetime(2013, 3, 23), datetime(2013, 3, 25))
    )
    session.add(booking)
    session.commit()

从任何 range 列中选择也将返回 Range 对象,如所示

from sqlalchemy import select

with Session(engine) as session:
    for row in session.execute(select(RoomBooking.during)):
        print(row)

可用的 range 数据类型如下:

对象名称 描述

范围

表示 PostgreSQL 范围。

class sqlalchemy.dialects.postgresql.Range

表示 PostgreSQL 范围。

例如:

r = Range(10, 50, bounds="()")

调用样式类似于 psycopg 和 psycopg2 的样式,部分原因是允许更容易地从以前直接使用这些对象的 SQLAlchemy 版本进行迁移。

参数:
  • lower – 下界值,或 None

  • upper – 上界值,或 None

  • bounds – 仅关键字,可选字符串值,可以是 "()""[)""(]""[]" 之一。默认为 "[)"

  • empty – 仅关键字,可选布尔值,指示这是一个 “空” 范围

2.0 版本新增。

类签名

class sqlalchemy.dialects.postgresql.Range (typing.Generic)

method sqlalchemy.dialects.postgresql.Range.__eq__(other: Any) bool

将此范围与 other 进行比较,同时考虑边界的包含性,如果它们相等,则返回 True

method sqlalchemy.dialects.postgresql.Range.adjacent_to(other: Range[_T]) bool

确定此范围是否与 other 相邻。

method sqlalchemy.dialects.postgresql.Range.contained_by(other: Range[_T]) bool

确定此范围是否被 other 包含。

method sqlalchemy.dialects.postgresql.Range.contains(value: _T | Range[_T]) bool

确定此范围是否包含 value

method sqlalchemy.dialects.postgresql.Range.difference(other: Range[_T]) Range[_T]

计算此范围与 other 之间的差集。

如果两个范围“不相交”,即既不相邻也不重叠,则会引发 ValueError 异常。

method sqlalchemy.dialects.postgresql.Range.intersection(other: Range[_T]) Range[_T]

计算此范围与 other 的交集。

2.0.10 版本新增。

attribute sqlalchemy.dialects.postgresql.Range.is_empty

‘empty’ 属性的同义词。

attribute sqlalchemy.dialects.postgresql.Range.isempty

‘empty’ 属性的同义词。

attribute sqlalchemy.dialects.postgresql.Range.lower: _T | None

下界

attribute sqlalchemy.dialects.postgresql.Range.lower_inc

如果下界是包含的,则返回 True。

attribute sqlalchemy.dialects.postgresql.Range.lower_inf

如果此范围非空且下界为无穷大,则返回 True。

method sqlalchemy.dialects.postgresql.Range.not_extend_left_of(other: Range[_T]) bool

确定此范围是否不向 other 的左侧延伸。

method sqlalchemy.dialects.postgresql.Range.not_extend_right_of(other: Range[_T]) bool

确定此范围是否不向 other 的右侧延伸。

method sqlalchemy.dialects.postgresql.Range.overlaps(other: Range[_T]) bool

确定此范围是否与 other 重叠。

method sqlalchemy.dialects.postgresql.Range.strictly_left_of(other: Range[_T]) bool

确定此范围是否完全在 other 的左侧。

method sqlalchemy.dialects.postgresql.Range.strictly_right_of(other: Range[_T]) bool

确定此范围是否完全在 other 的右侧。

method sqlalchemy.dialects.postgresql.Range.union(other: Range[_T]) Range[_T]

计算此范围与 other 的并集。

如果两个范围“不相交”,即既不相邻也不重叠,则会引发 ValueError 异常。

attribute sqlalchemy.dialects.postgresql.Range.upper: _T | None

上界

attribute sqlalchemy.dialects.postgresql.Range.upper_inc

如果上界是包含的,则返回 True。

attribute sqlalchemy.dialects.postgresql.Range.upper_inf

如果此范围非空且上界为无穷大,则返回 True。

多范围

PostgreSQL 14 及以上版本支持多范围。SQLAlchemy 的多范围数据类型处理 Range 类型列表。

在 psycopg、asyncpg 和 pg8000 方言上支持多范围。psycopg2 方言是 SQLAlchemy 的默认 postgresql 方言, 支持多范围数据类型。

2.0 版本新增: 添加了对 MULTIRANGE 数据类型的支持。SQLAlchemy 将多范围值表示为 Range 对象列表。

2.0.17 版本新增: 为 pg8000 方言添加了多范围支持。需要 pg8000 1.29.8 或更高版本。

2.0.26 版本新增: 添加了 MultiRange 序列。

以下示例说明了 TSMULTIRANGE 数据类型的用法

from datetime import datetime
from typing import List

from sqlalchemy.dialects.postgresql import Range
from sqlalchemy.dialects.postgresql import TSMULTIRANGE
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column


class Base(DeclarativeBase):
    pass


class EventCalendar(Base):
    __tablename__ = "event_calendar"

    id: Mapped[int] = mapped_column(primary_key=True)
    event_name: Mapped[str]
    added: Mapped[datetime]
    in_session_periods: Mapped[List[Range[datetime]]] = mapped_column(TSMULTIRANGE)

说明记录的插入和选择

from sqlalchemy import create_engine
from sqlalchemy import select
from sqlalchemy.orm import Session

engine = create_engine("postgresql+psycopg://scott:tiger@pg14/test")

Base.metadata.create_all(engine)

with Session(engine) as session:
    calendar = EventCalendar(
        event_name="SQLAlchemy Tutorial Sessions",
        in_session_periods=[
            Range(datetime(2013, 3, 23), datetime(2013, 3, 25)),
            Range(datetime(2013, 4, 12), datetime(2013, 4, 15)),
            Range(datetime(2013, 5, 9), datetime(2013, 5, 12)),
        ],
    )
    session.add(calendar)
    session.commit()

    for multirange in session.scalars(select(EventCalendar.in_session_periods)):
        for range_ in multirange:
            print(f"Start: {range_.lower}  End: {range_.upper}")

注意

在以上示例中,ORM 处理的 Range 类型列表不会自动检测到特定列表值的就地更改;要使用 ORM 更新列表值,请将新列表重新分配给属性,或使用 MutableList 类型修饰符。有关背景信息,请参阅 Mutation Tracking 部分。

使用 MultiRange 序列来推断多范围类型

当使用多范围作为字面量而不指定类型时,可以使用实用程序 MultiRange 序列

from sqlalchemy import literal
from sqlalchemy.dialects.postgresql import MultiRange

with Session(engine) as session:
    stmt = select(EventCalendar).where(
        EventCalendar.added.op("<@")(
            MultiRange(
                [
                    Range(datetime(2023, 1, 1), datetime(2013, 3, 31)),
                    Range(datetime(2023, 7, 1), datetime(2013, 9, 30)),
                ]
            )
        )
    )
    in_range = session.execute(stmt).all()

with engine.connect() as conn:
    row = conn.scalar(select(literal(MultiRange([Range(2, 4)]))))
    print(f"{row.lower} -> {row.upper}")

使用简单的 list 而不是 MultiRange 将需要手动将字面量值的类型设置为适当的多范围类型。

2.0.26 版本新增: 添加了 MultiRange 序列。

可用的多范围数据类型如下

网络数据类型

包含的网络数据类型有 INETCIDRMACADDR

对于 INETCIDR 数据类型,有条件地支持发送和检索 Python ipaddress 对象,包括 ipaddress.IPv4Networkipaddress.IPv6Networkipaddress.IPv4Addressipaddress.IPv6Address。此支持目前是 DBAPI 本身 的默认行为,并且因 DBAPI 而异。SQLAlchemy 尚未实现其自身的网络地址转换逻辑

  • psycopgasyncpg 完全支持这些数据类型;默认情况下,ipaddress 系列的对象在行中返回。

  • psycopg2 方言仅发送和接收字符串。

  • pg8000 方言支持 INET 数据类型的 ipaddress.IPv4Addressipaddress.IPv6Address 对象,但 CIDR 类型使用字符串。

将以上所有 DBAPI 规范化为仅返回字符串,请使用 native_inet_types 参数,并传递 False

e = create_engine(
    "postgresql+psycopg://scott:tiger@host/dbname", native_inet_types=False
)

使用上述参数,psycopgasyncpgpg8000 方言将禁用 DBAPI 对这些类型的适配,并且将仅返回字符串,从而与旧的 psycopg2 方言的行为相匹配。

该参数也可以设置为 True,在这种情况下,对于那些不支持或尚未完全支持将行转换为 Python ipaddress 数据类型的后端(目前为 psycopg2 和 pg8000),它将引发 NotImplementedError

2.0.18 版本新增: - 添加了 native_inet_types 参数。

PostgreSQL 数据类型

与所有 SQLAlchemy 方言一样,所有已知对 PostgreSQL 有效的大写类型都可以从顶级方言导入,无论它们是源自 sqlalchemy.types 还是来自本地方言

from sqlalchemy.dialects.postgresql import (
    ARRAY,
    BIGINT,
    BIT,
    BOOLEAN,
    BYTEA,
    CHAR,
    CIDR,
    CITEXT,
    DATE,
    DATEMULTIRANGE,
    DATERANGE,
    DOMAIN,
    DOUBLE_PRECISION,
    ENUM,
    FLOAT,
    HSTORE,
    INET,
    INT4MULTIRANGE,
    INT4RANGE,
    INT8MULTIRANGE,
    INT8RANGE,
    INTEGER,
    INTERVAL,
    JSON,
    JSONB,
    JSONPATH,
    MACADDR,
    MACADDR8,
    MONEY,
    NUMERIC,
    NUMMULTIRANGE,
    NUMRANGE,
    OID,
    REAL,
    REGCLASS,
    REGCONFIG,
    SMALLINT,
    TEXT,
    TIME,
    TIMESTAMP,
    TSMULTIRANGE,
    TSQUERY,
    TSRANGE,
    TSTZMULTIRANGE,
    TSTZRANGE,
    TSVECTOR,
    UUID,
    VARCHAR,
)

特定于 PostgreSQL 或具有 PostgreSQL 特定构造参数的类型如下:

对象名称 描述

AbstractMultiRange

PostgreSQL MULTIRANGE 类型的基类。

AbstractRange

单个和多范围 SQL 类型的基类。

AbstractSingleRange

PostgreSQL RANGE 类型的基类。

ARRAY

PostgreSQL ARRAY 类型。

BIT

BYTEA

CIDR

CITEXT

提供 PostgreSQL CITEXT 类型。

DATEMULTIRANGE

表示 PostgreSQL DATEMULTIRANGE 类型。

DATERANGE

表示 PostgreSQL DATERANGE 类型。

DOMAIN

表示 DOMAIN PostgreSQL 类型。

ENUM

PostgreSQL ENUM 类型。

HSTORE

表示 PostgreSQL HSTORE 类型。

INET

INT4MULTIRANGE

表示 PostgreSQL INT4MULTIRANGE 类型。

INT4RANGE

表示 PostgreSQL INT4RANGE 类型。

INT8MULTIRANGE

表示 PostgreSQL INT8MULTIRANGE 类型。

INT8RANGE

表示 PostgreSQL INT8RANGE 类型。

INTERVAL

PostgreSQL INTERVAL 类型。

JSON

表示 PostgreSQL JSON 类型。

JSONB

表示 PostgreSQL JSONB 类型。

JSONPATH

JSON Path 类型。

MACADDR

MACADDR8

MONEY

提供 PostgreSQL MONEY 类型。

MultiRange

表示多范围序列。

NUMMULTIRANGE

表示 PostgreSQL NUMMULTIRANGE 类型。

NUMRANGE

表示 PostgreSQL NUMRANGE 类型。

OID

提供 PostgreSQL OID 类型。

REGCLASS

提供 PostgreSQL REGCLASS 类型。

REGCONFIG

提供 PostgreSQL REGCONFIG 类型。

TIME

PostgreSQL TIME 类型。

TIMESTAMP

提供 PostgreSQL TIMESTAMP 类型。

TSMULTIRANGE

表示 PostgreSQL TSRANGE 类型。

TSQUERY

提供 PostgreSQL TSQUERY 类型。

TSRANGE

表示 PostgreSQL TSRANGE 类型。

TSTZMULTIRANGE

表示 PostgreSQL TSTZRANGE 类型。

TSTZRANGE

表示 PostgreSQL TSTZRANGE 类型。

TSVECTOR

TSVECTOR 类型实现了 PostgreSQL 文本搜索类型 TSVECTOR。

class sqlalchemy.dialects.postgresql.AbstractRange

单个和多范围 SQL 类型的基类。

class comparator_factory

定义范围类型的比较操作。

类签名

class sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory (sqlalchemy.types.Comparator)

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.adjacent_to(other: Any) ColumnElement[bool]

布尔表达式。如果列中的范围与操作数中的范围相邻,则返回 true。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.contained_by(other: Any) ColumnElement[bool]

布尔表达式。如果列包含在右手操作数中,则返回 true。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.contains(other: Any, **kw: Any) ColumnElement[bool]

布尔表达式。如果右手操作数(可以是元素或范围)包含在列中,则返回 true。

kwargs 可能会被此运算符忽略,但 API 一致性需要它。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.difference(other: Any) ColumnElement[bool]

范围表达式。返回两个范围的并集。如果结果范围不连续,将引发异常。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.intersection(other: Any) ColumnElement[Range[_T]]

范围表达式。返回两个范围的交集。如果结果范围不连续,将引发异常。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.not_extend_left_of(other: Any) ColumnElement[bool]

布尔表达式。如果列中的范围不向操作数中的范围左侧延伸,则返回 true。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.not_extend_right_of(other: Any) ColumnElement[bool]

布尔表达式。如果列中的范围不向操作数中的范围右侧延伸,则返回 true。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.overlaps(other: Any) ColumnElement[bool]

布尔表达式。如果列与右手操作数重叠(具有共同点),则返回 true。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.strictly_left_of(other: Any) ColumnElement[bool]

布尔表达式。如果列严格位于右手操作数的左侧,则返回 true。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.strictly_right_of(other: Any) ColumnElement[bool]

布尔表达式。如果列严格位于右手操作数的右侧,则返回 true。

method sqlalchemy.dialects.postgresql.AbstractRange.comparator_factory.union(other: Any) ColumnElement[bool]

范围表达式。返回两个范围的并集。如果结果范围不连续,将引发异常。

class sqlalchemy.dialects.postgresql.AbstractSingleRange

PostgreSQL RANGE 类型的基类。

这些是返回单个 Range 对象的类型。

class sqlalchemy.dialects.postgresql.AbstractMultiRange

PostgreSQL MULTIRANGE 类型的基类。

这些是返回 Range 对象序列的类型。

class sqlalchemy.dialects.postgresql.ARRAY

PostgreSQL ARRAY 类型。

ARRAY 类型以与核心 ARRAY 类型相同的方式构建; 成员类型是必需的,如果该类型将用于多个维度,则建议使用维度数量

from sqlalchemy.dialects import postgresql

mytable = Table(
    "mytable",
    metadata,
    Column("data", postgresql.ARRAY(Integer, dimensions=2)),
)

ARRAY 类型提供了核心 ARRAY 类型上定义的所有操作,包括对“维度”、索引访问和简单匹配(例如 Comparator.any()Comparator.all())的支持。ARRAY 类还提供了 PostgreSQL 特有的包含操作方法,包括 Comparator.contains()Comparator.contained_by()Comparator.overlap(),例如:

mytable.c.data.contains([1, 2])

默认情况下,索引访问是基于 1 的,以匹配 PostgreSQL; 对于基于 0 的索引访问,请设置 ARRAY.zero_indexes

此外,ARRAY 类型不能直接与 ENUM 类型结合使用。 有关解决方法,请参阅 将 ENUM 与 ARRAY 结合使用 中的特殊类型。

在使用 ORM 时检测 ARRAY 列中的更改

当与 SQLAlchemy ORM 一起使用时,ARRAY 类型不会检测到对数组的就地修改。 为了检测这些修改,必须使用 sqlalchemy.ext.mutable 扩展,并使用 MutableList

from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.ext.mutable import MutableList


class SomeOrmClass(Base):
    # ...

    data = Column(MutableList.as_mutable(ARRAY(Integer)))

此扩展将允许对数组进行“就地”更改(例如 .append())以生成将被工作单元检测到的事件。 请注意,对数组内部元素(包括就地修改的子数组)的更改不会被检测到。

或者,将新的数组值分配给替换旧值的 ORM 元素将始终触发更改事件。

另请参阅

ARRAY - 基础数组类型

array - 生成字面数组值。

method sqlalchemy.dialects.postgresql.ARRAY.__init__(item_type: _TypeEngineArgument[Any], as_tuple: bool = False, dimensions: int | None = None, zero_indexes: bool = False)

构造 ARRAY。

例如:

Column("myarray", ARRAY(Integer))

参数包括:

参数:
  • item_type – 此数组项的数据类型。 请注意,维度在这里是不相关的,因此像 INTEGER[][] 这样的多维数组被构造为 ARRAY(Integer),而不是 ARRAY(ARRAY(Integer)) 等。

  • as_tuple=False – 指定返回结果是否应从列表转换为元组。 诸如 psycopg2 之类的 DBAPI 默认返回列表。 当返回元组时,结果是可哈希的。

  • dimensions – 如果为非 None,则 ARRAY 将假定固定的维度数。 这将导致为此 ARRAY 发出的 DDL 包括确切的括号子句 [] 的数量,并且还将优化类型的整体性能。 请注意,PG 数组始终是隐式“非维度”的,这意味着无论它们是如何声明的,它们都可以存储任意数量的维度。

  • zero_indexes=False – 当为 True 时,索引值将在 Python 基于 0 的索引和 PostgreSQL 基于 1 的索引之间进行转换,例如,在传递到数据库之前,索引值都将加 1。

class Comparator

ARRAY 定义比较运算。

请注意,这些操作是对基础 Comparator 类提供的操作的补充,包括 Comparator.any()Comparator.all()

类签名

class sqlalchemy.dialects.postgresql.ARRAY.Comparator (sqlalchemy.types.Comparator)

method sqlalchemy.dialects.postgresql.ARRAY.Comparator.contains(other, **kwargs)

布尔表达式。 测试元素是否是参数数组表达式元素的超集。

kwargs 可能会被此运算符忽略,但 API 一致性需要它。

method sqlalchemy.dialects.postgresql.ARRAY.Comparator.contained_by(other)

布尔表达式。 测试元素是否是参数数组表达式元素的真子集。

method sqlalchemy.dialects.postgresql.ARRAY.Comparator.overlap(other)

布尔表达式。 测试数组是否与参数数组表达式有共同的元素。

class sqlalchemy.dialects.postgresql.BIT
class sqlalchemy.dialects.postgresql.BYTEA

成员

__init__()

method sqlalchemy.dialects.postgresql.BYTEA.__init__(length: int | None = None)

继承自 sqlalchemy.types.LargeBinary.__init__ 方法,该方法属于 LargeBinary

构造 LargeBinary 类型。

参数:

length – 可选,用于 DDL 语句的列长度,适用于接受长度的二进制类型,例如 MySQL BLOB 类型。

class sqlalchemy.dialects.postgresql.CIDR

类签名

class sqlalchemy.dialects.postgresql.CIDR (sqlalchemy.dialects.postgresql.types._NetworkAddressTypeMixin, sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.CITEXT

提供 PostgreSQL CITEXT 类型。

2.0.7 版本新增。

成员

__init__()

method sqlalchemy.dialects.postgresql.CITEXT.__init__(length: int | None = None, collation: str | None = None)

继承自 sqlalchemy.types.String.__init__ 方法,该方法属于 String

创建字符串类型的持有器。

参数:
  • length – 可选,用于 DDL 和 CAST 表达式的列长度。 如果不发出 CREATE TABLE,则可以安全地省略。 某些数据库可能需要 length 以用于 DDL,并且如果包含没有长度的 VARCHAR,则在发出 CREATE TABLE DDL 时会引发异常。 该值被解释为字节还是字符取决于具体的数据库。

  • collation

    可选,列级别的排序规则,用于 DDL 和 CAST 表达式。 使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字呈现。 例如:

    >>> from sqlalchemy import cast, select, String
    >>> print(select(cast("some string", String(collation="utf8"))))
    
    SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1

    注意

    在大多数情况下,UnicodeUnicodeText 数据类型应用于期望存储非 ASCII 数据的 Column。 这些数据类型将确保在数据库上使用正确的类型。

class sqlalchemy.dialects.postgresql.DOMAIN

表示 DOMAIN PostgreSQL 类型。

域本质上是一种数据类型,带有可选的约束,用于限制允许的值集。 例如:

PositiveInt = DOMAIN("pos_int", Integer, check="VALUE > 0", not_null=True)

UsPostalCode = DOMAIN(
    "us_postal_code",
    Text,
    check="VALUE ~ '^\d{5}$' OR VALUE ~ '^\d{5}-\d{4}$'",
)

有关更多详细信息,请参阅 PostgreSQL 文档

2.0 版本新增。

类签名

class sqlalchemy.dialects.postgresql.DOMAIN (sqlalchemy.dialects.postgresql.named_types.NamedType, sqlalchemy.types.SchemaType)

method sqlalchemy.dialects.postgresql.DOMAIN.__init__(name: str, data_type: _TypeEngineArgument[Any], *, collation: str | None = None, default: elements.TextClause | str | None = None, constraint_name: str | None = None, not_null: bool | None = None, check: elements.TextClause | str | None = None, create_type: bool = True, **kw: Any)

构造 DOMAIN。

参数:
  • name – 域的名称

  • data_type – 域的底层数据类型。 这可以包括数组说明符。

  • collation – 域的可选排序规则。 如果未指定排序规则,则使用底层数据类型的默认排序规则。 如果指定了 collation,则底层类型必须是可排序的。

  • default – DEFAULT 子句指定域数据类型列的默认值。 默认值应为字符串或 text() 值。 如果未指定默认值,则默认值为 null 值。

  • constraint_name – 约束的可选名称。 如果未指定,则后端会生成一个名称。

  • not_null – 阻止此域的值为空。 默认情况下,域允许为空。 如果未指定,则不会发出非空子句。

  • check – CHECK 子句指定完整性约束或测试,域的值必须满足该约束或测试。 约束必须是生成布尔结果的表达式,该表达式可以使用关键字 VALUE 来引用被测试的值。 与 PostgreSQL 不同,SQLAlchemy 中目前只允许使用单个 check 子句。

  • schema – 可选的模式名称

  • metadata – 可选的 MetaData 对象,此 DOMAIN 将直接与之关联

  • create_type – 默认为 True。 指示在创建父表时,应发出 CREATE TYPE,并在可选地检查类型的存在之后; 此外,当删除表时,将调用 DROP TYPE

method sqlalchemy.dialects.postgresql.DOMAIN.create(bind, checkfirst=True, **kw)

继承自 NamedType.create() 方法,该方法属于 NamedType

为此类型发出 CREATE DDL。

参数:
  • bind – 可连接的 EngineConnection 或类似对象,用于发出 SQL。

  • checkfirst – 如果为 True,则首先针对 PG 目录执行查询,以查看在创建之前类型是否已存在。

method sqlalchemy.dialects.postgresql.DOMAIN.drop(bind, checkfirst=True, **kw)

继承自 NamedType.drop() 方法,该方法属于 NamedType

为此类型发出 DROP DDL。

参数:
  • bind – 可连接的 EngineConnection 或类似对象,用于发出 SQL。

  • checkfirst – 如果为 True,则首先针对 PG 目录执行查询,以查看在删除之前类型是否实际存在。

class sqlalchemy.dialects.postgresql.DOUBLE_PRECISION

SQL DOUBLE PRECISION 类型。

2.0 版本新增。

另请参阅

Double - 基础类型的文档。

类签名

class sqlalchemy.dialects.postgresql.DOUBLE_PRECISION (sqlalchemy.types.Double)

方法 sqlalchemy.dialects.postgresql.DOUBLE_PRECISION.__init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)

继承自 sqlalchemy.types.Float.__init__ 方法,源于 Float

构造一个 Float 类型。

参数:
  • precision

    用于 DDL CREATE TABLE 的数值精度。后端应该尝试确保此精度指示通用 Float 数据类型的位数。

    注意

    对于 Oracle 数据库后端,渲染 DDL 时不接受 Float.precision 参数,因为 Oracle 数据库不支持以十进制位数指定的浮点精度。请改用 Oracle 数据库特定的 FLOAT 数据类型,并指定 FLOAT.binary_precision 参数。这是 SQLAlchemy 2.0 版本中的新功能。

    要创建一个数据库无关的 Float,该类型为 Oracle 数据库单独指定二进制精度,请使用 TypeEngine.with_variant(),如下所示

    from sqlalchemy import Column
    from sqlalchemy import Float
    from sqlalchemy.dialects import oracle
    
    Column(
        "float_data",
        Float(5).with_variant(oracle.FLOAT(binary_precision=16), "oracle"),
    )

  • asdecimal – 与 Numeric 的标志相同,但默认为 False。 请注意,将此标志设置为 True 会导致浮点转换。

  • decimal_return_scale – 从浮点数转换为 Python 十进制数时使用的默认刻度。 由于十进制不精确,浮点值通常会更长,并且大多数浮点数据库类型都没有“刻度”的概念,因此默认情况下,浮点类型在转换时会查找前十位小数位。 指定此值将覆盖该长度。 请注意,MySQL 浮点类型(确实包含“刻度”)如果未另行指定,将使用“刻度”作为 decimal_return_scale 的默认值。

class sqlalchemy.dialects.postgresql.ENUM

PostgreSQL ENUM 类型。

这是 Enum 的子类,它包含对 PG 的 CREATE TYPEDROP TYPE 的支持。

当使用内置类型 EnumEnum.native_enum 标志保留其默认值 True 时,PostgreSQL 后端将使用 ENUM 类型作为实现,因此将使用特殊的创建/删除规则。

ENUM 的创建/删除行为必然是复杂的,因为 ENUM 类型与父表的关系很尴尬,因为它可能只由单个表“拥有”,也可能在多个表之间共享。

当以“内联”方式使用 EnumENUM 时,CREATE TYPEDROP TYPE 会在调用 Table.create()Table.drop() 方法时发出

table = Table(
    "sometable",
    metadata,
    Column("some_enum", ENUM("a", "b", "c", name="myenum")),
)

table.create(engine)  # will emit CREATE ENUM and CREATE TABLE
table.drop(engine)  # will emit DROP TABLE and DROP ENUM

要在多个表之间使用通用的枚举类型,最佳实践是独立声明 EnumENUM,并将其与 MetaData 对象本身关联

my_enum = ENUM("a", "b", "c", name="myenum", metadata=metadata)

t1 = Table("sometable_one", metadata, Column("some_enum", myenum))

t2 = Table("sometable_two", metadata, Column("some_enum", myenum))

当使用此模式时,仍然必须在单个表创建级别注意。 发出 CREATE TABLE 而不指定 checkfirst=True 仍然会导致问题

t1.create(engine)  # will fail: no such type 'myenum'

如果我们指定 checkfirst=True,则单个表级别的创建操作将检查 ENUM,如果不存在则创建

# will check if enum exists, and emit CREATE TYPE if not
t1.create(engine, checkfirst=True)

当使用元数据级别的 ENUM 类型时,如果调用了元数据范围的创建/删除,则始终会创建和删除该类型

metadata.create_all(engine)  # will emit CREATE TYPE
metadata.drop_all(engine)  # will emit DROP TYPE

该类型也可以直接创建和删除

my_enum.create(engine)
my_enum.drop(engine)

类签名

class sqlalchemy.dialects.postgresql.ENUM (sqlalchemy.dialects.postgresql.named_types.NamedType, sqlalchemy.types.NativeForEmulated, sqlalchemy.types.Enum)

方法 sqlalchemy.dialects.postgresql.ENUM.__init__(*enums, name: str | _NoArg | None = _NoArg.NO_ARG, create_type: bool = True, **kw)

构造一个 ENUM

参数与 Enum 的参数相同,但还包括以下参数。

参数:

create_type – 默认为 True。 表示当创建父表时,应发出 CREATE TYPE,并可选择在发出之前检查类型是否存在; 此外,当删除表时,会调用 DROP TYPE。 当为 False 时,将不执行检查,也不会发出 CREATE TYPEDROP TYPE,除非直接调用 ENUM.create()ENUM.drop()。 当在无法访问实际数据库的情况下调用 SQL 文件的创建方案时,将设置为 False 会很有帮助 - ENUM.create()ENUM.drop() 方法可用于将 SQL 发送到目标绑定。

方法 sqlalchemy.dialects.postgresql.ENUM.create(bind=None, checkfirst=True)

为此 ENUM 发出 CREATE TYPE

如果底层方言不支持 PostgreSQL CREATE TYPE,则不执行任何操作。

参数:
  • bind – 一个可连接的 EngineConnection 或类似对象,用于发出 SQL。

  • checkfirst – 如果为 True,则首先执行针对 PG 目录的查询,以查看该类型是否尚不存在,然后再创建。

方法 sqlalchemy.dialects.postgresql.ENUM.drop(bind=None, checkfirst=True)

为此 ENUM 发出 DROP TYPE

如果底层方言不支持 PostgreSQL DROP TYPE,则不执行任何操作。

参数:
  • bind – 一个可连接的 EngineConnection 或类似对象,用于发出 SQL。

  • checkfirst – 如果为 True,则首先执行针对 PG 目录的查询,以查看该类型是否实际存在,然后再删除。

class sqlalchemy.dialects.postgresql.HSTORE

表示 PostgreSQL HSTORE 类型。

HSTORE 类型存储包含字符串的字典,例如:

data_table = Table(
    "data_table",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("data", HSTORE),
)

with engine.connect() as conn:
    conn.execute(
        data_table.insert(), data={"key1": "value1", "key2": "value2"}
    )

HSTORE 提供了广泛的操作,包括

  • 索引操作

    data_table.c.data["some key"] == "some value"
  • 包含操作

    data_table.c.data.has_key("some key")
    
    data_table.c.data.has_all(["one", "two", "three"])
  • 连接

    data_table.c.data + {"k1": "v1"}

有关特殊方法的完整列表,请参见 comparator_factory

使用 ORM 时检测 HSTORE 列中的更改

对于 SQLAlchemy ORM 的用法,可能需要将 HSTORE 的用法与 MutableDict 字典结合使用,该字典现在是 sqlalchemy.ext.mutable 扩展的一部分。 此扩展将允许对字典进行“就地”更改,例如向当前字典添加新键或替换/删除现有键,以生成将被工作单元检测到的事件

from sqlalchemy.ext.mutable import MutableDict


class MyClass(Base):
    __tablename__ = "data_table"

    id = Column(Integer, primary_key=True)
    data = Column(MutableDict.as_mutable(HSTORE))


my_object = session.query(MyClass).one()

# in-place mutation, requires Mutable extension
# in order for the ORM to detect
my_object.data["some_key"] = "some value"

session.commit()

当不使用 sqlalchemy.ext.mutable 扩展时,除非将该字典值重新分配给 HSTORE 属性本身,从而生成更改事件,否则 ORM 不会收到现有字典内容发生任何更改的警报。

另请参阅

hstore - 渲染 PostgreSQL hstore() 函数。

class Comparator

定义 HSTORE 的比较操作。

类签名

class sqlalchemy.dialects.postgresql.HSTORE.Comparator (sqlalchemy.types.Comparator, sqlalchemy.types.Comparator)

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.array()

文本数组表达式。 返回交替键和值的数组。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.contained_by(other)

布尔表达式。 测试键是否是参数 jsonb 表达式的键的真子集。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.contains(other, **kwargs)

布尔表达式。 测试键(或数组)是否是参数 jsonb 表达式的键的超集/包含。

kwargs 可能会被此运算符忽略,但 API 一致性需要它。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.defined(key)

布尔表达式。 测试键是否存在非 NULL 值。 请注意,键可以是 SQLA 表达式。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.delete(key)

HStore 表达式。 返回此 hstore 的内容,并删除给定键。 请注意,键可以是 SQLA 表达式。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.has_all(other)

布尔表达式。 测试 jsonb 中是否存在所有键

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.has_any(other)

布尔表达式。 测试 jsonb 中是否存在任何键

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.has_key(other)

布尔表达式。 测试是否存在键。 请注意,键可以是 SQLA 表达式。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.keys()

文本数组表达式。 返回键的数组。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.matrix()

文本数组表达式。 返回 [键, 值] 对的数组。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.slice(array)

HStore 表达式。 返回由键数组定义的 hstore 的子集。

方法 sqlalchemy.dialects.postgresql.HSTORE.Comparator.vals()

文本数组表达式。 返回值的数组。

方法 sqlalchemy.dialects.postgresql.HSTORE.__init__(text_type=None)

构造一个新的 HSTORE

参数:

text_type – 应该用于索引值的类型。 默认为 Text

方法 sqlalchemy.dialects.postgresql.HSTORE.bind_processor(dialect)

返回用于处理绑定值的转换函数。

返回一个可调用对象,它将接收绑定参数值作为唯一的位置参数,并将返回要发送到 DB-API 的值。

如果不需要处理,则该方法应返回 None

注意

此方法仅相对于方言特定的类型对象调用,该对象通常对方言私有,并且与公共类型对象不同,这意味着为了提供替代的 TypeEngine.bind_processor() 方法,除非显式子类化 UserDefinedType 类,否则子类化 TypeEngine 类是不可行的。

要为 TypeEngine.bind_processor() 提供替代行为,请实现 TypeDecorator 类,并提供 TypeDecorator.process_bind_param() 的实现。

另请参阅

增强现有类型

参数:

dialect – 使用中的方言实例。

attribute sqlalchemy.dialects.postgresql.HSTORE.comparator_factory

Comparator 的别名

attribute sqlalchemy.dialects.postgresql.HSTORE.hashable = False

标志,如果为 False,则表示此类型的值不可哈希。

ORM 在对结果列表进行去重时使用。

方法 sqlalchemy.dialects.postgresql.HSTORE.result_processor(dialect, coltype)

返回用于处理结果行值的转换函数。

返回一个可调用对象,它将接收结果行列值作为唯一的位置参数,并将返回要返回给用户的值。

如果不需要处理,则该方法应返回 None

注意

此方法仅相对于方言特定的类型对象调用,该对象通常对方言私有,并且与公共类型对象不同,这意味着为了提供替代的 TypeEngine.result_processor() 方法,除非显式子类化 UserDefinedType 类,否则子类化 TypeEngine 类是不可行的。

要为 TypeEngine.result_processor() 提供备选行为,请实现 TypeDecorator 类,并提供 TypeDecorator.process_result_value() 的实现。

另请参阅

增强现有类型

参数:
  • dialect – 使用中的 Dialect 实例。

  • coltype – 在 cursor.description 中接收的 DBAPI coltype 参数。

class sqlalchemy.dialects.postgresql.INET

类签名

class sqlalchemy.dialects.postgresql.INET (sqlalchemy.dialects.postgresql.types._NetworkAddressTypeMixin, sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.INTERVAL

PostgreSQL INTERVAL 类型。

成员

__init__()

类签名

class sqlalchemy.dialects.postgresql.INTERVAL (sqlalchemy.types.NativeForEmulated, sqlalchemy.types._AbstractInterval)

method sqlalchemy.dialects.postgresql.INTERVAL.__init__(precision: int | None = None, fields: str | None = None) None

构造一个 INTERVAL。

参数:
  • precision – 可选的整数精度值

  • fields

    字符串字段说明符。 允许限制字段的存储,例如 "YEAR""MONTH""DAY TO HOUR" 等。

    1.2 版本新增。

class sqlalchemy.dialects.postgresql.JSON

表示 PostgreSQL JSON 类型。

JSON 在针对 PostgreSQL 后端使用基本 JSON 数据类型时会自动使用,但是基本 JSON 数据类型不提供 Python 访问器来访问 PostgreSQL 特定的比较方法,例如 Comparator.astext();此外,要使用 PostgreSQL JSONB,应显式使用 JSONB 数据类型。

另请参阅

JSON - 通用跨平台 JSON 数据类型的主要文档。

PostgreSQL 版本的 JSON 提供的运算符包括

  • 索引操作(-> 运算符)

    data_table.c.data["some key"]
    
    data_table.c.data[5]
  • 返回文本的索引操作(->> 运算符)

    data_table.c.data["some key"].astext == "some value"

    请注意,等效功能可通过 Comparator.as_string 访问器获得。

  • 带有 CAST 的索引操作(等效于 CAST(col ->> ['some key'] AS <type>)

    data_table.c.data["some key"].astext.cast(Integer) == 5

    请注意,等效功能可通过 Comparator.as_integer 和类似的访问器获得。

  • 路径索引操作(#> 运算符)

    data_table.c.data[("key_1", "key_2", 5, ..., "key_n")]
  • 返回文本的路径索引操作(#>> 运算符)

    data_table.c.data[
        ("key_1", "key_2", 5, ..., "key_n")
    ].astext == "some value"

索引操作返回表达式对象,其类型默认设置为 JSON,以便可以对结果类型调用进一步的面向 JSON 的指令。

自定义序列化器和反序列化器在方言级别指定,即使用 create_engine()。 这样做的原因是,当使用 psycopg2 时,DBAPI 仅允许在每个游标或每个连接级别进行序列化。例如:

engine = create_engine(
    "postgresql+psycopg2://scott:tiger@localhost/test",
    json_serializer=my_serialize_fn,
    json_deserializer=my_deserialize_fn,
)

当使用 psycopg2 方言时,json_deserializer 将使用 psycopg2.extras.register_default_json 注册到数据库。

另请参阅

JSON - 核心级别的 JSON 类型

JSONB

class Comparator

定义 JSON 的比较操作。

类签名

class sqlalchemy.dialects.postgresql.JSON.Comparator (sqlalchemy.types.Comparator)

attribute sqlalchemy.dialects.postgresql.JSON.Comparator.astext

在索引表达式上,在 SQL 中呈现时使用 “astext”(例如 “->>”)转换。

例如:

select(data_table.c.data["some key"].astext)

另请参阅

ColumnElement.cast()

method sqlalchemy.dialects.postgresql.JSON.__init__(none_as_null: bool = False, astext_type: TypeEngine[str] | None = None)

构造一个 JSON 类型。

参数:
  • none_as_null

    如果为 True,则将值 None 持久化为 SQL NULL 值,而不是 null 的 JSON 编码。 请注意,当此标志为 False 时,null() 构造仍然可以用于持久化 NULL 值

    from sqlalchemy import null
    
    conn.execute(table.insert(), {"data": null()})

    另请参阅

    JSON.NULL

  • astext_type – 用于索引属性上的 Comparator.astext 访问器的类型。 默认为 Text

attribute sqlalchemy.dialects.postgresql.JSON.comparator_factory

Comparator 的别名

attribute sqlalchemy.dialects.postgresql.JSON.render_bind_cast = True

BindTyping.RENDER_CASTS 模式渲染绑定转换。

如果为 True,则此类型(通常是方言级别的 impl 类型)向编译器发出信号,表明应在此类型的绑定参数周围呈现转换。

2.0 版本新增。

另请参阅

BindTyping

class sqlalchemy.dialects.postgresql.JSONB

表示 PostgreSQL JSONB 类型。

JSONB 类型存储任意 JSONB 格式的数据,例如:

data_table = Table(
    "data_table",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("data", JSONB),
)

with engine.connect() as conn:
    conn.execute(
        data_table.insert(), data={"key1": "value1", "key2": "value2"}
    )

JSONB 类型包含 JSON 提供的所有操作,包括索引操作的相同行为。 它还添加了 JSONB 特定的其他运算符,包括 Comparator.has_key()Comparator.has_all()Comparator.has_any()Comparator.contains()Comparator.contained_by()Comparator.delete_path()Comparator.path_exists()Comparator.path_match()

JSON 类型一样,JSONB 类型在使用 ORM 时不会检测到就地更改,除非使用了 sqlalchemy.ext.mutable 扩展。

自定义序列化器和反序列化器与 JSON 类共享,使用 json_serializerjson_deserializer 关键字参数。 这些必须在方言级别使用 create_engine() 指定。 当使用 psycopg2 时,序列化器使用 psycopg2.extras.register_default_jsonb 在每个连接的基础上与 jsonb 类型关联,就像使用 psycopg2.extras.register_default_json 将这些处理程序注册到 json 类型一样。

另请参阅

JSON

class Comparator

定义 JSON 的比较操作。

类签名

class sqlalchemy.dialects.postgresql.JSONB.Comparator (sqlalchemy.dialects.postgresql.json.Comparator)

method sqlalchemy.dialects.postgresql.JSONB.Comparator.contained_by(other: Any) ColumnElement[bool]

布尔表达式。 测试键是否是参数 jsonb 表达式的键的真子集(等效于 <@ 运算符)。

method sqlalchemy.dialects.postgresql.JSONB.Comparator.contains(other: Any, **kwargs: Any) ColumnElement[bool]

布尔表达式。 测试键(或数组)是否是参数 jsonb 表达式的键的超集/包含(等效于 @> 运算符)。

kwargs 可能会被此运算符忽略,但 API 一致性需要它。

method sqlalchemy.dialects.postgresql.JSONB.Comparator.delete_path(array: List[str] | _pg_array[str]) ColumnElement[JSONB]

JSONB 表达式。 删除参数数组中指定的字段或数组元素(等效于 #- 运算符)。

输入可以是字符串列表(将强制转换为 ARRAY)或 _postgres.array() 的实例。

2.0 版本新增。

method sqlalchemy.dialects.postgresql.JSONB.Comparator.has_all(other: Any) ColumnElement[bool]

布尔表达式。 测试 jsonb 中是否存在所有键(等效于 ?& 运算符)

method sqlalchemy.dialects.postgresql.JSONB.Comparator.has_any(other: Any) ColumnElement[bool]

布尔表达式。 测试 jsonb 中是否存在任何键(等效于 ?| 运算符)

method sqlalchemy.dialects.postgresql.JSONB.Comparator.has_key(other: Any) ColumnElement[bool]

布尔表达式。 测试是否存在键(等效于 ? 运算符)。 请注意,键可以是 SQLA 表达式。

method sqlalchemy.dialects.postgresql.JSONB.Comparator.path_exists(other: Any) ColumnElement[bool]

布尔表达式。 测试是否存在由参数 JSONPath 表达式给出的项目(等效于 @? 运算符)。

2.0 版本新增。

method sqlalchemy.dialects.postgresql.JSONB.Comparator.path_match(other: Any) ColumnElement[bool]

布尔表达式。 测试由参数 JSONPath 表达式给出的 JSONPath 谓词是否匹配(等效于 @@ 运算符)。

仅考虑结果的第一项。

2.0 版本新增。

attribute sqlalchemy.dialects.postgresql.JSONB.comparator_factory

Comparator 的别名

class sqlalchemy.dialects.postgresql.JSONPATH

JSON Path 类型。

这通常是在使用类似 jsonb_path_query_arrayjsonb_path_exists 这样的 JSON 搜索函数时,将字面值转换为 JSON 路径所必需的。

stmt = sa.select(
    sa.func.jsonb_path_query_array(
        table.c.jsonb_col, cast("$.address.id", JSONPATH)
    )
)

类签名

class sqlalchemy.dialects.postgresql.JSONPATH (sqlalchemy.dialects.postgresql.json.JSONPathType)

class sqlalchemy.dialects.postgresql.MACADDR

类签名

class sqlalchemy.dialects.postgresql.MACADDR (sqlalchemy.dialects.postgresql.types._NetworkAddressTypeMixin, sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.MACADDR8

类签名

class sqlalchemy.dialects.postgresql.MACADDR8 (sqlalchemy.dialects.postgresql.types._NetworkAddressTypeMixin, sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.MONEY

提供 PostgreSQL MONEY 类型。

取决于驱动程序,使用此类型的结果行可能会返回包含货币符号的字符串值。

因此,可能最好使用 TypeDecorator 将其转换为基于数值的货币数据类型

import re
import decimal
from sqlalchemy import Dialect
from sqlalchemy import TypeDecorator


class NumericMoney(TypeDecorator):
    impl = MONEY

    def process_result_value(self, value: Any, dialect: Dialect) -> None:
        if value is not None:
            # adjust this for the currency and numeric
            m = re.match(r"\$([\d.]+)", value)
            if m:
                value = decimal.Decimal(m.group(1))
        return value

或者,可以使用 TypeDecorator.column_expression() 方法将转换作为 CAST 应用,如下所示

import decimal
from sqlalchemy import cast
from sqlalchemy import TypeDecorator


class NumericMoney(TypeDecorator):
    impl = MONEY

    def column_expression(self, column: Any):
        return cast(column, Numeric())

1.2 版本新增。

class sqlalchemy.dialects.postgresql.OID

提供 PostgreSQL OID 类型。

class sqlalchemy.dialects.postgresql.REAL

SQL REAL 类型。

另请参阅

Float - 基础类型的文档。

类签名

class sqlalchemy.dialects.postgresql.REAL (sqlalchemy.types.Float)

method sqlalchemy.dialects.postgresql.REAL.__init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)

继承自 sqlalchemy.types.Float.__init__ 方法,源于 Float

构造一个 Float 类型。

参数:
  • precision

    用于 DDL CREATE TABLE 的数值精度。后端应该尝试确保此精度指示通用 Float 数据类型的位数。

    注意

    对于 Oracle 数据库后端,渲染 DDL 时不接受 Float.precision 参数,因为 Oracle 数据库不支持以十进制位数指定的浮点精度。请改用 Oracle 数据库特定的 FLOAT 数据类型,并指定 FLOAT.binary_precision 参数。这是 SQLAlchemy 2.0 版本中的新功能。

    要创建一个数据库无关的 Float,该类型为 Oracle 数据库单独指定二进制精度,请使用 TypeEngine.with_variant(),如下所示

    from sqlalchemy import Column
    from sqlalchemy import Float
    from sqlalchemy.dialects import oracle
    
    Column(
        "float_data",
        Float(5).with_variant(oracle.FLOAT(binary_precision=16), "oracle"),
    )

  • asdecimal – 与 Numeric 的标志相同,但默认为 False。 请注意,将此标志设置为 True 会导致浮点转换。

  • decimal_return_scale – 从浮点数转换为 Python 十进制数时使用的默认刻度。 由于十进制不精确性,浮点值通常会更长,并且大多数浮点数据库类型没有“刻度”的概念,因此默认情况下,float 类型在转换时会查找前十位小数位。 指定此值将覆盖该长度。 请注意,MySQL float 类型(确实包含“刻度”)如果未另行指定,则将“刻度”用作 decimal_return_scale 的默认值。

class sqlalchemy.dialects.postgresql.REGCONFIG

提供 PostgreSQL REGCONFIG 类型。

2.0.0rc1 版本新增。

class sqlalchemy.dialects.postgresql.REGCLASS

提供 PostgreSQL REGCLASS 类型。

1.2.7 版本新增。

class sqlalchemy.dialects.postgresql.TIMESTAMP

提供 PostgreSQL TIMESTAMP 类型。

成员

__init__()

method sqlalchemy.dialects.postgresql.TIMESTAMP.__init__(timezone: bool = False, precision: int | None = None) None

构造一个 TIMESTAMP。

参数:
  • timezone – 布尔值,指示时区是否存在,默认为 False

  • precision

    可选的整数精度值

    1.4 版本新增。

class sqlalchemy.dialects.postgresql.TIME

PostgreSQL TIME 类型。

成员

__init__()

method sqlalchemy.dialects.postgresql.TIME.__init__(timezone: bool = False, precision: int | None = None) None

构造一个 TIME。

参数:
  • timezone – 布尔值,指示时区是否存在,默认为 False

  • precision

    可选的整数精度值

    1.4 版本新增。

class sqlalchemy.dialects.postgresql.TSQUERY

提供 PostgreSQL TSQUERY 类型。

2.0.0rc1 版本新增。

class sqlalchemy.dialects.postgresql.TSVECTOR

TSVECTOR 类型实现了 PostgreSQL 文本搜索类型 TSVECTOR。

它可用于对自然语言文档执行全文查询。

另请参阅

全文搜索

class sqlalchemy.dialects.postgresql.UUID

表示 SQL UUID 类型。

这是 Uuid 数据库无关数据类型的 SQL 原生形式,并且向后兼容以前仅限 PostgreSQL 版本的 UUID

UUID 数据类型仅适用于具有名为 UUID 的 SQL 数据类型的数据库。 它不适用于没有此精确命名类型的后端,包括 SQL Server。 对于具有原生支持的后端无关 UUID 值,包括 SQL Server 的 UNIQUEIDENTIFIER 数据类型,请使用 Uuid 数据类型。

2.0 版本新增。

另请参阅

Uuid

类签名

class sqlalchemy.dialects.postgresql.UUID (sqlalchemy.types.Uuid, sqlalchemy.types.NativeForEmulated)

method sqlalchemy.dialects.postgresql.UUID.__init__(as_uuid: bool = True)

构造一个 UUID 类型。

参数:

as_uuid=True

如果为 True,值将被解释为 Python uuid 对象,并通过 DBAPI 在字符串之间进行转换。

class sqlalchemy.dialects.postgresql.INT4RANGE

表示 PostgreSQL INT4RANGE 类型。

class sqlalchemy.dialects.postgresql.INT8RANGE

表示 PostgreSQL INT8RANGE 类型。

class sqlalchemy.dialects.postgresql.NUMRANGE

表示 PostgreSQL NUMRANGE 类型。

class sqlalchemy.dialects.postgresql.DATERANGE

表示 PostgreSQL DATERANGE 类型。

class sqlalchemy.dialects.postgresql.TSRANGE

表示 PostgreSQL TSRANGE 类型。

class sqlalchemy.dialects.postgresql.TSTZRANGE

表示 PostgreSQL TSTZRANGE 类型。

class sqlalchemy.dialects.postgresql.INT4MULTIRANGE

表示 PostgreSQL INT4MULTIRANGE 类型。

class sqlalchemy.dialects.postgresql.INT8MULTIRANGE

表示 PostgreSQL INT8MULTIRANGE 类型。

class sqlalchemy.dialects.postgresql.NUMMULTIRANGE

表示 PostgreSQL NUMMULTIRANGE 类型。

class sqlalchemy.dialects.postgresql.DATEMULTIRANGE

表示 PostgreSQL DATEMULTIRANGE 类型。

class sqlalchemy.dialects.postgresql.TSMULTIRANGE

表示 PostgreSQL TSRANGE 类型。

class sqlalchemy.dialects.postgresql.TSTZMULTIRANGE

表示 PostgreSQL TSTZRANGE 类型。

class sqlalchemy.dialects.postgresql.MultiRange

表示多范围序列。

此列表子类是一个实用程序,允许根据单范围值自动推断正确的多范围 SQL 类型。 这在操作字面多范围时很有用

import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import MultiRange, Range

value = literal(MultiRange([Range(2, 4)]))

select(tbl).where(tbl.c.value.op("@")(MultiRange([Range(-3, 7)])))

2.0.26 版本新增。

类签名

class sqlalchemy.dialects.postgresql.MultiRange (builtins.list, typing.Generic)

PostgreSQL SQL 元素和函数

对象名称 描述

aggregate_order_by

表示 PostgreSQL 聚合 order by 表达式。

All(other, arrexpr[, operator])

ARRAY 级别的 Comparator.all() 方法的同义词。 有关详细信息,请参阅该方法。

Any(other, arrexpr[, operator])

ARRAY 级别的 Comparator.any() 方法的同义词。 有关详细信息,请参阅该方法。

array

PostgreSQL ARRAY 字面量。

array_agg(*arg, **kw)

array_agg 的 PostgreSQL 特定形式,确保返回类型为 ARRAY 而不是普通的 ARRAY,除非传递了显式的 type_

hstore

使用 PostgreSQL hstore() 函数在 SQL 表达式中构造 hstore 值。

phraseto_tsquery

PostgreSQL phraseto_tsquery SQL 函数。

plainto_tsquery

PostgreSQL plainto_tsquery SQL 函数。

to_tsquery

PostgreSQL to_tsquery SQL 函数。

to_tsvector

PostgreSQL to_tsvector SQL 函数。

ts_headline

PostgreSQL ts_headline SQL 函数。

websearch_to_tsquery

PostgreSQL websearch_to_tsquery SQL 函数。

class sqlalchemy.dialects.postgresql.aggregate_order_by

表示 PostgreSQL 聚合 order by 表达式。

例如:

from sqlalchemy.dialects.postgresql import aggregate_order_by

expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc()))
stmt = select(expr)

将表示表达式

SELECT array_agg(a ORDER BY b DESC) FROM table;

类似地

expr = func.string_agg(
    table.c.a, aggregate_order_by(literal_column("','"), table.c.a)
)
stmt = select(expr)

将表示

SELECT string_agg(a, ',' ORDER BY a) FROM table;

Changed in version 1.2.13: - ORDER BY 参数可以是多个术语

另请参阅

array_agg

class sqlalchemy.dialects.postgresql.array

PostgreSQL ARRAY 字面量。

这用于在 SQL 表达式中生成 ARRAY 字面量,例如

from sqlalchemy.dialects.postgresql import array
from sqlalchemy.dialects import postgresql
from sqlalchemy import select, func

stmt = select(array([1, 2]) + array([3, 4, 5]))

print(stmt.compile(dialect=postgresql.dialect()))

生成 SQL

SELECT ARRAY[%(param_1)s, %(param_2)s] ||
    ARRAY[%(param_3)s, %(param_4)s, %(param_5)s]) AS anon_1

array 的实例将始终具有 ARRAY 数据类型。type_ 关键字参数传递时,数组的“内部”类型从存在的值推断出来,除非

array(["foo", "bar"], type_=CHAR)

多维数组通过嵌套 array 构造产生。 最终 ARRAY 类型的维度通过递归添加内部 ARRAY 类型的维度来计算

stmt = select(
    array(
        [array([1, 2]), array([3, 4]), array([column("q"), column("x")])]
    )
)
print(stmt.compile(dialect=postgresql.dialect()))

产生

SELECT ARRAY[
    ARRAY[%(param_1)s, %(param_2)s],
    ARRAY[%(param_3)s, %(param_4)s],
    ARRAY[q, x]
] AS anon_1

New in version 1.3.6: 添加了对多维数组字面量的支持

另请参阅

ARRAY

类签名

class sqlalchemy.dialects.postgresql.array (sqlalchemy.sql.expression.ExpressionClauseList)

function sqlalchemy.dialects.postgresql.array_agg(*arg, **kw)

array_agg 的 PostgreSQL 特定形式,确保返回类型为 ARRAY 而不是普通的 ARRAY,除非传递了显式的 type_

function sqlalchemy.dialects.postgresql.Any(other, arrexpr, operator=<built-in function eq>)

ARRAY 级别的 Comparator.any() 方法的同义词。 有关详细信息,请参阅该方法。

function sqlalchemy.dialects.postgresql.All(other, arrexpr, operator=<built-in function eq>)

ARRAY 级别的 Comparator.all() 方法的同义词。 有关详细信息,请参阅该方法。

class sqlalchemy.dialects.postgresql.hstore

使用 PostgreSQL hstore() 函数在 SQL 表达式中构造 hstore 值。

hstore 函数接受一个或两个参数,如 PostgreSQL 文档中所述。

例如:

from sqlalchemy.dialects.postgresql import array, hstore

select(hstore("key1", "value1"))

select(
    hstore(
        array(["key1", "key2", "key3"]),
        array(["value1", "value2", "value3"]),
    )
)

另请参阅

HSTORE - PostgreSQL HSTORE 数据类型。

attribute sqlalchemy.dialects.postgresql.hstore.inherit_cache: bool | None = True

指示此 HasCacheKey 实例是否应使用其直接超类使用的缓存键生成方案。

该属性默认为 None,这表示构造尚未考虑它是否适合参与缓存;这在功能上等同于将值设置为 False,但也会发出警告。

如果与对象对应的 SQL 不会根据此类的本地属性(而不是其超类)而更改,则可以在特定类上将此标志设置为 True

另请参阅

为自定义构造启用缓存支持 - 关于为第三方或用户定义的 SQL 构造设置 HasCacheKey.inherit_cache 属性的一般指南。

attribute sqlalchemy.dialects.postgresql.hstore.type

的别名 HSTORE

class sqlalchemy.dialects.postgresql.to_tsvector

PostgreSQL to_tsvector SQL 函数。

此函数自动应用 REGCONFIG 参数的类型转换,以使用 REGCONFIG 数据类型,并应用 TSVECTOR 的返回类型。

假设 PostgreSQL 方言已导入,无论是通过调用 from sqlalchemy.dialects import postgresql 还是通过使用 create_engine("postgresql...") 创建 PostgreSQL 引擎,当调用 sqlalchemy.func.to_tsvector() 时,将自动使用 to_tsvector,确保在编译和执行时使用正确的参数和返回类型处理程序。

2.0.0rc1 版本新增。

类签名

class sqlalchemy.dialects.postgresql.to_tsvector (sqlalchemy.dialects.postgresql.ext._regconfig_fn)

class sqlalchemy.dialects.postgresql.to_tsquery

PostgreSQL to_tsquery SQL 函数。

此函数自动应用 REGCONFIG 参数的类型转换,以使用 REGCONFIG 数据类型,并应用 TSQUERY 的返回类型。

假设 PostgreSQL 方言已导入,无论是通过调用 from sqlalchemy.dialects import postgresql 还是通过使用 create_engine("postgresql...") 创建 PostgreSQL 引擎,当调用 sqlalchemy.func.to_tsquery() 时,将自动使用 to_tsquery,确保在编译和执行时使用正确的参数和返回类型处理程序。

2.0.0rc1 版本新增。

类签名

class sqlalchemy.dialects.postgresql.to_tsquery (sqlalchemy.dialects.postgresql.ext._regconfig_fn)

class sqlalchemy.dialects.postgresql.plainto_tsquery

PostgreSQL plainto_tsquery SQL 函数。

此函数自动应用 REGCONFIG 参数的类型转换,以使用 REGCONFIG 数据类型,并应用 TSQUERY 的返回类型。

假设 PostgreSQL 方言已导入,无论是通过调用 from sqlalchemy.dialects import postgresql 还是通过使用 create_engine("postgresql...") 创建 PostgreSQL 引擎,当调用 sqlalchemy.func.plainto_tsquery() 时,将自动使用 plainto_tsquery,确保在编译和执行时使用正确的参数和返回类型处理程序。

2.0.0rc1 版本新增。

类签名

class sqlalchemy.dialects.postgresql.plainto_tsquery (sqlalchemy.dialects.postgresql.ext._regconfig_fn)

class sqlalchemy.dialects.postgresql.phraseto_tsquery

PostgreSQL phraseto_tsquery SQL 函数。

此函数自动应用 REGCONFIG 参数的类型转换,以使用 REGCONFIG 数据类型,并应用 TSQUERY 的返回类型。

假设 PostgreSQL 方言已导入,无论是通过调用 from sqlalchemy.dialects import postgresql 还是通过使用 create_engine("postgresql...") 创建 PostgreSQL 引擎,当调用 sqlalchemy.func.phraseto_tsquery() 时,将自动使用 phraseto_tsquery,确保在编译和执行时使用正确的参数和返回类型处理程序。

2.0.0rc1 版本新增。

类签名

class sqlalchemy.dialects.postgresql.phraseto_tsquery (sqlalchemy.dialects.postgresql.ext._regconfig_fn)

class sqlalchemy.dialects.postgresql.websearch_to_tsquery

PostgreSQL websearch_to_tsquery SQL 函数。

此函数自动应用 REGCONFIG 参数的类型转换,以使用 REGCONFIG 数据类型,并应用 TSQUERY 的返回类型。

假设 PostgreSQL 方言已导入,无论是通过调用 from sqlalchemy.dialects import postgresql 还是通过使用 create_engine("postgresql...") 创建 PostgreSQL 引擎,当调用 sqlalchemy.func.websearch_to_tsquery() 时,将自动使用 websearch_to_tsquery,确保在编译和执行时使用正确的参数和返回类型处理程序。

2.0.0rc1 版本新增。

类签名

class sqlalchemy.dialects.postgresql.websearch_to_tsquery (sqlalchemy.dialects.postgresql.ext._regconfig_fn)

class sqlalchemy.dialects.postgresql.ts_headline

PostgreSQL ts_headline SQL 函数。

此函数自动应用 REGCONFIG 参数的类型转换,以使用 REGCONFIG 数据类型,并应用 TEXT 的返回类型。

假设 PostgreSQL 方言已导入,无论是通过调用 from sqlalchemy.dialects import postgresql 还是通过使用 create_engine("postgresql...") 创建 PostgreSQL 引擎,当调用 sqlalchemy.func.ts_headline() 时,将自动使用 ts_headline,确保在编译和执行时使用正确的参数和返回类型处理程序。

2.0.0rc1 版本新增。

类签名

class sqlalchemy.dialects.postgresql.ts_headline (sqlalchemy.dialects.postgresql.ext._regconfig_fn)

PostgreSQL 约束类型

SQLAlchemy 通过 ExcludeConstraint 类支持 PostgreSQL EXCLUDE 约束

对象名称 描述

ExcludeConstraint

表级别的 EXCLUDE 约束。

class sqlalchemy.dialects.postgresql.ExcludeConstraint

表级别的 EXCLUDE 约束。

定义 EXCLUDE 约束,如 PostgreSQL 文档中所述。

成员

__init__()

method sqlalchemy.dialects.postgresql.ExcludeConstraint.__init__(*elements, **kw)

创建 ExcludeConstraint 对象。

例如:

const = ExcludeConstraint(
    (Column("period"), "&&"),
    (Column("group"), "="),
    where=(Column("group") != "some group"),
    ops={"group": "my_operator_class"},
)

该约束通常直接嵌入到 Table 构造中,或稍后使用 append_constraint() 添加

some_table = Table(
    "some_table",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("period", TSRANGE()),
    Column("group", String),
)

some_table.append_constraint(
    ExcludeConstraint(
        (some_table.c.period, "&&"),
        (some_table.c.group, "="),
        where=some_table.c.group != "some group",
        name="some_table_excl_const",
        ops={"group": "my_operator_class"},
    )
)

此示例中定义的排除约束需要 btree_gist 扩展,可以使用命令 CREATE EXTENSION btree_gist; 创建。

参数:
  • *elements

    两个元组的序列,形式为 (column, operator),其中 “column” 是 Column 对象,或 SQL 表达式元素(例如 func.int8range(table.from, table.to)),或列的名称(字符串),“operator” 是包含要使用的运算符的字符串(例如 “&&”“=”)。

    为了在 Column 对象不可用时指定列名,同时确保任何必要的引用规则生效,应使用临时的 Columncolumn() 对象。column 也可以是作为 literal_column()text() 传递的字符串 SQL 表达式

  • name – 可选,此约束在数据库中的名称。

  • deferrable – 可选布尔值。如果设置,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。

  • initially – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY <value>。

  • using – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 USING <index_method>。默认为 ‘gist’。

  • where

    可选的 SQL 表达式构造或字面 SQL 字符串。如果设置,则在为此约束发出 DDL 时发出 WHERE <predicate>。

    警告

    可以将 ExcludeConstraint.where 参数作为 Python 字符串参数传递给 ExcludeConstraint,该参数将被视为 受信任的 SQL 文本 并按给定方式呈现。请勿将不受信任的输入传递给此参数

  • ops

    可选字典。用于为元素定义运算符类;其工作方式与为 Index 构造指定的 postgresql_ops 参数相同。

    1.3.21 版本新增。

    另请参阅

    运算符类 - 关于如何指定 PostgreSQL 运算符类的一般描述。

例如

from sqlalchemy.dialects.postgresql import ExcludeConstraint, TSRANGE


class RoomBooking(Base):
    __tablename__ = "room_booking"

    room = Column(Integer(), primary_key=True)
    during = Column(TSRANGE())

    __table_args__ = (ExcludeConstraint(("room", "="), ("during", "&&")),)

PostgreSQL DML 构造

对象名称 描述

insert(table)

构造一个 PostgreSQL 特定的变体 Insert 构造。

Insert

PostgreSQL 特定的 INSERT 实现。

function sqlalchemy.dialects.postgresql.insert(table: _DMLTableArgument) Insert

构造一个 PostgreSQL 特定的变体 Insert 构造。

sqlalchemy.dialects.postgresql.insert() 函数创建一个 sqlalchemy.dialects.postgresql.Insert。此类基于与方言无关的 Insert 构造,后者可以使用 SQLAlchemy Core 中的 insert() 函数构造。

Insert 构造包括附加方法 Insert.on_conflict_do_update(), Insert.on_conflict_do_nothing()

class sqlalchemy.dialects.postgresql.Insert

PostgreSQL 特定的 INSERT 实现。

为 PG 特定的语法(例如 ON CONFLICT)添加方法。

Insert 对象是使用 sqlalchemy.dialects.postgresql.insert() 函数创建的。

attribute sqlalchemy.dialects.postgresql.Insert.excluded

为 ON CONFLICT 语句提供 excluded 命名空间

PG 的 ON CONFLICT 子句允许引用将要插入的行,称为 excluded。此属性提供此行中的所有列以供引用。

提示

Insert.excluded 属性是 ColumnCollection 的实例,它提供的接口与 Table.c 集合相同,如 访问表和列 中所述。 使用此集合,普通名称可以像属性一样访问(例如 stmt.excluded.some_column),但特殊名称和字典方法名称应使用索引访问来访问,例如 stmt.excluded["column name"]stmt.excluded["values"]。 有关更多示例,请参阅 ColumnCollection 的文档字符串。

另请参阅

INSERT…ON CONFLICT (Upsert) - 如何使用 Insert.excluded 的示例

attribute sqlalchemy.dialects.postgresql.Insert.inherit_cache: bool | None = False

指示此 HasCacheKey 实例是否应使用其直接超类使用的缓存键生成方案。

该属性默认为 None,这表示构造尚未考虑它是否适合参与缓存;这在功能上等同于将值设置为 False,但也会发出警告。

如果与对象对应的 SQL 不会根据此类的本地属性(而不是其超类)而更改,则可以在特定类上将此标志设置为 True

另请参阅

为自定义构造启用缓存支持 - 关于为第三方或用户定义的 SQL 构造设置 HasCacheKey.inherit_cache 属性的一般指南。

method sqlalchemy.dialects.postgresql.Insert.on_conflict_do_nothing(constraint: str | ColumnCollectionConstraint | Index | None = None, index_elements: Iterable[Column[Any] | str | DDLConstraintColumnRole] | None = None, index_where: WhereHavingRole | None = None) Self

为 ON CONFLICT 子句指定 DO NOTHING 操作。

constraintindex_elements 参数是可选的,但只能指定其中一个。

参数:
  • constraint – 表上唯一约束或排除约束的名称,或者如果约束对象具有 .name 属性,则为约束对象本身。

  • index_elements – 由字符串列名、Column 对象或其他列表达式对象组成的序列,这些对象将用于推断目标索引。

  • index_where – 可用于推断条件目标索引的附加 WHERE 条件。

method sqlalchemy.dialects.postgresql.Insert.on_conflict_do_update(constraint: str | ColumnCollectionConstraint | Index | None = None, index_elements: Iterable[Column[Any] | str | DDLConstraintColumnRole] | None = None, index_where: WhereHavingRole | None = None, set_: Mapping[Any, Any] | ColumnCollection[Any, Any] | None = None, where: WhereHavingRole | None = None) Self

为 ON CONFLICT 子句指定 DO UPDATE SET 操作。

constraintindex_elements 参数是必需的,但只能指定其中一个。

参数:
  • constraint – 表上唯一约束或排除约束的名称,或者如果约束对象具有 .name 属性,则为约束对象本身。

  • index_elements – 由字符串列名、Column 对象或其他列表达式对象组成的序列,这些对象将用于推断目标索引。

  • index_where – 可用于推断条件目标索引的附加 WHERE 条件。

  • set_

    一个字典或其他映射对象,其中键是目标表中列的名称,或者是 Column 对象或其他与目标表匹配的 ORM 映射列,值是表达式或字面量,指定要执行的 SET 操作。

    1.4 版本新增: Insert.on_conflict_do_update.set_ 参数支持来自目标 TableColumn 对象作为键。

    警告

    此字典考虑 Python 指定的默认 UPDATE 值或生成函数,例如使用 Column.onupdate 指定的值。这些值不会为 ON CONFLICT 样式的 UPDATE 执行,除非它们在 Insert.on_conflict_do_update.set_ 字典中手动指定。

  • where – 可选参数。表示 WHERE 子句的表达式对象,该子句限制受 DO UPDATE SET 影响的行。不满足 WHERE 条件的行将不会被更新(实际上对于这些行是 DO NOTHING)。

psycopg2

通过 psycopg2 驱动程序支持 PostgreSQL 数据库。

DBAPI

psycopg2 的文档和下载信息(如果适用)可在以下网址获取:https://pypi.ac.cn/project/psycopg2/

连接

连接字符串

postgresql+psycopg2://user:password@host:port/dbname[?key=value&key=value...]

psycopg2 连接参数

SQLAlchemy psycopg2 方言特有的关键字参数可以传递给 create_engine(),包括以下内容

提示

上面的关键字参数是方言关键字参数,这意味着它们作为显式关键字参数传递给 create_engine()

engine = create_engine(
    "postgresql+psycopg2://scott:tiger@localhost/test",
    isolation_level="SERIALIZABLE",
)

这些不应与 DBAPI 连接参数混淆,DBAPI 连接参数作为 create_engine.connect_args 字典的一部分传递,和/或在 URL 查询字符串中传递,如 自定义 DBAPI connect() 参数 / 连接时例程 部分所述。

SSL 连接

psycopg2 模块有一个名为 sslmode 的连接参数,用于控制其关于安全 (SSL) 连接的行为。默认值为 sslmode=prefer;它将尝试 SSL 连接,如果失败,则回退到未加密的连接。sslmode=require 可用于确保仅建立安全连接。有关更多可用选项,请查阅 psycopg2 / libpq 文档。

请注意,sslmode 是 psycopg2 特有的,因此它包含在连接 URI 中

engine = sa.create_engine(
    "postgresql+psycopg2://scott:tiger@192.168.0.199:5432/test?sslmode=require"
)

Unix 域连接

psycopg2 支持通过 Unix 域连接进行连接。当 URL 的 host 部分被省略时,SQLAlchemy 将 None 传递给 psycopg2,这指定了 Unix 域通信而不是 TCP/IP 通信

create_engine("postgresql+psycopg2://user:password@/dbname")

默认情况下,使用的套接字文件是连接到 /tmp 中的 Unix 域套接字,或者构建 PostgreSQL 时指定的任何套接字目录。可以通过将路径名传递给 psycopg2,使用 host 作为附加关键字参数来覆盖此值

create_engine(
    "postgresql+psycopg2://user:password@/dbname?host=/var/lib/postgresql"
)

警告

此处接受的格式允许在主 URL 中使用主机名,以及 “host” 查询字符串参数。当使用此 URL 格式时,初始主机将被静默忽略。也就是说,此 URL

engine = create_engine(
    "postgresql+psycopg2://user:password@myhost1/dbname?host=myhost2"
)

在上面,主机名 myhost1静默忽略并丢弃。 连接的主机是 myhost2 主机。

这是为了保持与 PostgreSQL 自身 URL 格式的某种程度的兼容性,该格式已被测试为以相同的方式运行,并且 PifPaf 等工具为此硬编码了两个主机名。

另请参阅

PQconnectdbParams

指定多个备用主机

psycopg2 在连接字符串中支持多个连接点。当 host 参数在 URL 的查询部分中多次使用时,SQLAlchemy 将创建一个包含提供的主机和端口信息的单个字符串以进行连接。令牌可以包含 host::port 或仅 host;在后一种情况下,默认端口由 libpq 选择。在下面的示例中,指定了三个主机连接,分别用于 HostA::PortA、连接到默认端口的 HostBHostC::PortC

create_engine(
    "postgresql+psycopg2://user:password@/dbname?host=HostA:PortA&host=HostB&host=HostC:PortC"
)

作为替代方案,也可以使用 libpq 查询字符串格式;这会将 hostport 指定为带有逗号分隔列表的单个查询字符串参数 - 可以通过在逗号分隔列表中指示空值来选择默认端口

create_engine(
    "postgresql+psycopg2://user:password@/dbname?host=HostA,HostB,HostC&port=PortA,,PortC"
)

使用任一 URL 样式,都会根据可配置的策略尝试连接到每个主机,该策略可以使用 libpq target_session_attrs 参数进行配置。根据 libpq,这默认为 any,表示然后尝试连接到每个主机,直到连接成功。其他策略包括 primaryprefer-standby 等。PostgreSQL 在 libpq 连接字符串 中记录了完整列表。

例如,要使用 primary 策略指示两个主机

create_engine(
    "postgresql+psycopg2://user:password@/dbname?host=HostA:PortA&host=HostB&host=HostC:PortC&target_session_attrs=primary"
)

1.4.40 版本更改: 修复了 psycopg2 多主机格式中的端口规范,以前端口在此上下文中未被正确解释。现在也支持 libpq 逗号分隔格式。

1.3.20 版本新增: 支持 PostgreSQL 连接字符串中的多个主机。

另请参阅

libpq 连接字符串 - 请参考 libpq 文档中的此部分,以获取有关多主机支持的完整背景信息。

空 DSN 连接 / 环境变量连接

psycopg2 DBAPI 可以通过将空 DSN 传递给 libpq 客户端库来连接到 PostgreSQL,默认情况下,这表示连接到为 “信任” 连接打开的 localhost PostgreSQL 数据库。可以使用以 PG_... 为前缀的特定环境变量集进一步定制此行为,这些环境变量由 libpq 消耗,以代替连接字符串的任何或所有元素。

对于此形式,可以传递不包含任何元素(除了初始方案)的 URL

engine = create_engine("postgresql+psycopg2://")

在上述形式中,一个空白的 “dsn” 字符串被传递给 psycopg2.connect() 函数,这反过来表示传递给 libpq 的空 DSN。

1.3.2 版本新增: 支持使用 psycopg2 的无参数连接。

另请参阅

环境变量 - PostgreSQL 文档,介绍如何使用 PG_... 环境变量进行连接。

每个语句/连接的执行选项

以下 DBAPI 特定的选项在使用 Connection.execution_options()Executable.execution_options()Query.execution_options() 时被遵循,除了那些不特定于 DBAPI 的选项之外

  • isolation_level - 设置 Connection 生命周期内的事务隔离级别(只能在连接上设置,不能在语句或查询上设置)。请参阅 Psycopg2 事务隔离级别

  • stream_results - 启用或禁用 psycopg2 服务器端游标的使用 - 此功能使用 “命名” 游标与特殊结果处理方法相结合,以便结果行不会被完全缓冲。默认为 False,这意味着默认情况下游标会被缓冲。

  • max_row_buffer - 当使用 stream_results 时,一个整数值,指定一次要缓冲的最大行数。这由 BufferedRowCursorResult 解释,如果省略,缓冲区将增长到最终一次存储 1000 行。

    1.4 版本更改: max_row_buffer 大小现在可以大于 1000,并且缓冲区将增长到该大小。

Psycopg2 快速执行助手

现代版本的 psycopg2 包括一个名为 快速执行助手 的功能,在基准测试中已证明可以提高 psycopg2 的 executemany() 性能,主要是在 INSERT 语句中,至少提高一个数量级。

SQLAlchemy 实现了 “插入多个值” 处理程序的本机形式,它将重写单行 INSERT 语句,以便在一个扩展的 VALUES 子句中容纳多个值;此处理程序等效于 psycopg2 的 execute_values() 处理程序;有关此功能及其配置的概述,请参阅 INSERT 语句的 “插入多个值” 行为

2.0 版本新增: 将 psycopg2 的 execute_values() 快速执行助手替换为名为 insertmanyvalues 的本机 SQLAlchemy 机制。

psycopg2 方言保留了使用 psycopg2 特定的 execute_batch() 功能的能力,尽管预计这不是一个广泛使用的功能。可以使用 executemany_mode 标志启用此扩展的使用,该标志可以传递给 create_engine()

engine = create_engine(
    "postgresql+psycopg2://scott:tiger@host/dbname",
    executemany_mode="values_plus_batch",
)

executemany_mode 的可能选项包括

  • values_only - 这是默认值。SQLAlchemy 的本机 insertmanyvalues 处理程序用于限定 INSERT 语句,假设 create_engine.use_insertmanyvalues 保留其默认值 True。此处理程序重写简单的 INSERT 语句以包含多个 VALUES 子句,以便可以使用一个语句插入多个参数集。

  • 'values_plus_batch'- SQLAlchemy 的本机 insertmanyvalues 处理程序用于限定 INSERT 语句,假设 create_engine.use_insertmanyvalues 保留其默认值 True。然后,psycopg2 的 execute_batch() 处理程序用于在使用多个参数集执行时限定 UPDATE 和 DELETE 语句。当使用此模式时,CursorResult.rowcount 属性将不包含针对 UPDATE 和 DELETE 语句的 executemany 样式执行的值。

2.0 版本更改: 从 psycopg2 executemany_mode 中删除了 'batch''None' 选项。现在通过 create_engine.use_insertmanyvalues 引擎级参数配置 INSERT 语句的批处理控制。

术语 “限定语句” 是指正在执行的语句是 Core insert()update()delete() 构造,而不是纯文本 SQL 字符串或使用 text() 构造的字符串。它也不能是特殊的 “扩展” 语句,例如 “ON CONFLICT” “upsert” 语句。当使用 ORM 时,ORM 刷新过程使用的所有 insert/update/delete 语句都是限定的。

psycopg2 “batch” 策略的 “页面大小” 可以通过使用 executemany_batch_page_size 参数来影响,该参数默认为 100。

对于 “insertmanyvalues” 功能,可以使用 create_engine.insertmanyvalues_page_size 参数来控制页面大小,该参数默认为 1000。下面是修改这两个参数的示例

engine = create_engine(
    "postgresql+psycopg2://scott:tiger@host/dbname",
    executemany_mode="values_plus_batch",
    insertmanyvalues_page_size=5000,
    executemany_batch_page_size=500,
)

另请参阅

INSERT 语句的 “插入多个值” 行为 - 关于 “insertmanyvalues” 的背景信息

发送多个参数 - 关于使用 Connection 对象以使其能够使用 DBAPI .executemany() 方法的方式执行语句的一般信息。

Psycopg2 的 Unicode 支持

psycopg2 DBAPI 驱动程序透明地支持 Unicode 数据。

可以按照以下方式控制 psycopg2 方言的客户端字符编码

  • 对于 PostgreSQL 9.1 及更高版本,可以在数据库 URL 中传递 client_encoding 参数;此参数由底层 libpq PostgreSQL 客户端库使用

    engine = create_engine(
        "postgresql+psycopg2://user:pass@host/dbname?client_encoding=utf8"
    )

    或者,可以使用 create_engine.connect_args 传递上述 client_encoding 值,以便与 libpq 建立程序化连接

    engine = create_engine(
        "postgresql+psycopg2://user:pass@host/dbname",
        connect_args={"client_encoding": "utf8"},
    )
  • 对于所有 PostgreSQL 版本,psycopg2 支持客户端编码值,该值将在首次建立数据库连接时传递给数据库连接。SQLAlchemy psycopg2 方言支持使用传递给 create_engine()client_encoding 参数来实现此目的

    engine = create_engine(
        "postgresql+psycopg2://user:pass@host/dbname", client_encoding="utf8"
    )

    提示

    上述 client_encoding 参数在外观上与在 create_engine.connect_args 字典中使用该参数非常相似;上面的区别在于该参数由 psycopg2 使用,并使用 SET client_encoding TO 'utf8' 传递到数据库连接;在前面提到的样式中,该参数而是通过 psycopg2 传递并由 libpq 库使用。

  • 设置 PostgreSQL 数据库客户端编码的常用方法是确保在服务器端的 postgresql.conf 文件中配置它;这是为所有数据库编码一致的服务器设置编码的推荐方法。

    # postgresql.conf file
    
    # client_encoding = sql_ascii # actually, defaults to database
    # encoding
    client_encoding = utf8

事务

psycopg2 方言完全支持 SAVEPOINT 和两阶段提交操作。

Psycopg2 事务隔离级别

正如在事务隔离级别中讨论的那样,所有 PostgreSQL 方言都支持通过传递给 create_engine()isolation_level 参数以及 Connection.execution_options() 使用的 isolation_level 参数来设置事务隔离级别。当使用 psycopg2 方言时,这些选项使用 psycopg2 的 set_isolation_level() 连接方法,而不是发出 PostgreSQL 指令;这是因为无论如何,psycopg2 的 API 级别设置始终在每个事务开始时发出。

psycopg2 方言支持以下隔离级别常量

  • READ COMMITTED

  • READ UNCOMMITTED

  • REPEATABLE READ

  • SERIALIZABLE

  • AUTOCOMMIT

NOTICE 日志记录

psycopg2 方言将通过 sqlalchemy.dialects.postgresql logger 记录 PostgreSQL NOTICE 消息。当此 logger 设置为 logging.INFO 级别时,将记录 notice 消息

import logging

logging.getLogger("sqlalchemy.dialects.postgresql").setLevel(logging.INFO)

上面假设日志记录是在外部配置的。如果不是这种情况,则必须使用诸如 logging.basicConfig() 之类的配置

import logging

logging.basicConfig()  # log messages to stdout
logging.getLogger("sqlalchemy.dialects.postgresql").setLevel(logging.INFO)

另请参阅

Logging HOWTO - 在 python.org 网站上

HSTORE 类型

psycopg2 DBAPI 包括一个扩展,用于本地处理 HSTORE 类型的编组。当使用 psycopg2 版本 2.4 或更高版本,并且检测到目标数据库已设置 HSTORE 类型以供使用时,SQLAlchemy psycopg2 方言将默认启用此扩展。换句话说,当方言建立第一个连接时,会执行如下序列:

  1. 使用 psycopg2.extras.HstoreAdapter.get_oids() 请求可用的 HSTORE oids。如果此函数返回 HSTORE 标识符列表,则我们确定 HSTORE 扩展存在。如果安装的 psycopg2 版本低于 2.4,则会跳过此函数。

  2. 如果 use_native_hstore 标志处于其默认值 True,并且我们已检测到 HSTORE oids 可用,则将为所有连接调用 psycopg2.extensions.register_hstore() 扩展。

register_hstore() 扩展的效果是所有 Python 字典都被接受为参数,而不管 SQL 中目标列的类型如何。字典由此扩展转换为文本 HSTORE 表达式。如果不需要此行为,请通过将 use_native_hstore 设置为 False 来禁用 hstore 扩展,如下所示:

engine = create_engine(
    "postgresql+psycopg2://scott:tiger@localhost/test",
    use_native_hstore=False,
)

当不使用 psycopg2.extensions.register_hstore() 扩展时,仍然支持 HSTORE 类型。这仅仅意味着 Python 字典和 HSTORE 字符串格式之间的强制转换(在参数侧和结果侧)将在 SQLAlchemy 自己的编组逻辑中进行,而不是在可能性能更高的 psycopg2 中进行。

psycopg

通过 psycopg(又名 psycopg 3)驱动程序支持 PostgreSQL 数据库。

DBAPI

psycopg(又名 psycopg 3)的文档和下载信息(如果适用)可在以下网址获得:https://pypi.ac.cn/project/psycopg/

连接

连接字符串

postgresql+psycopg://user:password@host:port/dbname[?key=value&key=value...]

psycopgpsycopg 数据库驱动程序版本 3 的包和模块名称,以前称为 psycopg2。此驱动程序与其 psycopg2 前身有很大不同,因此 SQLAlchemy 通过完全独立的方言支持它;对于 psycopg2 的支持预计将持续存在,只要该包继续为现代 Python 版本工作,并且仍然是 postgresql:// 方言系列的默认方言。

SQLAlchemy psycopg 方言在同一方言名称下提供同步和异步实现。根据引擎的创建方式选择正确的版本

  • 使用 postgresql+psycopg://... 调用 create_engine() 将自动选择同步版本,例如:

    from sqlalchemy import create_engine
    
    sync_engine = create_engine(
        "postgresql+psycopg://scott:tiger@localhost/test"
    )
  • 使用 postgresql+psycopg://... 调用 create_async_engine() 将自动选择异步版本,例如:

    from sqlalchemy.ext.asyncio import create_async_engine
    
    asyncio_engine = create_async_engine(
        "postgresql+psycopg://scott:tiger@localhost/test"
    )

异步版本的方言也可以使用 psycopg_async 后缀显式指定,如下所示:

from sqlalchemy.ext.asyncio import create_async_engine

asyncio_engine = create_async_engine(
    "postgresql+psycopg_async://scott:tiger@localhost/test"
)

另请参阅

psycopg2 - SQLAlchemy psycopg 方言与其 psycopg2 方言共享大部分行为。更多文档可在此处找到。

使用不同的 Cursor 类

psycopg 和旧的 psycopg2 之间的区别之一是绑定参数的处理方式:psycopg2 将在客户端绑定它们,而 psycopg 默认将在服务器端绑定它们。

可以通过在创建引擎时将 cursor_factory 指定为 ClientCursor 来配置 psycopg 执行客户端绑定:

from psycopg import ClientCursor

client_side_engine = create_engine(
    "postgresql+psycopg://...",
    connect_args={"cursor_factory": ClientCursor},
)

同样,当使用异步引擎时,可以指定 AsyncClientCursor

from psycopg import AsyncClientCursor

client_side_engine = create_async_engine(
    "postgresql+psycopg://...",
    connect_args={"cursor_factory": AsyncClientCursor},
)

另请参阅

客户端绑定游标

pg8000

通过 pg8000 驱动程序支持 PostgreSQL 数据库。

DBAPI

pg8000 的文档和下载信息(如果适用)可在以下网址获得:https://pypi.ac.cn/project/pg8000/

连接

连接字符串

postgresql+pg8000://user:password@host:port/dbname[?key=value&key=value...]

在 1.4 版本中更改:pg8000 方言已更新至 1.16.6 及更高版本,并且再次成为 SQLAlchemy 持续集成的一部分,具有完整的功能支持。

Unicode

pg8000 将使用 PostgreSQL client_encoding 参数在它和服务器之间编码/解码字符串值;默认情况下,这是 postgresql.conf 文件中的值,通常默认为 SQL_ASCII。通常,可以将其更改为 utf-8,作为更有用的默认值

# client_encoding = sql_ascii # actually, defaults to database encoding
client_encoding = utf8

可以通过执行 SQL 来为会话覆盖 client_encoding

SET CLIENT_ENCODING TO 'utf8';

SQLAlchemy 将基于传递给 create_engine()client_encoding 参数的值,在所有新连接上执行此 SQL:

engine = create_engine(
    "postgresql+pg8000://user:pass@host/dbname", client_encoding="utf8"
)

SSL 连接

pg8000 接受一个 Python SSLContext 对象,可以使用 create_engine.connect_args 字典指定:

import ssl

ssl_context = ssl.create_default_context()
engine = sa.create_engine(
    "postgresql+pg8000://scott:tiger@192.168.0.199/test",
    connect_args={"ssl_context": ssl_context},
)

如果服务器使用自动生成的自签名证书或与主机名不匹配的证书(从客户端的角度来看),则可能还需要禁用主机名检查:

import ssl

ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
engine = sa.create_engine(
    "postgresql+pg8000://scott:tiger@192.168.0.199/test",
    connect_args={"ssl_context": ssl_context},
)

pg8000 事务隔离级别

pg8000 方言提供与 psycopg2 方言相同的隔离级别设置。

  • READ COMMITTED

  • READ UNCOMMITTED

  • REPEATABLE READ

  • SERIALIZABLE

  • AUTOCOMMIT

asyncpg

通过 asyncpg 驱动程序支持 PostgreSQL 数据库。

DBAPI

asyncpg 的文档和下载信息(如果适用)可在以下网址获得:https://magicstack.github.io/asyncpg/

连接

连接字符串

postgresql+asyncpg://user:password@host:port/dbname[?key=value&key=value...]

asyncpg 方言是 SQLAlchemy 的第一个 Python asyncio 方言。

asyncpg 方言使用特殊的 asyncio 中介层,可以用作 SQLAlchemy asyncio 扩展包的后端。

此方言通常应仅与 create_async_engine() 引擎创建函数一起使用

from sqlalchemy.ext.asyncio import create_async_engine

engine = create_async_engine(
    "postgresql+asyncpg://user:pass@hostname/dbname"
)

1.4 版本新增。

注意

默认情况下,asyncpg 不解码 jsonjsonb 类型,而是将它们作为字符串返回。SQLAlchemy 为 jsonjsonb 类型设置默认类型解码器,使用 python 内置的 json.loads 函数。可以通过在使用 create_engine()create_async_engine() 创建引擎时设置属性 json_deserializer 来更改使用的 json 实现。

多主机连接

asyncpg 方言具有与 psycopg2 和 psycopg 方言相同的方式支持多个备用主机。语法相同,使用 host=<host>:<port> 组合作为附加的查询字符串参数;但是,没有默认端口,因此所有主机都必须存在完整的端口号,否则会引发异常

engine = create_async_engine(
    "postgresql+asyncpg://user:password@/dbname?host=HostA:5432&host=HostB:5432&host=HostC:5432"
)

有关此语法的完整背景信息,请参阅指定多个备用主机

2.0.18 版本新增。

预处理语句缓存

asyncpg SQLAlchemy 方言对所有语句使用 asyncpg.connection.prepare()。预处理语句对象在构造后会被缓存,这似乎为语句调用带来了 10% 或更高的性能提升。缓存是基于每个 DBAPI 连接的,这意味着预处理语句的主要存储在连接池中池化的 DBAPI 连接中。此缓存的大小默认为每个 DBAPI 连接 100 个语句,可以使用 prepared_statement_cache_size DBAPI 参数进行调整(请注意,虽然此参数由 SQLAlchemy 实现,但它是 asyncpg 方言的 DBAPI 模拟部分的一部分,因此被视为 DBAPI 参数,而不是方言参数)

engine = create_async_engine(
    "postgresql+asyncpg://user:pass@hostname/dbname?prepared_statement_cache_size=500"
)

要禁用预处理语句缓存,请使用零值:

engine = create_async_engine(
    "postgresql+asyncpg://user:pass@hostname/dbname?prepared_statement_cache_size=0"
)

在 1.4.0b2 版本中新增:为 asyncpg 添加了 prepared_statement_cache_size

警告

asyncpg 数据库驱动程序必然使用缓存来存储 PostgreSQL 类型 OID,当通过 DDL 操作更改自定义 PostgreSQL 数据类型(例如 ENUM 对象)时,这些缓存会变得陈旧。此外,SQLAlchemy 的驱动程序可选缓存的预处理语句本身,当已向 PostgreSQL 数据库发出 DDL 以修改特定预处理语句中涉及的表或其他对象时,也可能变得“陈旧”。

当代表 DDL 的语句在本地连接上发出时,SQLAlchemy asyncpg 方言将在其本地进程中使这些缓存失效,但这仅在单个 Python 进程/数据库引擎中可控。如果 DDL 更改是从其他数据库引擎和/或进程进行的,则运行中的应用程序可能会遇到 asyncpg 异常 InvalidCachedStatementError 和/或 InternalServerError("cache lookup failed for type <oid>"),如果它引用了对先前结构进行操作的池化数据库连接。当驱动程序引发这些异常时,SQLAlchemy asyncpg 方言将通过清除其内部缓存以及 asyncpg 驱动程序的缓存来从这些错误情况中恢复,但如果缓存的预处理语句或 asyncpg 类型缓存已过时,则无法阻止它们首先被引发,也无法在发生这些错误时重试语句,因为 PostgreSQL 事务已失效。

带有 PGBouncer 的预处理语句名称

默认情况下,asyncpg 按数字顺序枚举预处理语句,如果名称已被另一个预处理语句占用,则可能导致错误。如果您的应用程序使用数据库代理(例如 PgBouncer)来处理连接,则可能会出现此问题。一种可能的解决方法是使用动态预处理语句名称,asyncpg 现在通过语句名称的可选 name 值来支持动态预处理语句名称。这允许您生成自己的唯一名称,这些名称不会与现有名称冲突。为了实现这一点,您可以提供一个函数,该函数将在每次准备预处理语句时被调用:

from uuid import uuid4

engine = create_async_engine(
    "postgresql+asyncpg://user:pass@somepgbouncer/dbname",
    poolclass=NullPool,
    connect_args={
        "prepared_statement_name_func": lambda: f"__asyncpg_{uuid4()}__",
    },
)

警告

当使用 PGBouncer 时,为了防止应用程序中积累无用的预处理语句,重要的是使用 NullPool 池类,并将 PgBouncer 配置为在返回连接时使用 DISCARD。DISCARD 命令用于释放数据库连接持有的资源,包括预处理语句。如果没有正确的设置,预处理语句可能会迅速累积并导致性能问题。

禁用 PostgreSQL JIT 以改进 ENUM 数据类型处理

Asyncpg 在使用 PostgreSQL ENUM 数据类型时存在一个 问题,其中在新数据库连接创建时,可能会发出昂贵的查询以检索有关自定义类型的元数据,这已被证明会对性能产生负面影响。为了缓解此问题,可以使用传递给 create_async_engine() 的此设置从客户端禁用 PostgreSQL “jit” 设置:

engine = create_async_engine(
    "postgresql+asyncpg://user:password@localhost/tmp",
    connect_args={"server_settings": {"jit": "off"}},
)

psycopg2cffi

通过 psycopg2cffi 驱动程序支持 PostgreSQL 数据库。

DBAPI

psycopg2cffi 的文档和下载信息(如果适用)可在以下网址获得:https://pypi.ac.cn/project/psycopg2cffi/

连接

连接字符串

postgresql+psycopg2cffi://user:password@host:port/dbname[?key=value&key=value...]

psycopg2cffipsycopg2 的改编版本,使用 CFFI 作为 C 层。这使其适用于例如 PyPy。文档与 psycopg2 相同。