SqlAlchemy-2-0-中文文档-二十九-

SqlAlchemy 2.0 中文文档(二十九)

原文:docs.sqlalchemy.org/en/20/contents.html

方言

原文:docs.sqlalchemy.org/en/20/dialects/index.html

方言 是 SQLAlchemy 用来与各种类型的 DBAPI 实现和数据库通信的系统。以下各节包含每个后端使用的特定用法的参考文档和说明,以及各种 DBAPI 的说明。

所有方言都要求安装适当的 DBAPI 驱动程序。

包含的方言

  • PostgreSQL

  • MySQL 和 MariaDB

  • SQLite

  • Oracle

  • Microsoft SQL Server

包含的方言的支持级别

以下表格总结了每个包含的方言的支持级别。

包含的方言支持的数据库版本

数据库 在 CI 中完全测试 正常支持 尽力而为
Microsoft SQL Server 2017 2012+ 2005+
MySQL / MariaDB 5.6, 5.7, 8.0 / 10.8, 10.9 5.6+ / 10+ 5.0.2+ / 5.0.2+
Oracle 18c 11+ 9+
PostgreSQL 12, 13, 14, 15 9.6+ 9+
SQLite 3.36.0 3.12+ 3.7.16+

支持定义

在 CI 中完全测试

在 CI 中完全测试 表示已在 sqlalchemy CI 系统中进行测试并通过测试套件中的所有测试的版本。

正常支持

正常支持 表示大多数功能应该可以工作,但不是所有版本都在 ci 配置中进行测试,因此可能存在一些不受支持的边缘情况。我们将尝试修复影响这些版本的问题。

尽力而为

尽力而为 指我们尝试在其中支持基本功能,但在某些用例中可能存在不受支持的功能或错误。我们可能会接受相关问题的拉取请求以继续支持较旧的版本,这些请求会逐案审查。 ## 外部方言

目前为 SQLAlchemy 维护的外部方言项目包括:

数据库 方言
Actian Data Platform、Vector、Actian X、Ingres sqlalchemy-ingres
Amazon Athena pyathena
亚马逊 Redshift (通过 psycopg2) sqlalchemy-redshift
Apache Drill sqlalchemy-drill
Apache Druid pydruid
Apache Hive 和 Presto PyHive
Apache Solr sqlalchemy-solr
CockroachDB sqlalchemy-cockroachdb
CrateDB crate-python
EXASolution sqlalchemy_exasol
Elasticsearch(只读) elasticsearch-dbapi
Firebird sqlalchemy-firebird
Firebolt firebolt-sqlalchemy
Google BigQuery pybigquery
Google Sheets gsheets
IBM DB2 和 Informix ibm-db-sa
IBM Netezza Performance Server [1] nzalchemy
Impala impyla
Microsoft Access(通过 pyodbc) sqlalchemy-access
Microsoft SQL Server(通过 python-tds) sqlalchemy-tds
Microsoft SQL Server(通过 turbodbc) sqlalchemy-turbodbc
MonetDB [1] sqlalchemy-monetdb
OpenGauss openGauss-sqlalchemy
Rockset rockset-sqlalchemy
SAP ASE(前 Sybase 方言的分支) sqlalchemy-sybase
SAP Hana [1] sqlalchemy-hana
SAP Sybase SQL Anywhere sqlalchemy-sqlany
Snowflake snowflake-sqlalchemy
Teradata Vantage teradatasqlalchemy

| YugabyteDB | sqlalchemy-yugabytedb | ## 包含的方言

  • PostgreSQL

  • MySQL 和 MariaDB

  • SQLite

  • Oracle

  • Microsoft SQL Server

包含的方言的支持级别

下表总结了每个包含的方言的支持级别。

包含的方言的支持数据库版本

数据库 在 CI 中完全测试过 普通支持 尽力而为
Microsoft SQL Server 2017 2012+ 2005+
MySQL / MariaDB 5.6、5.7、8.0 / 10.8、10.9 5.6+ / 10+ 5.0.2+ / 5.0.2+
Oracle 18c 11+ 9+
PostgreSQL 12、13、14、15 9.6+ 9+
SQLite 3.36.0 3.12+ 3.7.16+

支持定义

在 CI 中完全测试过

在 CI 中完全测试过 表示经过在 sqlalchemy CI 系统中测试的版本,并通过测试套件中的所有测试。

普通支持

普通支持 表示大多数功能应该正常工作,但并非所有版本都在 ci 配置中进行测试,因此可能存在一些不受支持的边缘情况。我们将尝试修复影响这些版本的问题。

尽力而为

尽力而为 表示我们尽力在这些版本上支持基本功能,但在某些用例中可能会存在不支持的功能或错误。可能会接受带有相关问题的拉取请求,以继续支持旧版本,这些请求会根据具体情况进行审查。

已包括方言的支持级别

以下表总结了每个已包含方言的支持级别。

已包括方言的支持数据库版本

数据库 在 CI 中进行了全面测试 普通支持 尽力而为
Microsoft SQL Server 2017 2012+ 2005+
MySQL / MariaDB 5.6, 5.7, 8.0 / 10.8, 10.9 5.6+ / 10+ 5.0.2+ / 5.0.2+
Oracle 18c 11+ 9+
PostgreSQL 12、13、14、15 9.6+ 9+
SQLite 3.36.0 3.12+ 3.7.16+

支持定义

在 CI 中进行了全面测试

在 CI 中进行了全面测试 表示已经在 sqlalchemy CI 系统中测试并通过了测试套件中的所有测试的版本。

普通支持

普通支持 表示大多数功能应该可以正常工作,但并非所有版本都在 ci 配置中进行了测试,因此可能存在一些不受支持的边缘情况。我们将尝试修复影响这些版本的问题。

尽力而为

尽力而为 表明我们尽力在这些版本上支持基本功能,但在某些用例中可能会存在不支持的功能或错误。可能会接受带有相关问题的拉取请求,以继续支持旧版本,这些请求会根据具体情况进行审查。

外部方言

目前由 SQLAlchemy 维护的外部方言项目包括:

数据库 方言
Actian Data Platform、Vector、Actian X、Ingres sqlalchemy-ingres
亚马逊 Athena pyathena
Amazon Redshift(通过 psycopg2) sqlalchemy-redshift
Apache Drill sqlalchemy-drill
Apache Druid pydruid
Apache Hive 和 Presto PyHive
Apache Solr sqlalchemy-solr
CockroachDB sqlalchemy-cockroachdb
CrateDB crate-python
EXASolution sqlalchemy_exasol
Elasticsearch(只读) elasticsearch-dbapi
Firebird sqlalchemy-firebird
Firebolt firebolt-sqlalchemy
Google BigQuery pybigquery
Google Sheets gsheets
IBM DB2 and Informix ibm-db-sa
IBM Netezza Performance Server [1] nzalchemy
Impala impyla
Microsoft Access (via pyodbc) sqlalchemy-access
Microsoft SQL Server (via python-tds) sqlalchemy-tds
Microsoft SQL Server (via turbodbc) sqlalchemy-turbodbc
MonetDB [1] sqlalchemy-monetdb
OpenGauss openGauss-sqlalchemy
Rockset rockset-sqlalchemy
SAP ASE (fork of former Sybase dialect) sqlalchemy-sybase
SAP Hana [1] sqlalchemy-hana
SAP Sybase SQL Anywhere sqlalchemy-sqlany
Snowflake snowflake-sqlalchemy
Teradata Vantage teradatasqlalchemy
YugabyteDB sqlalchemy-yugabytedb

PostgreSQL

原文:docs.sqlalchemy.org/en/20/dialects/postgresql.html

对 PostgreSQL 数据库的支持。

以下表总结了当前数据库发布版本的支持水平。

支持的 PostgreSQL 版本

支持类型 版本
CI 中完全测试通过 12, 13, 14, 15
正常支持 9.6+
最佳尝试 9+

DBAPI 支持

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

  • psycopg2

  • psycopg (又名 psycopg 3)

  • pg8000

  • asyncpg

  • psycopg2cffi

序列/SERIAL/IDENTITY

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

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

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

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

PostgreSQL 10 及以上版本的 IDENTITY 列

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

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 的出现替换为 IDENTITY:

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`连接执行选项,可以在每个语句基础上启用服务器端游标:

```py
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 连接对象上的.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

请参阅

设置事务隔离级别,包括 DBAPI 自动提交

设置 READ ONLY / DEFERRABLE

Psycopg2 事务隔离级别

pg8000 事务隔离级别 ## 设置 READ ONLY / DEFERRABLE

大多数 PostgreSQL 方言支持设置事务的 “READ ONLY” 和 “DEFERRABLE” 特性,这是隔离级别设置的补充。通过使用 Connection.execution_options() 方法并传递 postgresql_readonlypostgresql_deferrable 标志,可以同时或独立地建立这两个属性与隔离级别。下面的示例说明了在设置 “READ ONLY” 和 “DEFERRABLE” 的同时传递 "SERIALIZABLE" 隔离级别:

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()事件添加了额外的状态参数,并确保该事件为所有“reset”发生而调用,因此它适合作为自定义“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 连接进行回滚时不会被回滚。

另请参见

为新连接设置默认模式 - 在用 MetaData 描述数据库文档中 ## 远程模式表内省和 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对象通过外键约束引用的表,必须决定在当前search_path成员也是该远程表的模式名称的情况下,如何在这些远程表中表示.schema

默认情况下,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的成员,然而当我们将test_schema添加到 PG 的search_path然后询问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选项,该选项可以作为特定于方言的参数指定给Table以及MetaData.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 网站上。

插入/更新…返回

该方言支持 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())

插入…冲突时执行(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用于直接指定索引而不是推断它。这可以是唯一约束的名称、主键约束或索引:

    >>> 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_ 参数指定。该参数接受一个字典,其中包含更新的直接值:

>>> 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 端的默认更新值或生成函数,例如使用 Column.onupdate 指定的值。这些值将不会被用于 ON CONFLICT 类型的 UPDATE,除非它们在 Insert.on_conflict_do_update.set_ 字典中手动指定。

使用排除的 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 
```  ## 全文搜索

PostgreSQL 的全文搜索系统可通过`func`命名空间来使用,结合使用自定义运算符通过`Operators.bool_op()`方法。对于一些简单情况并具有一定的跨后端兼容性,也可以使用`Operators.match()`运算符。

### 使用`match()`进行简单纯文本匹配

`Operators.match()`运算符提供跨兼容的简单文本匹配。对于 PostgreSQL 后端,它被硬编码为使用`@@`运算符与`plainto_tsquery()` PostgreSQL 函数结合生成表达式。

在 PostgreSQL 方言中,类似以下表达式:

```py
select(sometable.c.text.match("search string"))

将发送到数据库:

SELECT text @@ plainto_tsquery('search string') FROM table

在上面,将纯字符串传递给Operators.match()将自动使用plainto_tsquery()来指定 tsquery 的类型。这为Operators.match()在其他后端与基本数据库跨兼容性建立了基础。

从 2.0 版本开始更改:PostgreSQL 方言与Operators.match()一起使用的默认 tsquery 生成函数是plainto_tsquery()

要精确呈现 1.4 中呈现的内容,请使用以下形式:

from sqlalchemy import func

select(
    sometable.c.text.bool_op("@@")(func.to_tsquery("search string"))
)

将发出:

SELECT text @@ to_tsquery('search string') FROM table

直接使用 PostgreSQL 全文本函数和运算符

超出简单使用Operators.match()的文本搜索操作可能会利用func命名空间来生成 PostgreSQL 全文本函数,结合Operators.bool_op()来生成任何布尔运算符。

例如,查询:

select(
    func.to_tsquery('cat').bool_op("@>")(func.to_tsquery('cat & rat'))
)

将生成:

SELECT  to_tsquery('cat')  @>  to_tsquery('cat & rat')

TSVECTOR类型可以提供显式的 CAST:

from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy import select, cast
select(cast("some text", TSVECTOR))

生成等效于的语句:

SELECT CAST('some text' AS TSVECTOR) AS anon_1

PostgreSQL 方言通过扩展 func 命名空间来设置大多数全文搜索函数的正确参数和返回类型。假定已导入 sqlalchemy.dialects.postgresql 包,或者使用 postgresql 方言调用了 create_engine(),则这些函数将自动由 sqlalchemy.sql.expression.func 命名空间使用。这些函数在以下位置有文档:

  • to_tsvector

  • to_tsquery

  • plainto_tsquery

  • phraseto_tsquery

  • websearch_to_tsquery

  • ts_headline

使用 match() 或自定义运算符指定“regconfig”

PostgreSQL 的 plainto_tsquery() 函数接受一个可选的“regconfig”参数,用于指示 PostgreSQL 使用特定的预先计算的 GIN 或 GiST 索引来执行搜索。当使用 Operators.match() 时,可以使用 postgresql_regconfig 参数指定此额外参数,例如:

select(mytable.c.id).where(
    mytable.c.title.match('somestring', postgresql_regconfig='english')
)

这将产生:

SELECT mytable.id FROM mytable
WHERE mytable.title @@ plainto_tsquery('english', 'somestring')

使用其他 PostgreSQL 搜索函数时,可以直接传递“regconfig”参数作为初始参数:

select(mytable.c.id).where(
    func.to_tsvector("english", mytable.c.title).bool_op("@@")(
        func.to_tsquery("english", "somestring")
    )
)

生成等效语句:

SELECT mytable.id FROM mytable
WHERE to_tsvector('english', mytable.title) @@
    to_tsquery('english', 'somestring')

建议您使用 PostgreSQL 的 EXPLAIN ANALYZE... 工具,以确保您使用 SQLAlchemy 生成的查询充分利用了您可能为全文搜索创建的任何索引。

另请参阅

全文搜索 - PostgreSQL 文档中

仅来自…

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

# 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 特定索引选项

提供了针对 PostgreSQL 方言的 Index 构造的几个扩展。

覆盖索引

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 中的新功能。

部分索引

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

Index('my_index', my_table.c.id, postgresql_where=my_table.c.value > 10)
```  ### 操作符类

PostgreSQL 允许为索引的每一列指定*操作符类*(参见[`www.postgresql.org/docs/current/interactive/indexes-opclass.html`](https://www.postgresql.org/docs/current/interactive/indexes-opclass.html))。`Index`构造允许通过`postgresql_ops`关键字参数指定这些:

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

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

如果要对复杂的 SQL 表达式(如函数调用)使用postgresql_ops,则必须为其提供一个在字典中通过名称标识的标签,以便应用于列,例如:

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,以及用户创建自己的能力(参见www.postgresql.org/docs/current/static/indexes-types.html)。这些可以在Index上使用postgresql_using关键字参数指定:

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

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

索引存储参数

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

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

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

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)

上述索引构造将呈现 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 的“自动提交”模式:

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 索引反射

当使用唯一约束构造时,PostgreSQL 数据库会隐式创建唯一索引。使用 Inspector 检查表时,Inspector.get_indexes()Inspector.get_unique_constraints() 将分别报告这两种构造;在索引的情况下,如果检测到它与约束镜像,则索引条目中将存在键 duplicates_constraint。在使用 Table(..., autoload_with=engine) 执行反射时,如果检测到它与 Table.constraints 中的 UniqueConstraint 镜像,唯一索引不会在 Table.indexes 中返回。

特殊反射选项

用于 PostgreSQL 后端的 InspectorPGInspector 的实例,提供了额外的方法:

from sqlalchemy import create_engine, inspect

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

print(insp.get_enums())
对象名称 描述
PGInspector
class sqlalchemy.dialects.postgresql.base.PGInspector

成员

get_domains(), get_enums(), get_foreign_table_names(), get_table_oid(), has_type()

类签名

sqlalchemy.dialects.postgresql.base.PGInspectorsqlalchemy.engine.reflection.Inspector

method get_domains(schema: str | None = None) → List[ReflectedDomain]

返回 DOMAIN 对象的列表。

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

  • 名称 - 领域的名称
  • 领域的模式 - 领域的模式名称。
  • visible - 布尔值,此领域是否在默认搜索路径中可见。
  • 类型 - 此领域定义的类型。
  • nullable - 表示此域是否可以为NULL
  • 默认值 - 域的默认值或None(如果域没有默认值)。
  • 约束 - 包含此域定义的约束的字典列表。每个元素包含两个键:约束的namecheck与约束文本。

参数:

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

2.0 版中的新内容。

method get_enums(schema: str | None = None) → List[ReflectedEnum]

返回 ENUM 对象的列表。

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

  • 名称 - 枚举的名称
  • 枚举的模式 - 枚举的模式名称。
  • visible - 布尔值,此枚举是否在默认搜索路径中可见。
  • 标签 - 适用于枚举的字符串标签列表。

参数:

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

method get_foreign_table_names(schema: str | None = None) → List[str]

返回 FOREIGN TABLE 名称的列表。

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

method get_table_oid(table_name: str, schema: str | None = None) → int

返回给定表名称的 OID。

参数:

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

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

method has_type(type_name: str, schema: str | None = None, **kw: Any) → bool

返回数据库中是否在提供的模式中具有指定类型。

参数:

  • type_name – 要检查的类型。

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

版本 2.0 中的新功能。

PostgreSQL 表选项

PostgreSQL 方言与Table构造一起直接支持 CREATE 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)')
    
    .. versionadded:: 1.2.6
    
  • TABLESPACE:

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

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

  • USING:

    Table("some_table", metadata, ..., postgresql_using='heap')
    
    .. versionadded:: 2.0.26
    
  • WITH OIDS:

    Table("some_table", metadata, ..., postgresql_with_oids=True)
    
  • WITHOUT OIDS:

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

另请参阅

PostgreSQL CREATE TABLE 选项 - 在 PostgreSQL 文档中。 ## PostgreSQL 约束选项

PostgreSQL 方言与选定约束构造一起支持以下选项:

  • NOT VALID:此选项适用于通过 ALTER TABLE 向现有表添加 CHECK 和 FOREIGN KEY 约束时,其效果是在添加约束时不扫描现有行。

    当使用 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 选项 - 在 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 中,使用 FunctionElement.table_valued() 方法与从 func 命名空间生成的 Function 对象,可以使用这些 SQL 函数调用形式。

下面是来自 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 将一个序号计数器添加到函数的输出中,并且被一组有限的 PostgreSQL 函数接受,包括 unnest()generate_series()FunctionElement.table_valued() 方法接受一个关键字参数 with_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() 构造:

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

另请参阅

列值函数 - 将表值函数作为标量列 - 在 SQLAlchemy 统一教程 中

行类型

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

>>> 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 行构造器

PostgreSQL 行构造器比较

传递给函数的表类型

PostgreSQL 支持将表作为函数参数传递,这称为“record”类型。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 方言支持数组,既作为多维列类型,也作为数组字面量:

  • ARRAY - ARRAY 数据类型

  • array - 数组字面量

  • array_agg() - ARRAY_AGG SQL 函数

  • aggregate_order_by - 用于 PG 的 ORDER BY 聚合函数语法的辅助函数。

JSON 类型

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

  • JSON

  • JSONB

  • JSONPATH

HSTORE 类型

PostgreSQL HSTORE 类型以及 hstore 字面值都受支持:

  • HSTORE - HSTORE 数据类型

  • hstore - hstore 字面值

ENUM 类型

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

  • ENUM - 用于 ENUM 的 DDL 和类型支持。

  • PGInspector.get_enums() - 检索当前 ENUM 类型的列表

  • ENUM.create()ENUM.drop() - 用于 ENUM 的单独 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 数组,我们需要呈现适当的 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)),
)
```  ## 范围和多范围类型

PostgreSQL 支持 psycopg、pg8000 和 asyncpg 方言的范围和多范围类型;psycopg2 方言仅支持范围类型。

新版本 2.0.17 中新增了对 pg8000 方言的范围和多范围支持。需要 pg8000 1.29.8 或更高版本。

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

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

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

```py
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 类型是一个简单的数据类,用于表示范围的边界。下面演示了向上述 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 对象,如下所示:

from sqlalchemy import select

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

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

  • INT4RANGE

  • INT8RANGE

  • NUMRANGE

  • DATERANGE

  • TSRANGE

  • TSTZRANGE

对象名称 描述
Range 表示 PostgreSQL 范围。
class sqlalchemy.dialects.postgresql.Range

表示 PostgreSQL 范围。

例如:

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

调用风格类似于 psycopg 和 psycopg2,部分原因是为了更容易从之前直接使用这些对象的 SQLAlchemy 版本迁移。

参数:

  • lower – 下限值,或者为 None

  • upper – 上限值,或者为 None

  • bounds – 仅关键字,可选字符串值,为 "()", "[)", "(]", "[]" 中的一个。默认为 ")"

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

新版本 2.0 中新增。

成员

[eq(), adjacent_to(), contained_by(), contains(), difference(), intersection(), is_empty, isempty, lower, lower_inc, lower_inf, not_extend_left_of(), not_extend_right_of(), overlaps(), strictly_left_of(), strictly_right_of(), union(), upper, upper_inc, upper_inf

类签名

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

method __eq__(other: Any) → bool

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

method adjacent_to(other: Range[_T]) → bool

确定此范围是否与其他范围相邻。

method contained_by(other: Range[_T]) → bool

确定此范围是否被其他范围包含。

method contains(value: _T | Range[_T]) → bool

确定此范围是否包含值。

method difference(other: Range[_T]) → Range[_T]

计算此范围与其他范围的差异。

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

method intersection(other: Range[_T]) → Range[_T]

计算此范围与其他范围的交集。

版本 2.0.10 中的新功能。

attribute is_empty

“empty”属性的同义词。

attribute isempty

“empty”属性的同义词。

attribute lower: _T | None

下界

attribute lower_inc

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

attribute lower_inf

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

method not_extend_left_of(other: Range[_T]) → bool

确定此范围是否不向左延伸到其他范围。

method not_extend_right_of(other: Range[_T]) → bool

确定此范围是否不向右延伸到其他范围。

method overlaps(other: Range[_T]) → bool

确定此范围是否与其他范围重叠。

method strictly_left_of(other: Range[_T]) → bool

确定此范围是否完全位于其他范围的左侧。

method strictly_right_of(other: Range[_T]) → bool

确定此范围是否完全位于其他范围的右侧。

method union(other: Range[_T]) → Range[_T]

计算此范围与其他范围的并集。

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

attribute upper: _T | None

上界

attribute upper_inc

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

attribute upper_inf

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

多范围

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

仅支持在 psycopg、asyncpg 和 pg8000 方言上使用多范围(multiranges)。SQLAlchemy 默认的 postgresql 方言 psycopg2 不支持多范围数据类型。

新版本 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 序列。

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

  • INT4MULTIRANGE

  • INT8MULTIRANGE

  • NUMMULTIRANGE

  • DATEMULTIRANGE

  • TSMULTIRANGE

  • TSTZMULTIRANGE ## 网络数据类型

包含的网络数据类型为 INETCIDRMACADDR

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

  • psycopg 和 asyncpg 完全支持这些数据类型;默认情况下,ipaddress 家族的对象将在行中返回。

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

  • pg8000 方言支持 ipaddress.IPv4Addressipaddress.IPv6Address 对象用于 INET 数据类型,但对于 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 单个和多个 Range SQL 类型的基类。
AbstractSingleRange PostgreSQL RANGE 类型的基类。
ARRAY PostgreSQL ARRAY 类型。
BIT
BYTEA
CIDR
CITEXT 提供 PostgreSQL 的 CITEXT 类型。
DATEMULTIRANGE 表示 PostgreSQL 的 DATEMULTIRANGE 类型。
DATERANGE 表示 PostgreSQL 的 DATERANGE 类型。
DOMAIN 表示 PostgreSQL 的 DOMAIN 类型。
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 路径类型。
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 类型的基类。

成员

adjacent_to(), contained_by(), contains(), difference(), intersection(), not_extend_left_of(), not_extend_right_of(), overlaps(), strictly_left_of(), strictly_right_of(), union()

类签名

sqlalchemy.dialects.postgresql.AbstractRange (sqlalchemy.types.TypeEngine)

class comparator_factory

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

类签名

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

method adjacent_to(other: Any) → ColumnElement[bool]

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

method contained_by(other: Any) → ColumnElement[bool]

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

method contains(other: Any, **kw: Any) → ColumnElement[bool]

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

此运算符可能会忽略 kwargs,但对于 API 符合性而言,它们是必需的。

method difference(other: Any) → ColumnElement[bool]

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

method intersection(other: Any) → ColumnElement[Range[_T]]

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

method not_extend_left_of(other: Any) → ColumnElement[bool]

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

method not_extend_right_of(other: Any) → ColumnElement[bool]

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

method overlaps(other: Any) → ColumnElement[bool]

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

method strictly_left_of(other: Any) → ColumnElement[bool]

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

method strictly_right_of(other: Any) → ColumnElement[bool]

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

method union(other: Any) → ColumnElement[bool]

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

class sqlalchemy.dialects.postgresql.AbstractSingleRange

PostgreSQL RANGE 类型的基础。

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

另请参阅

PostgreSQL 范围函数

类签名

sqlalchemy.dialects.postgresql.AbstractSingleRange (sqlalchemy.dialects.postgresql.ranges.AbstractRange)

class sqlalchemy.dialects.postgresql.AbstractMultiRange

PostgreSQL MULTIRANGE 类型的基础。

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

类签名

sqlalchemy.dialects.postgresql.AbstractMultiRange (sqlalchemy.dialects.postgresql.ranges.AbstractRange)

class sqlalchemy.dialects.postgresql.ARRAY

PostgreSQL 数组类型。

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])

默认情况下,索引访问是基于一的,以匹配 PostgreSQL 的索引访问;要进行基于零的索引访问,请设置 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 - 生成文字数组值。

成员

init(), contains(), contained_by(), overlap()

类签名

sqlalchemy.dialects.postgresql.ARRAYsqlalchemy.types.ARRAY

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

构造一个数组。

例如:

Column('myarray', ARRAY(Integer))

参数为:

参数:

  • item_type – 此数组项的数据类型。请注意,这里维度是无关紧要的,因此像INTEGER[][]这样的多维数组被构造为ARRAY(Integer),而不是ARRAY(ARRAY(Integer))或类似的。

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

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

  • zero_indexes=False – 当为 True 时,索引值将在 Python 基于零和 PostgreSQL 基于一的索引之间转换,例如,在传递到数据库之前,所有索引值将增加一个值。

class Comparator

ARRAY定义比较操作。

注意,这些操作是基于基础Comparator类提供的操作之外的,包括Comparator.any()Comparator.all()

类签名

sqlalchemy.dialects.postgresql.ARRAY.Comparatorsqlalchemy.types.Comparator

method contains(other, **kwargs)

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

kwargs 可能会被此操作符忽略,但对于 API 一致性是必需的。

method contained_by(other)

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

method overlap(other)

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

class sqlalchemy.dialects.postgresql.BIT

类签名

sqlalchemy.dialects.postgresql.BIT (sqlalchemy.types.TypeEngine) - PostgreSQL 的 BIT 类型

class sqlalchemy.dialects.postgresql.BYTEA

成员

init() - 初始化方法

类签名

sqlalchemy.dialects.postgresql.BYTEA (sqlalchemy.types.LargeBinary) - PostgreSQL 的 BYTEA 类型

method __init__(length: int | None = None)

继承自 LargeBinarysqlalchemy.types.LargeBinary.__init__ 方法 - 从 sqlalchemy.types.LargeBinary 继承

构造一个 LargeBinary 类型。

参数:

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

class sqlalchemy.dialects.postgresql.CIDR

类签名

sqlalchemy.dialects.postgresql.CIDR (sqlalchemy.types.TypeEngine) - PostgreSQL 的 CIDR 类型

class sqlalchemy.dialects.postgresql.CITEXT

提供 PostgreSQL CITEXT 类型。

版本 2.0.7 中新增。

成员

init() - 初始化方法

类签名

sqlalchemy.dialects.postgresql.CITEXT (sqlalchemy.types.TEXT) - PostgreSQL 的 CITEXT 类型

method __init__(length: int | None = None, collation: str | None = None)

继承自 Stringsqlalchemy.types.String.__init__ 方法 - 从 sqlalchemy.types.String 继承

创建一个持有字符串的类型。

参数:

  • length – 可选,用于 DDL 和 CAST 表达式中的列长度。如果不会发出 CREATE TABLE,可以安全地省略。某些数据库可能需要在 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 中新增。

成员

init(), create(), drop()

类签名

sqlalchemy.dialects.postgresql.DOMAINsqlalchemy.dialects.postgresql.named_types.NamedTypesqlalchemy.types.SchemaType

method __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 – 此域的值不允许为 null。默认情况下,域允许为 null。如果未指定,则不会发出空值约束。

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

  • schema – 可选的模式名称

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

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

method create(bind, checkfirst=True, **kw)

继承自 NamedType NamedType.create() 方法

发出此类型的CREATE DDL。

参数:

  • bind – 一个可连接的EngineConnection或类似对象以发出 SQL。

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

method 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 类型。

新版本中新增。

另请参阅

Double - 基本类型的文档。

类签名

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

method __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的支持。

当使用内置类型Enum并且Enum.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)

成员

init(), create(), drop()

类签名

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

method __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。

method create(bind=None, checkfirst=True)

为此ENUM发出CREATE TYPE

如果底层方言不支持 PostgreSQL CREATE TYPE,则不会采取任何操作。

参数:

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

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

method 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扩展时,ORM 将不会被提醒对现有字典内容的任何更改,除非该字典值被重新分配给 HSTORE 属性本身,从而生成更改事件。

另见

hstore - 渲染 PostgreSQL 的 hstore() 函数。

成员

array(), contained_by(), contains(), defined(), delete(), has_all(), has_any(), has_key(), keys(), matrix(), slice(), vals(), init(), bind_processor(), comparator_factory, hashable, result_processor()

类签名

sqlalchemy.dialects.postgresql.HSTOREsqlalchemy.types.Indexable, sqlalchemy.types.Concatenable, sqlalchemy.types.TypeEngine)

class Comparator

HSTORE定义比较操作。

类签名

sqlalchemy.dialects.postgresql.HSTORE.Comparatorsqlalchemy.types.Comparatorsqlalchemy.types.Comparator

method array()

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

method contained_by(other)

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

method contains(other, **kwargs)

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

kwargs 可能会被此操作符忽略,但对 API 一致性来说是必需的。

method defined(key)

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

method delete(key)

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

method has_all(other)

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

method has_any(other)

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

method has_key(other)

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

method keys()

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

method matrix()

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

method slice(array)

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

method vals()

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

method __init__(text_type=None)

构建一个新的HSTORE

参数:

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

method bind_processor(dialect)

返回一个处理绑定值的转换函数。

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

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

注意

该方法仅相对于特定方言类型对象调用,该对象通常是正在使用的方言的私有对象,并且不是与公共面向的对象相同的类型对象,这意味着无法通过子类化TypeEngine类来提供替代TypeEngine.bind_processor()方法,除非明确子类化UserDefinedType类。

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

另请参见

扩充现有类型

参数:

dialect – 使用的方言实例。

attribute comparator_factory

Comparator的别名。

attribute hashable = False

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

在 ORM 中用于唯一化结果列表。

method result_processor(dialect, coltype)

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

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

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

注意

此方法仅相对于一个特定方言类型对象调用,该对象通常是正在使用的方言中的私有类型对象,并且与公共类型对象不同,这意味着无法通过子类化TypeEngine类来提供替代的TypeEngine.result_processor()方法,除非显式地子类化UserDefinedType类。

为了为TypeEngine.result_processor()提供替代行为,实现一个TypeDecorator类并提供一个TypeDecorator.process_result_value()的实现。

另请参见

扩充现有类型

参数:

  • dialect – 使用的方言实例。

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

class sqlalchemy.dialects.postgresql.INET

类签名

sqlalchemy.dialects.postgresql.INET (sqlalchemy.types.TypeEngine)。

class sqlalchemy.dialects.postgresql.INTERVAL

PostgreSQL 间隔类型。

成员

init()

类签名

sqlalchemy.dialects.postgresql.INTERVALsqlalchemy.types.NativeForEmulatedsqlalchemy.types._AbstractInterval

method __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 数据类型不提供用于 PostgreSQL 特定比较方法的 Python 访问器,例如 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

成员

astext, init(), comparator_factory

类签名

sqlalchemy.dialects.postgresql.JSONsqlalchemy.types.JSON

class Comparator

JSON 定义比较操作。

类签名

sqlalchemy.dialects.postgresql.JSON.Comparatorsqlalchemy.types.Comparator

attribute astext

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

例如:

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

另请参阅

ColumnElement.cast()

method __init__(none_as_null=False, astext_type=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 comparator_factory

的别名Comparator

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 时,序列化器与 jsonb 类型相关联,使用psycopg2.extras.register_default_jsonb在每个连接上基于 psycopg2 方式注册这些处理程序,与使用psycopg2.extras.register_default_json将这些处理程序注册到 json 类型的方式相同。

另请参阅

JSON

成员

contained_by(), contains(), delete_path(), has_all(), has_any(), has_key(), path_exists(), path_match(), comparator_factory。

类签名

sqlalchemy.dialects.postgresql.JSONB (sqlalchemy.dialects.postgresql.json.JSON)。

class Comparator

JSON 定义比较操作。

类签名

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

method contained_by(other)

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

method contains(other, **kwargs)

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

kwargs 可能会被此运算符忽略,但对于 API 一致性是必需的。

method delete_path(array)

JSONB 表达���。删除参数数组中指定的字段或数组元素。

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

版本 2.0 中新增。

method has_all(other)

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

method has_any(other)

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

method has_key(other)

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

method path_exists(other)

布尔表达式。测试参数 JSONPath 表达式给出的项目是否存在。

版本 2.0 中新增。

method path_match(other)

布尔表达式。测试参数 JSONPath 表达式给出的 JSONPath 谓词是否匹配。

仅考虑结果的第一项。

版本 2.0 中新增。

attribute comparator_factory

Comparator 的别名。

class sqlalchemy.dialects.postgresql.JSONPATH

JSON 路径类型。

当使用类似于 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)
    )
)

类签名

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

class sqlalchemy.dialects.postgresql.MACADDR

类签名

sqlalchemy.dialects.postgresql.MACADDRsqlalchemy.types.TypeEngine

class sqlalchemy.dialects.postgresql.MACADDR8

类签名

sqlalchemy.dialects.postgresql.MACADDR8sqlalchemy.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 中新增。

类签名

sqlalchemy.dialects.postgresql.MONEYsqlalchemy.types.TypeEngine

class sqlalchemy.dialects.postgresql.OID

提供 PostgreSQL OID 类型。

类签名

sqlalchemy.dialects.postgresql.OIDsqlalchemy.types.TypeEngine

class sqlalchemy.dialects.postgresql.REAL

SQL REAL 类型。

参见

Float - 基本类型的文档。

类签名

sqlalchemy.dialects.postgresql.REALsqlalchemy.types.Float

method __init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)

继承自 Float sqlalchemy.types.Float.__init__ 方法

构造一个 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.REGCONFIG

提供 PostgreSQL 的 REGCONFIG 类型。

新版本 2.0.0rc1 中新增。

类签名

sqlalchemy.dialects.postgresql.REGCONFIG (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.REGCLASS

提供 PostgreSQL 的 REGCLASS 类型。

新版本 1.2.7 中新增。

类签名

sqlalchemy.dialects.postgresql.REGCLASS (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.TIMESTAMP

提供 PostgreSQL 的 TIMESTAMP 类型。

成员

init()

类签名

sqlalchemy.dialects.postgresql.TIMESTAMP (sqlalchemy.types.TIMESTAMP)

method __init__(timezone: bool = False, precision: int | None = None) → None

构造一个 TIMESTAMP。

参数:

  • timezone – 如果存在时区则为布尔值,默认为 False

  • precision

    可选的整数精度值

    新版本 1.4 中新增。

class sqlalchemy.dialects.postgresql.TIME

PostgreSQL 的 TIME 类型。

成员

init()

类签名

sqlalchemy.dialects.postgresql.TIME (sqlalchemy.types.TIME)

method __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 中新增。

类签名

sqlalchemy.dialects.postgresql.TSQUERY (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.TSVECTOR

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

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

另请参见

全文搜索

类签名

sqlalchemy.dialects.postgresql.TSVECTOR (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.UUID

表示 SQL UUID 类型。

这是 Uuid 数据库不可知数据类型的 SQL 本机形式,并且向后兼容以前的仅限于 PostgreSQL 的 UUID 版本。

UUID 数据类型仅适用于具有名为 UUID 的 SQL 数据类型的数据库。它不适用于没有这个确切命名类型的后端,包括 SQL Server。对于具有本机支持的后端不可知 UUID 值,包括 SQL Server 的 UNIQUEIDENTIFIER 数据类型,请使用 Uuid 数据类型。

新版本 2.0 中新增。

另请参见

Uuid

类签名

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

method __init__(as_uuid: bool = True)

构建一个 UUID 类型。

参数:

as_uuid=True

如果为 True,则值将被解释为 Python uuid 对象,通过 DBAPI 转换为字符串。

class sqlalchemy.dialects.postgresql.INT4RANGE

表示 PostgreSQL INT4RANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT4RANGE (sqlalchemy.dialects.postgresql.ranges.AbstractSingleRange)

class sqlalchemy.dialects.postgresql.INT8RANGE

表示 PostgreSQL INT8RANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT8RANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.NUMRANGE

表示 PostgreSQL NUMRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.NUMRANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.DATERANGE

表示 PostgreSQL DATERANGE 类型。

类签名

sqlalchemy.dialects.postgresql.DATERANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.TSRANGE

表示 PostgreSQL TSRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.TSRANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.TSTZRANGE

表示 PostgreSQL TSTZRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.TSTZRANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.INT4MULTIRANGE

表示 PostgreSQL INT4MULTIRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT4MULTIRANGEsqlalchemy.dialects.postgresql.ranges.AbstractMultiRange

class sqlalchemy.dialects.postgresql.INT8MULTIRANGE

表示 PostgreSQL INT8MULTIRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT8MULTIRANGEsqlalchemy.dialects.postgresql.ranges.AbstractMultiRange

class sqlalchemy.dialects.postgresql.NUMMULTIRANGE

表示 PostgreSQL NUMMULTIRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.NUMMULTIRANGEsqlalchemy.dialects.postgresql.ranges.AbstractMultiRange

class sqlalchemy.dialects.postgresql.DATEMULTIRANGE

表示 PostgreSQL DATEMULTIRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.DATEMULTIRANGE (sqlalchemy.dialects.postgresql.ranges.AbstractMultiRange)

class sqlalchemy.dialects.postgresql.TSMULTIRANGE

表示 PostgreSQL TSRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.TSMULTIRANGE (sqlalchemy.dialects.postgresql.ranges.AbstractMultiRange)

class sqlalchemy.dialects.postgresql.TSTZMULTIRANGE

表示 PostgreSQL TSTZRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.TSTZMULTIRANGE (sqlalchemy.dialects.postgresql.ranges.AbstractMultiRange)

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 中新增。

另请参阅

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

类签名

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

PostgreSQL SQL 元素和函数

对象名称 描述
aggregate_order_by 表示 PostgreSQL 聚合排序表达式。
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;

在版本 1.2.13 中更改:- ORDER BY 参数可以是多个术语

另请参阅

array_agg

类签名

sqlalchemy.dialects.postgresql.aggregate_order_bysqlalchemy.sql.expression.ColumnElement)

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

版本 1.3.6 中的新内容:增加了对多维数组字面值的支持

另请参阅

ARRAY

类签名

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>)

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

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

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

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 数据类型。

成员

inherit_cache, type

类签名

sqlalchemy.dialects.postgresql.hstore (sqlalchemy.sql.functions.GenericFunction)

attribute inherit_cache: bool | None = True

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

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

如果与此类本地属性无关且不是其超类的属性,则可以在特定类上将此标志设置为 True,如果与对象对应的 SQL 不基于这些属性而变化。

另请参见

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

attribute 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 中的新功能。

类签名

sqlalchemy.dialects.postgresql.to_tsvectorsqlalchemy.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 中的新功能。

类签名

sqlalchemy.dialects.postgresql.to_tsquerysqlalchemy.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 中的新内容。

类签名

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 中的新内容。

类签名

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 中的新内容。

类签名

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 中的新功能。

类签名

sqlalchemy.dialects.postgresql.ts_headlinesqlalchemy.dialects.postgresql.ext._regconfig_fn

PostgreSQL 约束类型

SQLAlchemy 通过ExcludeConstraint类支持 PostgreSQL EXCLUDE 约束:

对象名称 描述
ExcludeConstraint 表级 EXCLUDE 约束。
class sqlalchemy.dialects.postgresql.ExcludeConstraint

表级 EXCLUDE 约束。

定义了在PostgreSQL 文档中描述的 EXCLUDE 约束。

成员

init()

类签名

sqlalchemy.dialects.postgresql.ExcludeConstraintsqlalchemy.schema.ColumnCollectionConstraint

method __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() 对象。当作为 literal_column()text() 传递时,column 也可以是字符串 SQL 表达式。

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

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

  • initially – 可选字符串。如果设置,当为此约束发出 DDL 时,发出 INITIALLY

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

  • where

    可选的 SQL 表达式构造或文字 SQL 字符串。如果设置,当为此约束发出 DDL 时,发出 WHERE

    警告

    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 INSERT 的 PostgreSQL 特定实现。
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

INSERT 的 PostgreSQL 特定实现。

添加了用于 PG 特定语法的方法,如 ON CONFLICT。

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

成员

excluded, inherit_cache, on_conflict_do_nothing(), on_conflict_do_update()

类签名

sqlalchemy.dialects.postgresql.Insert (sqlalchemy.sql.expression.Insert)

attribute 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 inherit_cache: bool | None = False

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

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

如果与对象对应的 SQL 不基于本类的局部属性而是基于其超类,则可以在特定类上将此标志设置为True

另请参阅

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

method on_conflict_do_nothing(constraint: _OnConflictConstraintT = None, index_elements: _OnConflictIndexElementsT = None, index_where: _OnConflictIndexWhereT = None) → Self

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

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

参数:

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

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

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

另请参阅

INSERT…ON CONFLICT(Upsert)

method on_conflict_do_update(constraint: _OnConflictConstraintT = None, index_elements: _OnConflictIndexElementsT = None, index_where: _OnConflictIndexWhereT = None, set_: _OnConflictSetT = None, where: _OnConflictWhereT = 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 – 可选参数。如果存在,则可以是文字 SQL 字符串或可接受的 WHERE 子句表达式,用于限制受 DO UPDATE SET 影响的行。不符合 WHERE 条件的行将不会被更新(实际上对于这些行是 DO NOTHING)。

另请参见

插入…在冲突时执行(Upsert)

psycopg2

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

DBAPI

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

连接

连接字符串:

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

psycopg2 连接参数

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

  • isolation_level: 对于所有 PostgreSQL 方言都可用的选项,当使用 psycopg2 方言时,包括了 AUTOCOMMIT 隔离级别。此选项在连接到数据库时立即设置连接的默认隔离级别,然后连接被池化。这个选项通常被更现代的 Connection.execution_options.isolation_level 执行选项所取代,详见 设置事务隔离级别,包括 DBAPI 自动提交。

    另请参见

    Psycopg2 事务隔离级别

    设置事务隔离级别,包括 DBAPI 自动提交

  • client_encoding: 使用 psycopg2 的 set_client_encoding() 方法以 libpq 无关的方式设置客户端编码。

    另请参见

    Psycopg2 中的 Unicode

  • executemany_mode, executemany_batch_page_size, executemany_values_page_size: 允许使用 psycopg2 扩展来优化“executemany”风格的查询。有关详细信息,请参阅下面引用的部分。

    另请参见

    Psycopg2 快速执行助手

提示

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

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

这些不应与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,这指定了与 TCP/IP 通信相反的 Unix 域通信:

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

默认情况下,用于连接到 Unix 域套接字的套接字文件是 /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 支持在连接字符串中指定多个连接点。当在 URL 的查询部分中多次使用host参数时,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 可以通过向 libpq 客户端库传递空 DSN 来连接到 PostgreSQL,默认情况下表示连接到一个开放了“trust”连接的本地主机 PostgreSQL 数据库。可以使用一组特定的以PG_...为前缀的环境变量来进一步调整此行为,这些环境变量由libpq消耗,以取代连接字符串的任何或所有元素。

对于这种形式,URL 可以在没有初始方案之外的任何元素的情况下传递:

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

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

新版本 1.3.2 中:支持使用 psycopg2 进行无参数连接。

另请参阅

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

每个语句/连接执行选项

当与Connection.execution_options()Executable.execution_options()Query.execution_options()一起使用时,以下 DBAPI 特定选项将被尊重,除了那些不特定于 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 中的新功能:使用称为 insertmanyvalues 的本机 SQLAlchemy 机制替换了 psycopg2 的execute_values()快速执行助手。

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

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

executemany_mode的可能选项包括:

  • values_only - 默认值。假设create_engine.use_insertmanyvalues保持默认值True,SQLAlchemy 的本地 insertmanyvalues 处理程序用于为合格的 INSERT 语句添加参数,该处理程序将简单的 INSERT 语句重写为包含多个 VALUES 子句,以便一次插入多个参数集合的语句。

  • 'values_plus_batch'- 默认值。假设create_engine.use_insertmanyvalues保持默认值True,SQLAlchemy 的本地 insertmanyvalues 处理程序用于为合格的 INSERT 语句添加参数,然后,当使用多个参数集合执行 UPDATE 和 DELETE 语句时,将使用 psycopg2 的execute_batch()处理程序进行合格处理。使用此模式时,对 UPDATE 和 DELETE 语句执行的 executemany 样式执行将不会包含CursorResult.rowcount属性的值。

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

“合格语句”一词指正在执行的语句是核心insert()update()delete()构造,并且不是普通的文本 SQL 字符串或使用text()构造的语句。它也可能不是特殊的“扩展”语句,如“ON CONFLICT”“upsert”语句。使用 ORM 时,ORM 刷新过程中使用的所有插入/更新/删除语句都是合格的。

psycopg2“批量”策略的“页面大小”可以通过使用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 语句的“插入多个值”行为 - “插入多个值”的背景

发送多个参数 - 使用Connection对象执行语句的一般信息,以便利用 DBAPI 的.executemany()方法。### 使用 Psycopg2 进行 Unicode

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

可以通过以下方式控制 psycopg2 方言的客户端字符编码:

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

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

    或者,上述client_encoding值可以通过create_engine.connect_args传递给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

另请参阅

事务隔离级别

pg8000 事务隔离级别

注意日志记录

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

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)

另请参阅

日志指南 - 在 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类型仍然受支持。 这意味着 SQLAlchemy 自身的编组逻辑将在参数端和结果端都发生 Python 字典与 HSTORE 字符串格式之间的强制转换,并不是psycopg2的逻辑,后者可能性能更好。 ## psycopg

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

DBAPI

有关 psycopg(又名 psycopg 3)的文档和下载信息可在此处获取:pypi.org/project/psycopg/

连接

连接字符串:

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

psycopg 是版本 3 的 psycopg 数据库驱动程序的包和模块名称,以前称为 psycopg2。 这个驱动程序与其psycopg2前身有足够的不同,以至于 SQLAlchemy 通过完全不同的方言支持它;预计只要该软件包继续为现代 Python 版本提供支持,并且仍然是postgresql://方言系列的默认方言,就会继续支持psycopg2

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")
    

可以明确指定方言的 asyncio 版本,如下所示:

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_factoryClientCursor来配置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 的文档和下载信息(如果适用)可在此处获取:pypi.org/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

client_encoding可以通过执行以下 SQL 语句在会话中被覆盖:

SET CLIENT_ENCODING TO ‘utf8’;

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

engine = create_engine(
    "postgresql+pg8000://user:pass@host/dbname", client_encoding='utf8')
```  ### SSL 连接

pg8000 接受可以使用`create_engine.connect_args`字典指定的 Python `SSLContext`对象:

```py
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`

另请参见

事务隔离级别

Psycopg2 事务隔离级别  ## asyncpg

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

### DBAPI

asyncpg 的文档和下载信息(如果适用)可在以下网址找到:[`magicstack.github.io/asyncpg/`](https://magicstack.github.io/asyncpg/)

### 连接

连接字符串:

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

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

使用特殊的 asyncio 中介层,asyncpg 方言可用作 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 使用内置的json.loads函数为jsonjsonb类型设置默认类型解码器。可以通过在使用create_engine()create_async_engine()创建引擎时设置json_deserializer属性来更改所使用的 json 实现。

多主机连接

asyncpg 方言支持多个备用主机,与 psycopg2psycopg 方言的方式相同。 语法相同,使用 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 驱动程序可选缓存的准备语句本身在发出修改特定准备语句涉及的表或其他对象的 DDL 到 PostgreSQL 数据库时也可能变得“过时”。

SQLAlchemy 的 asyncpg 方言在本地进程中发出代表 DDL 的语句时将使这些缓存失效,但这仅在单个 Python 进程/数据库引擎中可控。 如果从其他数据库引擎和/或进程进行 DDL 更改,则正在运行的应用程序可能会遇到 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()}__',
    },
)

另请参阅

github.com/MagicStack/asyncpg/issues/837

github.com/sqlalchemy/sqlalchemy/issues/6467

警告

在使用 PGBouncer 时,为了防止应用程序中无用的预处理语句的积累,重要的是使用 NullPool 池类,并配置 PgBouncer 在返回连接时使用 DISCARD。DISCARD 命令用于释放由数据库连接持有的资源,包括预处理语句。如果没有正确设置,预处理语句可能会迅速积累并导致性能问题。

禁用 PostgreSQL JIT 以改善 ENUM 数据类型处理

使用 PostgreSQL ENUM 数据类型时,asyncpg 存在一个 问题,在创建新的数据库连接时,可能会发出一个昂贵的查询,以检索有关自定义类型的元数据,这已被证明对性能产生负面影响。为了缓解这个问题,可以通过传递给 create_async_engine() 的设置来禁用客户端的 PostgreSQL “jit” 设置:

engine = create_async_engine(
    "postgresql+asyncpg://user:password@localhost/tmp",
    connect_args={"server_settings": {"jit": "off"}},
)

另请参阅

github.com/MagicStack/asyncpg/issues/727 ## psycopg2cffi

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

DBAPI

psycopg2cffi 的文档和下载信息(如果适用)可在此处找到:pypi.org/project/psycopg2cffi/

连接

连接字符串:

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

psycopg2cffipsycopg2 的改编版本,使用 CFFI 作为 C 层。这使得它适用于例如 PyPy 的使用。文档与 psycopg2 相同。

另请参阅

sqlalchemy.dialects.postgresql.psycopg2

对 PostgreSQL 数据库的支持。

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

支持的 PostgreSQL 版本

支持类型 版本
完全在 CI 中测试 12, 13, 14, 15
Normal support 9.6+
Best effort 9+

DBAPI 支持

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

  • psycopg2

  • psycopg(又名 psycopg 3)

  • pg8000

  • asyncpg

  • psycopg2cffi

序列/SERIAL/IDENTITY

PostgreSQL 支持序列,并且 SQLAlchemy 将其作为创建基于整数的主键列的新主键值的默认方式。在创建表时,SQLAlchemy 会为整数型主键列发出SERIAL数据类型,这会生成一个序列和对应于该列的服务器端默认值。

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

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

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

PostgreSQL 10 及以上的 IDENTITY 列

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

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 的出现替换为 IDENTITY:

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)
)

PostgreSQL 10 及以上版本的 IDENTITY 列

PostgreSQL 10 及以上版本具有一个新的 IDENTITY 功能,取代了 SERIAL 的使用。在Column中的Identity构造可以用来控制其行为:

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 替换为 IDENTITY:

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 开始弃用:dialect 级别的 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

另请参见

设置事务隔离级别,包括 DBAPI 自动提交

设置只读 / 可延迟

Psycopg2 事务隔离级别

pg8000 事务隔离级别

设置只读 / 可延迟

大多数 PostgreSQL 方言支持设置事务的“只读”和“可延迟”特性,这是隔离级别设置的补充。这两个属性可以通过使用Connection.execution_options()传递postgresql_readonlypostgresql_deferrable标志来同时或独立地建立。下面的示例演示了同时设置“只读”和“可延迟”以及设置"SERIALIZABLE"隔离级别:

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 隔离。

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

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

SQLAlchemy Engine 对象使用的 QueuePool 连接池实现包括在连接返回到池时调用 DBAPI 的 .rollback() 方法的 reset on return 行为。虽然这个回滚会清除前一个事务使用的即时状态,但它不涵盖更广泛的会话级状态,包括临时表以及其他服务器状态,如预备声明句柄和语句缓存。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 变量是指在引用特定表或其他对象时将隐式引用的模式名称列表。如下一节远程模式表内省和 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 连接回滚时不会被还原。

另请参阅

设置新连接的默认模式 - 在 用 MetaData 描述数据库 文档中

远程模式表内省和 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() 函数指示的模式中,表的“.schema”属性分配的模式名称是 Python 的“None”值。否则,“.schema”属性将被分配为该模式的字符串名称。

关于这些 Table 对象通过外键约束引用的表,必须决定在当前 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 的成员,然而当我们将 test_schema 添加到 PG 的 search_path 然后询问 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>

上述过程将向 MetaData.tables 集合交付 不含 模式的 referred 表名称:

>>> 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 语句,使用 INSERT..RETURNING 来获取新生成的主键标识符。要在每个语句基础上指定显式的 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(插入或更新)

从版本 9.5 开始,PostgreSQL 允许通过 INSERT 语句的 ON CONFLICT 子句将行“插入或更新”到表中。只有在该行不违反任何唯一约束的情况下才会插入候选行。在唯一约束冲突的情况下,可以发生次要操作,可以是“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 参数用于直接指定索引而不是推断索引。这可以是唯一约束的名称、主键约束或索引:

    >>> 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.primary_key 属性来引用具有命名或未命名主键的 Table

    >>> 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_ 参数指定。该参数接受一个包含直接更新值的字典:

>>> 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.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而没有指定任何列或约束条件,则会跳过任何唯一性或排他性约束违规的插入操作:

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

指定目标

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

  • 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 参数用于直接指定索引,而不是推断索引。这可以是唯一约束、主键约束或索引的名称:

    >>> 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.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_ 参数指定。此参数接受一个包含直接更新值的字典:

>>> 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 端的默认更新值或生成函数,例如使用 Column.onupdate 指定的值。这些值不会在 ON CONFLICT 类型的更新中执行,除非它们在 Insert.on_conflict_do_update.set_ 字典中手动指定。

使用排除的插入值进行更新

要引用提议的插入行,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() 方法还接受一个 WHERE 子句,使用 Insert.on_conflict_do_update.where 参数,将限制那些接收更新的行:

>>> 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 而没有指定任何列或约束,它将跳过任何唯一或排除约束违规的插入:

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

全文搜索

PostgreSQL 的全文搜索系统可通过 func 命名空间使用,结合通过 Operators.bool_op() 方法使用自定义运算符。对于一些简单情况,具有一定跨后端兼容性,也可以使用 Operators.match() 运算符。

使用 match() 进行简单纯文本���配

Operators.match() 运算符提供了跨平台的简单文本匹配功能。对于 PostgreSQL 后端,它被硬编码为使用 @@ 运算符与 plainto_tsquery() PostgreSQL 函数结合生成表达式。

在 PostgreSQL 方言中,类似以下表达式:

select(sometable.c.text.match("search string"))

将发送到数据库的内容:

SELECT text @@ plainto_tsquery('search string') FROM table

在上面的示例中,将普通字符串传递给Operators.match()将自动使用plainto_tsquery()来指定 tsquery 的类型。这为Operators.match()与其他后端的基本数据库跨兼容性建立了基础。

从版本 2.0 开始更改:PostgreSQL 方言与Operators.match()一起使用的默认 tsquery 生成函数是plainto_tsquery()

要精确呈现 1.4 中呈现的内容,请使用以下形式:

from sqlalchemy import func

select(
    sometable.c.text.bool_op("@@")(func.to_tsquery("search string"))
)

这将生成:

SELECT text @@ to_tsquery('search string') FROM table

直接使用 PostgreSQL 全文函数和运算符

文本搜索操作超出了简单使用Operators.match(),可能会利用func命名空间生成 PostgreSQL 全文函数,结合Operators.bool_op()生成任何布尔运算符。

例如,查询:

select(
    func.to_tsquery('cat').bool_op("@>")(func.to_tsquery('cat & rat'))
)

将生成:

SELECT  to_tsquery('cat')  @>  to_tsquery('cat & rat')

TSVECTOR 类型可以提供显式 CAST:

from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy import select, cast
select(cast("some text", TSVECTOR))

生成等效于的语句:

SELECT CAST('some text' AS TSVECTOR) AS anon_1

PostgreSQL 方言通过增强func命名空间来设置大多数全文搜索函数的正确参数和返回类型。假定已导入sqlalchemy.dialects.postgresql包,或者使用postgresql方言调用了create_engine(),这些函数将自动使用sqlalchemy.sql.expression.func命名空间。这些函数在以下文档中有详细说明:

  • to_tsvector

  • to_tsquery

  • plainto_tsquery

  • phraseto_tsquery

  • websearch_to_tsquery

  • ts_headline

使用match()或自定义运算符指定“regconfig”

PostgreSQL 的plainto_tsquery()函数接受一个可选的“regconfig”参数,用于指示 PostgreSQL 使用特定的预计算 GIN 或 GiST 索引来执行搜索。在使用Operators.match()时,可以使用postgresql_regconfig参数指定此附加参数,例如:

select(mytable.c.id).where(
    mytable.c.title.match('somestring', postgresql_regconfig='english')
)

这将生成:

SELECT mytable.id FROM mytable
WHERE mytable.title @@ plainto_tsquery('english', 'somestring')

当使用其他 PostgreSQL 搜索函数与 func 时,“regconfig” 参数可以直接作为初始参数传递:

select(mytable.c.id).where(
    func.to_tsvector("english", mytable.c.title).bool_op("@@")(
        func.to_tsquery("english", "somestring")
    )
)

产生一个等效于的语句:

SELECT mytable.id FROM mytable
WHERE to_tsvector('english', mytable.title) @@
    to_tsquery('english', 'somestring')

建议使用 PostgreSQL 的 EXPLAIN ANALYZE... 工具,以确保您使用 SQLAlchemy 生成了充分利用为全文搜索创建的任何索引的查询。

另请参阅

全文搜索 - PostgreSQL 文档中

使用 match() 进行简单纯文本匹配

Operators.match() 运算符提供跨兼容的简单文本匹配。对于 PostgreSQL 后端,它被硬编码为使用 @@ 运算符与 plainto_tsquery() PostgreSQL 函数结合生成表达式。

在 PostgreSQL 方言上,类似以下表达式:

select(sometable.c.text.match("search string"))

将会发送到数据库:

SELECT text @@ plainto_tsquery('search string') FROM table

在上面,将纯字符串传递给 Operators.match() 将自动使用 plainto_tsquery() 来指定 tsquery 的类型。这为 Operators.match() 与其他后端的基本数据库跨兼容性��立了基础。

从版本 2.0 开始更改:PostgreSQL 方言与 Operators.match() 一起使用的默认 tsquery 生成函数是 plainto_tsquery()

要精确呈现 1.4 中呈现的内容,请使用以下形式:

from sqlalchemy import func

select(
    sometable.c.text.bool_op("@@")(func.to_tsquery("search string"))
)

这将生成:

SELECT text @@ to_tsquery('search string') FROM table

直接使用 PostgreSQL 全文搜索函数和运算符

超出简单使用 Operators.match() 的文本搜索操作可能会利用 func 命名空间来生成 PostgreSQL 全文搜索函数,结合 Operators.bool_op() 生成任何布尔运算符。

例如,查询:

select(
    func.to_tsquery('cat').bool_op("@>")(func.to_tsquery('cat & rat'))
)

会生成:

SELECT  to_tsquery('cat')  @>  to_tsquery('cat & rat')

TSVECTOR 类型可以提供显式转换:

from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy import select, cast
select(cast("some text", TSVECTOR))

产生一个等效于的语句:

SELECT CAST('some text' AS TSVECTOR) AS anon_1

func 命名空间由 PostgreSQL 方言增强,以设置大多数全文搜索函数的正确参数和返回类型。假定已导入 sqlalchemy.dialects.postgresql 包,或者使用 postgresql 方言调用了 create_engine(),这些函数将自动由 sqlalchemy.sql.expression.func 命名空间使用。这些函数在以下文档中有详细说明:

  • to_tsvector

  • to_tsquery

  • plainto_tsquery

  • phraseto_tsquery

  • websearch_to_tsquery

  • ts_headline

使用 match() 或自定义操作符指定“regconfig”

PostgreSQL 的 plainto_tsquery() 函数接受一个可选的“regconfig”参数,用于指示 PostgreSQL 使用特定的预计��� GIN 或 GiST 索引来执行搜索。在使用 Operators.match() 时,可以使用 postgresql_regconfig 参数指定此附加参数,例如:

select(mytable.c.id).where(
    mytable.c.title.match('somestring', postgresql_regconfig='english')
)

会发出:

SELECT mytable.id FROM mytable
WHERE mytable.title @@ plainto_tsquery('english', 'somestring')

使用其他 PostgreSQL 搜索函数与 func 一起使用时,“regconfig” 参数可以直接作为初始参数传递:

select(mytable.c.id).where(
    func.to_tsvector("english", mytable.c.title).bool_op("@@")(
        func.to_tsquery("english", "somestring")
    )
)

生成等效语句:

SELECT mytable.id FROM mytable
WHERE to_tsvector('english', mytable.title) @@
    to_tsquery('english', 'somestring')

建议使用 PostgreSQL 的 EXPLAIN ANALYZE... 工具,以确保您正在生成利用为全文搜索创建的任何索引的 SQLAlchemy 查询。

另请参阅

全文搜索 - PostgreSQL 文档中的内容

仅来自…

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

# 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 特定的索引选项

有几个针对 PostgreSQL 方言的 Index 构造的扩展可用。

覆盖索引

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 中的新功能。

部分索引

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

Index('my_index', my_table.c.id, postgresql_where=my_table.c.value > 10)
```  ### 操作符类

PostgreSQL 允许为索引的每一列指定一个 *操作符类*(参见 [`www.postgresql.org/docs/current/interactive/indexes-opclass.html`](https://www.postgresql.org/docs/current/interactive/indexes-opclass.html))。`Index` 构造允许通过 `postgresql_ops` 关键字参数指定这些内容:

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

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

如果要对复杂的 SQL 表达式(例如函数调用)使用 postgresql_ops,那么它必须被赋予一个在字典中由名称标识的标签,例如:

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,以及用户创建自己的能力(参见www.postgresql.org/docs/current/static/indexes-types.html)。这些可以在 Index 上使用 postgresql_using 关键字参数指定:

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

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

索引存储参数

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

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

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

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

注意,同样的选项也可在 Table 上使用。### 使用 CONCURRENTLY 的索引

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

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

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

上述索引结构将呈现 DDL 用于 CREATE INDEX,假设检测到 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_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 中的新功能。

部分索引

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

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

操作类

PostgreSQL 允许为索引的每列指定操作类(参见www.postgresql.org/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的“键”名称,即从Table.c集合中访问它所使用的名称,这个名称可以配置为与数据库中实际列名不同。

如果要针对复杂的 SQL 表达式(如函数调用)使用postgresql_ops,则必须为列指定一个在字典中以名称标识的标签,例如:

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,用户还可以创建自己的索引类型(参见www.postgresql.org/docs/current/static/indexes-types.html)。这些可以在Index上使用postgresql_using关键字参数指定:

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)

上述索引构造将生成 DDL 用于 CREATE INDEX,假设检测到 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 的“自动提交”模式:

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 索引反射

当使用唯一约束构造时,PostgreSQL 数据库会隐式地创建一个唯一索引。当使用Inspector检查表时,Inspector.get_indexes()Inspector.get_unique_constraints()会分别报告这两个构造;在索引的情况下,如果检测到与约束相对应,则索引条目中将存在键duplicates_constraint。当使用Table(..., autoload_with=engine)进行反射时,如果检测到索引与Table.constraints集合中的UniqueConstraint相对应,则唯一索引会在Table.indexes中返回。

特殊反射选���

用于 PostgreSQL 后端的InspectorPGInspector的一个实例,提供了额外的方法:

from sqlalchemy import create_engine, inspect

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

print(insp.get_enums())
对象名称 描述
PGInspector
class sqlalchemy.dialects.postgresql.base.PGInspector

成员

get_domains(), get_enums(), get_foreign_table_names(), get_table_oid(), has_type()

类签名

sqlalchemy.dialects.postgresql.base.PGInspectorsqlalchemy.engine.reflection.Inspector

method get_domains(schema: str | None = None) → List[ReflectedDomain]

返回一个域对象的列表。

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

  • name - 域的名称
  • schema - 域的模式名称。
  • visible - 布尔值,表示此域是否在默认搜索路径中可见。
  • type - 此域定义的类型。
  • nullable - 指示此域是否可以为NULL
  • default - 域的默认值,如果域没有默认值,则为None
  • 约束 - 由此域定义的约束的字典列表。每个元素包含两个键:约束的namecheck约束文本。

参数:

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

2.0 版本中的新内容。

method get_enums(schema: str | None = None) → List[ReflectedEnum]

返回 ENUM 对象的列表。

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

  • name - 枚举的名称
  • schema - 枚举的模式名称。
  • visible - 布尔值,此枚举是否在默认搜索路径中可见。
  • labels - 应用于枚举的字符串标签列表。

参数:

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

method get_foreign_table_names(schema: str | None = None) → List[str]

返回 FOREIGN TABLE 名称列表。

其行为类似于Inspector.get_table_names(),只不过列表仅限于那些报告relkind值为f的表。

method get_table_oid(table_name: str, schema: str | None = None) → int

返回给定表名的 OID。

参数:

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

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

method has_type(type_name: str, schema: str | None = None, **kw: Any) → bool

返回数据库是否在提供的模式中具有指定类型。

参数:

  • type_name – 要检查的类型。

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

2.0 版本中的新内容。

PostgreSQL 表选项

PostgreSQL 方言与Table结构直接支持 CREATE 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)')
    
    .. versionadded:: 1.2.6
    
  • TABLESPACE

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

    上述选项也适用于Index结构。

  • USING

    Table("some_table", metadata, ..., postgresql_using='heap')
    
    .. versionadded:: 2.0.26
    
  • WITH OIDS

    Table("some_table", metadata, ..., postgresql_with_oids=True)
    
  • WITHOUT OIDS

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

参见

PostgreSQL CREATE TABLE options - PostgreSQL 文档中的内容。

PostgreSQL 约束选项

PostgreSQL 方言与选定的约束结构一起支持以下选项:

  • NOT VALID:此选项适用于向现有表通过 ALTER TABLE 添加约束时,约束正在添加到约束操作期间不扫描现有行的 CHECK 和 FOREIGN KEY 约束,并且具有的效果。

    当使用 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 选项 - 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 中,通过与从func 命名空间生成的Function 对象一起使用FunctionElement.table_valued() 方法,可以使用这些类别的 SQL 函数调用形式。

下面是来自 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 将一个序号计数器添加到函数的输出中,并被一组有限的 PostgreSQL 函数接受,包括 unnest()generate_series()FunctionElement.table_valued() 方法接受一个名为 with_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 
    

另请参阅

列值函数 - 表值函数作为标量列 - 在 SQLAlchemy 统一教程

行类型

使用sqlalchemy.func命名空间中的func.ROW或者使用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 行构造函数

PostgreSQL 行构造函数比较

传递给函数的表类型

PostgreSQL 支持将表作为函数的参数传递,这被称为“record”类型。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 中新增。

表值函数

许多 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 向函数的输出添加一个序数计数器,并被一组有限的 PostgreSQL 函数接受,包括 unnest()generate_series()FunctionElement.table_valued() 方法接受一个名为 with_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() 结构:

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

另请参阅

列值函数 - 作为标量列的表值函数 - 在 SQLAlchemy 统一教程 中

行类型

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

>>> 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 行构造函数

PostgreSQL 行构造函数比较

传递给函数的表类型

PostgreSQL 支持将表作为函数的参数传递,这称为“record”类型。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 版本中的新功能。

数组类型

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

  • ARRAY - 数组数据类型

  • array - 数组文本

  • array_agg() - ARRAY_AGG SQL 函数

  • aggregate_order_by - PG 的 ORDER BY 聚合函数语法的辅助工具。

JSON 类型

PostgreSQL 方言支持 JSON 和 JSONB 数据类型,包括 psycopg2 的本机支持以及对 PostgreSQL 的所有特殊操作符的支持:

  • JSON

  • JSONB

  • JSONPATH

HSTORE 类型

PostgreSQL 的 HSTORE 类型以及 hstore 文本都受支持:

  • HSTORE - HSTORE 数据类型

  • hstore - hstore 文本

枚举类型

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

  • ENUM - 用于 ENUM 的 DDL 和类型支持。

  • PGInspector.get_enums() - 检索当前 ENUM 类型的列表

  • ENUM.create()ENUM.drop() - 用于 ENUM 的单独 CREATE 和 DROP 命令。

使用 ENUM 与 ARRAY

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

自版本 1.3.17 起更改:现在 SQLAlchemy 的实现直接处理 ENUM 和 ARRAY 的组合,无需任何需要的变通方法。

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 的 DBAPI 不兼容。 ### 使用 JSON/JSONB 与 ARRAY

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

自版本 1.3.17 起更改:现在 SQLAlchemy 的实现直接处理 JSON/JSONB 和 ARRAY 的组合,无需任何需要的变通方法。

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)),
)
```  ### 使用 ENUM 与 ARRAY

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

自版本 1.3.17 起更改:现在 SQLAlchemy 的实现直接处理 ENUM 和 ARRAY 的组合,无需任何需要的变通方法。

```py
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 的 DBAPI 不兼容。

使用 JSON/JSONB 与 ARRAY

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

自版本 1.3.17 起更改:现在 SQLAlchemy 的实现直接处理 JSON/JSONB 和 ARRAY 的组合,无需任何需要的变通方法。

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)),
)

范围和多范围类型

对于 psycopg、pg8000 和 asyncpg 方言,支持 PostgreSQL 范围和多范围类型;psycopg2 方言仅支持范围类型。

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

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

2.0 版本中的新功能:添加了与后端无关的 Range 对象,用于表示范围。psycopg2-特定的范围类不再公开,仅由该特定方言内部使用。

例如,使用 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 类型是一个简单的数据类,用于表示范围的边界。下面说明了将行插入上述 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 对象,如下所示:

from sqlalchemy import select

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

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

  • INT4RANGE

  • INT8RANGE

  • NUMRANGE

  • DATERANGE

  • TSRANGE

  • TSTZRANGE

对象名称 描述
Range 表示一个 PostgreSQL 范围。
class sqlalchemy.dialects.postgresql.Range

表示一个 PostgreSQL 范围。

例如:

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

调用风格与 psycopg 和 psycopg2 类似,部分原因是为了方便从直接使用这些对象的以前的 SQLAlchemy 版本进行迁移。

参数:

  • lower – 下限值,或为 None

  • upper – 上限值,或为 None

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

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

2.0 版本中的新功能。

成员

[eq(), adjacent_to(), contained_by(), contains(), difference(), intersection(), is_empty, isempty, lower, lower_inc, lower_inf, not_extend_left_of(), not_extend_right_of(), overlaps(), strictly_left_of(), strictly_right_of(), union(), upper, upper_inc, upper_inf

类签名

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

method __eq__(other: Any) → bool

考虑边界包含性比较此范围与其他范围,如果它们相等则返回True

method adjacent_to(other: Range[_T]) → bool

确定此范围是否与其他范围相邻。

method contained_by(other: Range[_T]) → bool

确定此范围是否被其他范围包含。

method contains(value: _T | Range[_T]) → bool

确定此范围是否包含值。

method difference(other: Range[_T]) → Range[_T]

计算此范围与其他范围之间的差异。

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

method intersection(other: Range[_T]) → Range[_T]

计算此范围与其他范围的交集。

版本 2.0.10 中的新功能。

attribute is_empty

“空”属性的同义词。

attribute isempty

“空”属性的同义词。

attribute lower: _T | None

下限

attribute lower_inc

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

attribute lower_inf

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

method not_extend_left_of(other: Range[_T]) → bool

确定此范围是否不延伸到其他范围的左侧。

method not_extend_right_of(other: Range[_T]) → bool

确定此范围是否不延伸到其他范围的右侧。

method overlaps(other: Range[_T]) → bool

确定此范围是否与其他范围重叠。

method strictly_left_of(other: Range[_T]) → bool

确定此范围是否完全位于其他范围的左侧。

method strictly_right_of(other: Range[_T]) → bool

确定此范围是否完全位于其他范围的右侧。

method union(other: Range[_T]) → Range[_T]

计算此范围与其他范围的并集。

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

attribute upper: _T | None

上限

attribute upper_inc

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

attribute upper_inf

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

多范围

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

多范围仅受 psycopg、asyncpg 和 pg8000 方言的支持SQLAlchemy 的默认 postgresql 方言 psycopg2 方言支持多范围数据类型。

新版本 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 序列。

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

  • INT4MULTIRANGE

  • INT8MULTIRANGE

  • NUMMULTIRANGE

  • DATEMULTIRANGE

  • TSMULTIRANGE

  • TSTZMULTIRANGE

多范围

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

仅支持 psycopg、asyncpg 和 pg8000 方言的多范围。SQLAlchemy 的默认 postgresql 方言 psycopg2 方言 不支持 多范围数据类型。

新版本 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 序列。

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

  • INT4MULTIRANGE

  • INT8MULTIRANGE

  • NUMMULTIRANGE

  • DATEMULTIRANGE

  • TSMULTIRANGE

  • TSTZMULTIRANGE #### 使用 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序列。

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

  • INT4MULTIRANGE

  • INT8MULTIRANGE

  • NUMMULTIRANGE

  • DATEMULTIRANGE

  • TSMULTIRANGE

  • TSTZMULTIRANGE

网络数据类型

包含的网络数据类型有INETCIDRMACADDR

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

  • psycopg 和 asyncpg 完全支持这些数据类型;默认情况下,ipaddress系列的对象以行的形式返回。

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

  • pg8000 方言支持ipaddress.IPv4Addressipaddress.IPv6Address对象用于INET数据类型,但对于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 单个和多个 Range SQL 类型的基类。
AbstractSingleRange PostgreSQL RANGE 类型的基类。
ARRAY PostgreSQL ARRAY 类型。
BIT
BYTEA
CIDR
CITEXT 提供 PostgreSQL 的 CITEXT 类型。
DATEMULTIRANGE 代表 PostgreSQL 的 DATEMULTIRANGE 类型。
DATERANGE 代表 PostgreSQL 的 DATERANGE 类型。
DOMAIN 代表 PostgreSQL 的 DOMAIN 类型。
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 类型的基类。

成员

adjacent_to(), contained_by(), contains(), difference(), intersection(), not_extend_left_of(), not_extend_right_of(), overlaps(), strictly_left_of(), strictly_right_of(), union()

类签名

sqlalchemy.dialects.postgresql.AbstractRangesqlalchemy.types.TypeEngine

class comparator_factory

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

类签名

sqlalchemy.dialects.postgresql.AbstractRange.comparator_factorysqlalchemy.types.Comparator

method adjacent_to(other: Any) → ColumnElement[bool]

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

method contained_by(other: Any) → ColumnElement[bool]

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

method contains(other: Any, **kw: Any) → ColumnElement[bool]

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

此运算符可能会忽略 kwargs,但需要符合 API 标准。

method difference(other: Any) → ColumnElement[bool]

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

method intersection(other: Any) → ColumnElement[Range[_T]]

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

method not_extend_left_of(other: Any) → ColumnElement[bool]

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

method not_extend_right_of(other: Any) → ColumnElement[bool]

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

method overlaps(other: Any) → ColumnElement[bool]

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

method strictly_left_of(other: Any) → ColumnElement[bool]

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

method strictly_right_of(other: Any) → ColumnElement[bool]

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

method union(other: Any) → ColumnElement[bool]

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

class sqlalchemy.dialects.postgresql.AbstractSingleRange

PostgreSQL 范围类型的基类。

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

另请参阅

PostgreSQL 范围函数

类签名

sqlalchemy.dialects.postgresql.AbstractSingleRangesqlalchemy.dialects.postgresql.ranges.AbstractRange

class sqlalchemy.dialects.postgresql.AbstractMultiRange

PostgreSQL MULTIRANGE 类型的基类。

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

类签名

sqlalchemy.dialects.postgresql.AbstractMultiRangesqlalchemy.dialects.postgresql.ranges.AbstractRange

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])

默认情况��,索引访问是基于一的,以匹配 PostgreSQL 的索引访问;要进行基于零的索引访问,请设置 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 - 生成字面数组值。

成员

init(), contains(), contained_by(), overlap()

类签名

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

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

构造一个数组。

例如:

Column('myarray', ARRAY(Integer))

参数是:

参数:

  • item_type – 数组中项的数据类型。请注意,这里与维度无关,因此类似INTEGER[][]这样的多维数组,构造为ARRAY(Integer),而不是ARRAY(ARRAY(Integer))或类似的形式。

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

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

  • zero_indexes=False – 当为 True 时,索引值将在 Python 以零为基础和 PostgreSQL 以一为基础的索引之间转换,例如,将在传递到数据库之前的所有索引值上添加一个值为一的值。

class Comparator

ARRAY定义比较操作。

请注意,这些操作是在基础Comparator类提供的操作之外提供的,包括Comparator.any()Comparator.all()

类签名

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

method contains(other, **kwargs)

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

此运算符可能会忽略 kwargs,但对于 API 一致性,它们是必需的。

method contained_by(other)

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

method overlap(other)

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

class sqlalchemy.dialects.postgresql.BIT

类签名

sqlalchemy.dialects.postgresql.BIT (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.BYTEA

成员

init()

类签名

sqlalchemy.dialects.postgresql.BYTEA (sqlalchemy.types.LargeBinary)

method __init__(length: int | None = None)

继承自 LargeBinary sqlalchemy.types.LargeBinary.__init__ 方法

构造一个 LargeBinary 类型。

参数:

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

class sqlalchemy.dialects.postgresql.CIDR

类签名

sqlalchemy.dialects.postgresql.CIDR (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.CITEXT

提供 PostgreSQL CITEXT 类型。

2.0.7 版本中新增。

成员

init()

类签名

sqlalchemy.dialects.postgresql.CITEXT (sqlalchemy.types.TEXT)

method __init__(length: int | None = None, collation: str | None = None)

继承自 String sqlalchemy.types.String.__init__ 方法

创建一个持有字符串的类型。

参数:

  • length – 可选的,用于 DDL 和 CAST 表达式的列长度。如果不会发出 CREATE TABLE,可以安全地省略。某些数据库可能需要用于 DDL 的 length,如果包含了没有长度的 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 
    

    注意

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

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 中新增。

成员

init()、create()、drop()

类签名

sqlalchemy.dialects.postgresql.DOMAINsqlalchemy.dialects.postgresql.named_types.NamedTypesqlalchemy.types.SchemaType

method __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)

构造一个域。

参数:

  • name – 域的名称

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

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

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

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

  • not_null – 此域的值不能为 null。默认情况下,域允许为 null。如果未指定,则不会发出空性条款。

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

  • schema – 可选的模式名称

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

  • create_type – 默认为 True。指示在创建父表时(可选地检查类型的存在),发出CREATE TYPE;并且在删除表时另外调用DROP TYPE

method create(bind, checkfirst=True, **kw)

NamedType NamedType.create() 方法继承

发出CREATEDDL 来创建此类型。

参数:

  • bind – 一个可连接的EngineConnection或类似对象以发出 SQL。

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

method drop(bind, checkfirst=True, **kw)

继承自 NamedType NamedType.drop() 方法

发出此类型的 DROP DDL。

参数:

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

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

class sqlalchemy.dialects.postgresql.DOUBLE_PRECISION

SQL DOUBLE PRECISION 类型。

SQLAlchemy 2.0 中的新功能。

另请参阅

Double - 基本类型的文档。

类签名

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

method __init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)

继承自 Float sqlalchemy.types.Float.__init__ 方法

构造一个 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 decimal 时使用的默认精度。由于十进制不精确,浮点值通常会更长,并且大多数浮点数据库类型没有“精度”的概念,因此默认情况下,float 类型在转换时会寻找前十位小数。指定此值将覆盖该长度。请注意,如果未另行指定,具有“精度”的 MySQL 浮点类型将使用“精度”作为 decimal_return_scale 的默认值。

class sqlalchemy.dialects.postgresql.ENUM

PostgreSQL ENUM 类型。

这是Enum的一个子类,包括对 PG 的CREATE TYPEDROP TYPE的支持。

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

ENUM 的创建/删除行为必然是复杂的,这是由于 ENUM 类型与父表的尴尬关系所决定的,即它可能仅“属于”单个表,也可能在多个表之间共享。

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

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)

成员

init(), create(), drop()

类签名

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

method __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 发出到目标绑定。

method create(bind=None, checkfirst=True)

发出CREATE TYPE以适用于此ENUM

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

参数:

  • bind - 可连接的EngineConnection或类似对象,用于发出 SQL。

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

method drop(bind=None, checkfirst=True)

发出DROP TYPE以适用于此ENUM

如果底层方言不支持 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的使用与现在属于sqlalchemy.ext.mutable扩展的MutableDict字典结合起来。此扩展将允许对字典进行“原地”更改,例如向当前字典添加新键或替换/删除现有键,以产生将被工作单元检测到的事件:

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扩展时,ORM 不会注意到对现有字典内容的任何更改,除非将该字典值重新分配给 HSTORE 属性本身,从而生成更改事件。

另请参见

hstore - 渲染 PostgreSQL 的 hstore() 函数。

成员

array(), contained_by(), contains(), defined(), delete(), has_all(), has_any(), has_key(), keys(), matrix(), slice(), vals(), init(), bind_processor(), comparator_factory, hashable, result_processor()

类签名

sqlalchemy.dialects.postgresql.HSTOREsqlalchemy.types.Indexablesqlalchemy.types.Concatenablesqlalchemy.types.TypeEngine

class Comparator

HSTORE定义比较操作。

类签名

sqlalchemy.dialects.postgresql.HSTORE.Comparatorsqlalchemy.types.Comparatorsqlalchemy.types.Comparator

method array()

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

method contained_by(other)

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

method contains(other, **kwargs)

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

kwargs 可能会被此操作符忽略,但对于 API 的一致性是必需的。

method defined(key)

布尔表达式。测试键的非 NULL 值的存在。请注意,键可能是一个 SQLA 表达式。

method delete(key)

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

method has_all(other)

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

method has_any(other)

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

method has_key(other)

布尔表达式。测试键的存在。请注意,键可能是一个 SQLA 表达式。

method keys()

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

method matrix()

文本数组表达式。返回[key, value]对的数组。

method slice(array)

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

method vals()

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

method __init__(text_type=None)

构建一个新的HSTORE

参数:

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

method bind_processor(dialect)

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

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

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

注意

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

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

另请参阅

扩充现有类型

参数:

方言 – 正在使用的方言实例。

attribute comparator_factory

别名Comparator

attribute hashable = False

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

由 ORM 在唯一化结果列表时使用。

method result_processor(dialect, coltype)

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

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

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

注意

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

为了为 TypeEngine.result_processor() 提供备用行为,实现一个 TypeDecorator 类,并提供 TypeDecorator.process_result_value() 的实现。

另请参阅

扩展现有类型

参数:

  • dialect – 使用的方言实例。

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

class sqlalchemy.dialects.postgresql.INET

类签名

sqlalchemy.dialects.postgresql.INET (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.INTERVAL

PostgreSQL INTERVAL 类型。

成员

init()

类签名

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

method __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 数据类型不提供针对 PostgreSQL 特定比较方法的 Python 访问器,例如 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

成员

astext, init(), comparator_factory

类签名

sqlalchemy.dialects.postgresql.JSONsqlalchemy.types.JSON

class Comparator

JSON 定义比较操作。

类签名

sqlalchemy.dialects.postgresql.JSON.Comparatorsqlalchemy.types.Comparator

attribute astext

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

例如:

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

另请参阅

ColumnElement.cast()

method __init__(none_as_null=False, astext_type=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 comparator_factory

Comparator 的别名

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 类型一样,当与 ORM 一起使用时,JSONB 类型不会检测到原地更改,除非使用了 sqlalchemy.ext.mutable 扩展。

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

另见

JSON

成员

contained_by(),contains(),delete_path(),has_all(),has_any(),has_key(),path_exists(),path_match(),comparator_factory

类签名

sqlalchemy.dialects.postgresql.JSONBsqlalchemy.dialects.postgresql.json.JSON

class Comparator

JSON定义比较操作。

类签名

sqlalchemy.dialects.postgresql.JSONB.Comparatorsqlalchemy.dialects.postgresql.json.Comparator

method contained_by(other)

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

method contains(other, **kwargs)

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

kwargs 可能会被此运算符忽略,但在 API 符合性方面是必需的。

method delete_path(array)

JSONB 表达式。删除参数数组中指定的字段或数组元素。

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

在 2.0 版本中新增。

method has_all(other)

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

method has_any(other)

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

method has_key(other)

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

method path_exists(other)

布尔表达式。测试是否存在由参数 JSONPath 表达式给出的项目。

在 2.0 版本中新增。

method path_match(other)

布尔表达式。测试 JSONPath 断言是否与参数 JSONPath 表达式匹配。

仅考虑结果的第一个项目。

新版本 2.0 中新增。

attribute comparator_factory

Comparator 的别名

class sqlalchemy.dialects.postgresql.JSONPATH

JSON 路径类型。

当使用 json 搜索函数时,通常需要将字面值强制转换为 json 路径,例如 jsonb_path_query_arrayjsonb_path_exists

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

类签名

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

class sqlalchemy.dialects.postgresql.MACADDR

类签名

sqlalchemy.dialects.postgresql.MACADDR (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.MACADDR8

类签名

sqlalchemy.dialects.postgresql.MACADDR8 (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 中新增。

类签名

sqlalchemy.dialects.postgresql.MONEY (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.OID

提供 PostgreSQL OID 类型。

类签名

sqlalchemy.dialects.postgresql.OID (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.REAL

SQL REAL 类型。

另见

Float - 基本类型的文档。

类签名

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

method __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.REGCONFIG

提供 PostgreSQL REGCONFIG 类型。

新版本 2.0.0rc1 中加入。

类签名

sqlalchemy.dialects.postgresql.REGCONFIG (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.REGCLASS

提供 PostgreSQL REGCLASS 类型。

新版本 1.2.7 中加入。

类签名

sqlalchemy.dialects.postgresql.REGCLASS (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.TIMESTAMP

提供 PostgreSQL TIMESTAMP 类型。

成员

init()

类签名

sqlalchemy.dialects.postgresql.TIMESTAMP (sqlalchemy.types.TIMESTAMP)

method __init__(timezone: bool = False, precision: int | None = None) → None

构造一个 TIMESTAMP。

参数:

  • timezone – 如果有时区则为布尔值,默认为 False

  • precision

    可选的整数精度值

    新版本 1.4 中加入。

class sqlalchemy.dialects.postgresql.TIME

PostgreSQL TIME 类型。

成员

init()

类签名

sqlalchemy.dialects.postgresql.TIME (sqlalchemy.types.TIME)

method __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 中的新功能。

类签名

sqlalchemy.dialects.postgresql.TSQUERY (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.TSVECTOR

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

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

另请参阅

全文搜索

类签名

sqlalchemy.dialects.postgresql.TSVECTOR (sqlalchemy.types.TypeEngine)

class sqlalchemy.dialects.postgresql.UUID

表示 SQL UUID 类型。

这是 Uuid 数据库不可知数据类型的 SQL 本机形式,并且向后兼容以前的仅限于 PostgreSQL 的 UUID 版本。

UUID 数据类型仅适用于具有名为 UUID 的 SQL 数据类型的数据库。对于没有这个确切命名类型的后端,包括 SQL Server,它将无法正常工作。对于具有本机支持的后端不可知 UUID 值,包括 SQL Server 的 UNIQUEIDENTIFIER 数据类型,请使用 Uuid 数据类型。

版本 2.0 中的新功能。

另请参阅

Uuid

类签名

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

method __init__(as_uuid: bool = True)

构建一个UUID类型。

参数:

as_uuid=True

如果为 True,则值将被解释为 Python uuid 对象,通过 DBAPI 转换为/从字符串。

class sqlalchemy.dialects.postgresql.INT4RANGE

表示 PostgreSQL INT4RANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT4RANGE (sqlalchemy.dialects.postgresql.ranges.AbstractSingleRange)

class sqlalchemy.dialects.postgresql.INT8RANGE

表示 PostgreSQL INT8RANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT8RANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.NUMRANGE

表示 PostgreSQL NUMRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.NUMRANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.DATERANGE

表示 PostgreSQL DATERANGE 类型。

类签名

sqlalchemy.dialects.postgresql.DATERANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.TSRANGE

表示 PostgreSQL TSRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.TSRANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.TSTZRANGE

表示 PostgreSQL TSTZRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.TSTZRANGEsqlalchemy.dialects.postgresql.ranges.AbstractSingleRange

class sqlalchemy.dialects.postgresql.INT4MULTIRANGE

表示 PostgreSQL INT4MULTIRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT4MULTIRANGEsqlalchemy.dialects.postgresql.ranges.AbstractMultiRange

class sqlalchemy.dialects.postgresql.INT8MULTIRANGE

表示 PostgreSQL INT8MULTIRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.INT8MULTIRANGEsqlalchemy.dialects.postgresql.ranges.AbstractMultiRange

class sqlalchemy.dialects.postgresql.NUMMULTIRANGE

表示 PostgreSQL NUMMULTIRANGE 类型。

类签名

sqlalchemy.dialects.postgresql.NUMMULTIRANGEsqlalchemy.dialects.postgresql.ranges.AbstractMultiRange

class sqlalchemy.dialects.postgresql.DATEMULTIRANGE

表示 PostgreSQL DATEMULTIRANGE 类型。

类签名

class sqlalchemy.dialects.postgresql.DATEMULTIRANGE (sqlalchemy.dialects.postgresql.ranges.AbstractMultiRange)

class sqlalchemy.dialects.postgresql.TSMULTIRANGE

表示 PostgreSQL TSRANGE 类型。

类签名

class sqlalchemy.dialects.postgresql.TSMULTIRANGE (sqlalchemy.dialects.postgresql.ranges.AbstractMultiRange)

class sqlalchemy.dialects.postgresql.TSTZMULTIRANGE

表示 PostgreSQL TSTZRANGE 类型。

类签名

class sqlalchemy.dialects.postgresql.TSTZMULTIRANGE (sqlalchemy.dialects.postgresql.ranges.AbstractMultiRange)

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 版本中新增。

另请参阅

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

类签名

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

PostgreSQL SQL 元素和函数

对象名称 描述
aggregate_order_by 表示 PostgreSQL 聚合排序表达式。
All(other, arrexpr[, operator]) Comparator.all() 方法在数组层面的同义词。详情请参阅该方法。
Any(other, arrexpr[, operator]) Comparator.any() 方法在数组层面的同义词。详情请参阅该方法。
array 一个 PostgreSQL 数组字面量。
array_agg(*arg, **kw) PostgreSQL 特定形式的 array_agg,确保返回类型是 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 聚合排序表达式。

例如:

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;

1.2.13 版本更改:- ORDER BY 参数可以是多个条款

另请参见

array_agg

类签名

sqlalchemy.dialects.postgresql.aggregate_order_by (sqlalchemy.sql.expression.ColumnElement)

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

1.3.6 版本新增功能:增加了对多维数组文字的支持

另请参见

ARRAY

类签名

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

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

PostgreSQL 特定形式的array_agg,确保返回类型为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数据类型。

成员

inherit_cache, type

类签名

class sqlalchemy.dialects.postgresql.hstore (sqlalchemy.sql.functions.GenericFunction)

attribute inherit_cache: bool | None = True

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

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

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

另请参阅

为自定义构造启用缓存支持](../core/compiler.html#compilerext-caching) - 为第三方或用户定义的 SQL 构造设置HasCacheKey.inherit_cache属性的一般指南。

attribute 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 中推出。

类签名

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 中推出。

类签名

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 中新增。

类签名

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 中新增。

类签名

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 中新增。

类签名

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

类签名

sqlalchemy.dialects.postgresql.ts_headlinesqlalchemy.dialects.postgresql.ext._regconfig_fn

PostgreSQL 约束类型

SQLAlchemy 通过ExcludeConstraint类支持 PostgreSQL EXCLUDE 约束:

对象名称 描述
ExcludeConstraint 表级 EXCLUDE 约束。
class sqlalchemy.dialects.postgresql.ExcludeConstraint

表级 EXCLUDE 约束。

根据PostgreSQL 文档中的描述定义了一个 EXCLUDE 约束。

成员

init()

类签名

sqlalchemy.dialects.postgresql.ExcludeConstraintsqlalchemy.schema.ColumnCollectionConstraint

method __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() 对象。当作为 literal_column()text() 传递时,column 也可以是字符串 SQL 表达式。

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

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

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

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

  • where

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

    警告

    ExcludeConstraint.where 参数可以作为 Python 字符串参数传递,该参数将被视为受信任的 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 INSERT 的 PostgreSQL 特定实现。
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() 函数创建的。

成员

排除, inherit_cache, on_conflict_do_nothing(), on_conflict_do_update()

类签名

sqlalchemy.dialects.postgresql.Insert (sqlalchemy.sql.expression.Insert)

attribute 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 inherit_cache: bool | None = False

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

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

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

另请参阅

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

method on_conflict_do_nothing(constraint: _OnConflictConstraintT = None, index_elements: _OnConflictIndexElementsT = None, index_where: _OnConflictIndexWhereT = None) → Self

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

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

参数:

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

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

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

另请参阅

INSERT…ON CONFLICT (Upsert)

method on_conflict_do_update(constraint: _OnConflictConstraintT = None, index_elements: _OnConflictIndexElementsT = None, index_where: _OnConflictIndexWhereT = None, set_: _OnConflictSetT = None, where: _OnConflictWhereT = 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 – 可选参数。如果存在,可以是字面 SQL 字符串或WHERE子句的可接受表达式,用于限制受DO UPDATE SET影响的行。不符合WHERE条件的行将不会被更新(对于这些行实际上是DO NOTHING)。

另请参阅

INSERT…ON CONFLICT(Upsert)

psycopg2

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

DBAPI

psycopg2 的文档和下载信息(如果适用)可在以下网址找到:pypi.org/project/psycopg2/

连接中

连接字符串:

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

psycopg2 连接参数

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

  • isolation_level:此选项适用于所有 PostgreSQL 方言,在使用 psycopg2 方言时包括 AUTOCOMMIT 隔离级别。此选项设置连接的默认隔离级别,即在连接到数据库之前立即设置的连接隔离级别,而不是连接到池中。通常,此选项被更现代的Connection.execution_options.isolation_level执行选项所取代,详细信息请参见设置事务隔离级别,包括 DBAPI 自动提交。

    另请参见

    Psycopg2 事务隔离级别

    设置事务隔离级别,包括 DBAPI 自动提交

  • client_encoding:以与 libpq 无关的方式设置客户端编码,使用 psycopg2 的 set_client_encoding() 方法。

    另请参见

    Psycopg2 中的 Unicode

  • executemany_modeexecutemany_batch_page_sizeexecutemany_values_page_size:允许使用 psycopg2 扩展来优化“executemany”风格的查询。有关详细信息,请参见下面引用的部分。

    另请参见

    Psycopg2 快速执行助手

提示

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

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

这些不应与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")

默认情况下,用于连接到 Unix 域套接字的套接字文件位于 /tmp 中,或者在构建 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 支持在连接字符串中指定多个连接点。当在 URL 的查询部分中多次使用host参数时,SQLAlchemy 将创建提供的主机和端口信息的单个字符串以进行连接。令牌可以包含host::porthost;在后一种情况下,libpq 将选择默认端口。在下面的示例中,指定了三个主机连接,分别为HostA::PortAHostB连接到默认端口和HostC::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,默认情况下表示连接到打开“信任”连接的本地主机 PostgreSQL 数据库。此行为可以进一步使用一组以PG_...为前缀的特定环境变量进行定制,这些环境变量由libpq消耗,以取代连接字符串的任何或所有元素。

对于此形式,可以传递 URL 而不包含任何除初始方案之外的元素:

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

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

版本 1.3.2 中新增:对于 psycopg2 支持无参数连接。

另请参阅

环境变量 - PostgreSQL 文档上关于如何使用 PG_... 环境变量进行连接的说明。

每语句/连接执行选项

在使用 Connection.execution_options()Executable.execution_options()Query.execution_options() 时,将遵守以下特定于 DBAPI 的选项,除了不特定于 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 版本中的新功能:用本机 SQLAlchemy 机制 insertmanyvalues 替换了 psycopg2 的execute_values()快速执行助手。

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。然后,当使用多个参数集执行 UPDATE 和 DELETE 语句时,使用 psycopg2 的execute_batch()处理程序进行限定。在使用此模式时,CursorResult.rowcount属性将不会包含对 UPDATE 和 DELETE 语句进行 executemany-style 执行的行数。

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

“限定语句”一词指的是正在执行的语句是一个 Core insert()update()delete()构造,而不是一个简单的文本 SQL 字符串或使用text()构造的字符串。它也可能是一个特殊的“扩展”语句,比如“ON CONFLICT”“upsert”语句。在使用 ORM 时,ORM 刷新过程中使用的所有插入/更新/删除语句都是限定的。

使用 executemany_batch_page_size 参数可以影响 psycopg2 的 “batch” 策略的 “页面大小”,默认为 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 Many Values” Behavior for INSERT statements - 关于“insertmanyvalues”的背景信息

发送多个参数 - 关于使用 Connection 对象以便利用 DBAPI 的 .executemany() 方法执行语句的一般信息。### 使用 Psycopg2 进行 Unicode 编码

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

对于 psycopg2 方言,客户端字符编码可以通过以下方式进行控制:

  • 对于 PostgreSQL 9.1 及以上版本,client_encoding 参数可以通过数据库 URL 进行传递;该参数由底层的 libpq PostgreSQL 客户端库消费:

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

    或者,上述的 client_encoding 值可以通过 create_engine.connect_args 进行传递,用于使用 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

另请参阅

事务隔离级别

pg8000 事务隔离级别

注意日志

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

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)

另请参阅

日志指南 - 在 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 字典都被接受为参数,无论目标列的类型是什么。这些字典由此扩展转换为文本 HSTORE 表达式。如果不希望这种行为,请通过将use_native_hstore设置为False来禁用 hstore 扩展,如下所示:

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

当未使用psycopg2.extensions.register_hstore()扩展时,仍然支持HSTORE类型。 这仅意味着在 SQLAlchemy 自己的编组逻辑中,Python 字典和 HSTORE 字符串格式之间的强制转换,无论是参数方面还是结果方面,都将发生,而不是psycopg2的编组逻辑,后者可能更有效率。

DBAPI

psycopg2 的文档和下载信息(如适用)可在此处获取:pypi.org/project/psycopg2/

连接

Connect String:

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

psycopg2 连接参数

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

  • isolation_level: 此选项适用于所有 PostgreSQL 方言,在使用 psycopg2 方言时,它包括AUTOCOMMIT隔离级别。 此选项在连接到数据库时立即设置连接的默认隔离级别,然后连接到数据库之前将其池化。 通常,此选项被更现代的Connection.execution_options.isolation_level执行选项所取代,详见设置包括 DBAPI 自动提交的事务隔离级别。

    另请参阅

    Psycopg2 事务隔离级别

    设置包括 DBAPI 自动提交的事务隔离级别

  • client_encoding: 使用 psycopg2 的set_client_encoding()方法以 libpq 不可知的方式设置客户端编码。

    另请参阅

    Psycopg2 中的 Unicode

  • executemany_modeexecutemany_batch_page_sizeexecutemany_values_page_size:允许使用 psycopg2 扩展优化“executemany”式查询。 详见下面引用的章节了解详情。

    另请参阅

    Psycopg2 快速执行助手

提示

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

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

这些不应与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")

默认情况下,用于连接的套接字文件是连接到 Unix 域套接字的/tmp,或者在构建 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 支持在连接字符串中使用多个连接点。当在 URL 的查询部分中多次使用host参数时,SQLAlchemy 将创建主机和端口信息的单个字符串以进行连接。标记可以由host::port或仅host组成;在后一种情况下,默认端口由 libpq 选择。在下面的示例中,指定了三个主机连接,分别为HostA::PortA,连接到默认端口的HostB,以及HostC::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 可以通过向 libpq 客户端库传递空的 DSN 来连接到 PostgreSQL,默认情况下表示连接到一个开放了“trust”连接的 localhost PostgreSQL 数据库。这种行为可以通过一组特定的环境变量进一步定制,这些环境变量以 PG_... 为前缀,并由 libpq 使用,以取代连接字符串的任何或所有元素。

对于此形式,URL 可以在没有除了初始方案之外的任何元素的情况下传递:

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

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

1.3.2 版中的新功能:支持与 psycopg2 无参数连接。

另请参见

环境变量 - 有关如何使用 PG_... 环境变量进行连接的 PostgreSQL 文档。

每条语句 / 连接执行选项

当与 Connection.execution_options()Executable.execution_options()Query.execution_options() 一起使用时,以下 DBAPI 特定选项也会被尊重,除了那些不特定于 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 开始新增:用名为 insertmanyvalues 的本机 SQLAlchemy 机制替换了 psycopg2 的 execute_values() 快速执行辅助工具。

psycopg2 方言保留了使用 psycopg2 特定的 execute_batch() 功能的能力,尽管不太可能广泛使用此功能。可以通过传递给 create_engine()executemany_mode 标志启用此扩展:

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

executemany_mode 的可能选项包括:

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

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

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

术语“限定语句”指的是要执行的语句是一个 Core insert()update()delete()构造,并且是一个纯文本的 SQL 字符串或使用text()构造的字符串。它也可能是一个特殊的“扩展”语句,比如“ON CONFLICT”“upsert”语句。在使用 ORM 时,ORM 刷新过程中使用的所有插入/更新/删除语句都是限定语句。

使用executemany_batch_page_size参数可以影响 psycopg2 的“批量”策略中的“页面大小”,默认为 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 语句的“Insert Many Values”行为 - 关于“insertmanyvalues”的背景信息

发送多个参数 - 有关使用Connection对象执行语句以便利用 DBAPI 的.executemany()方法的一般信息。

使用 Psycopg2 进行 Unicode

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

可以通过以下方式控制 psycopg2 方言的客户端字符编码:

  • 对于 PostgreSQL 9.1 及以上版本,client_encoding参数可以在数据库 URL 中传递;此参数由底层的libpq PostgreSQL 客户端库消耗:

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

    或者,上述client_encoding值可以通过create_engine.connect_args在编程方式下与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

另请参阅

事务隔离级别

pg8000 事务隔离级别

NOTICE 记录

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

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)

另请参阅

日志指南 - 在 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 字典都被接受为参数,无论目标列的类型是什么。这些字典由此扩展转换为文本 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)的文档和下载信息(如果适用)可在以下网址找到:pypi.org/project/psycopg/

连接

连接字符串:

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

psycopgpsycopg数据库驱动程序第 3 版的包和模块名称。这个驱动程序与其前身psycopg2有足够的不同,以至于 SQLAlchemy 通过完全独立的方言支持它;预计只要该软件包继续为现代 Python 版本提供功能,并且仍然是postgresql://方言系列的默认方言,就会继续支持psycopg2

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")
    

可以明确指定方言的 asyncio 版本,如下所示:

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},
)

另请参阅

客户端绑定游标

DBAPI

psycopg(又名 psycopg 3)的文档和下载信息(如果适用)可在以下网址找到:pypi.org/project/psycopg/

连接

连接字符串:

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

使用不同的 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 的文档和下载信息(如果适用)可在以下网址找到:pypi.org/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

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

将 CLIENT_ENCODING 设置为 ‘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` 字典指定:

```py
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`

另请参阅

事务隔离级别

Psycopg2 事务隔离级别

### DBAPI

文档和下载信息(如果适用)可在以下网址找到:[`pypi.org/project/pg8000/`](https://pypi.org/project/pg8000/)

### 连接中

连接字符串:

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

Unicode

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

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

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

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

另请参阅

事务隔离级别

Psycopg2 事务隔离级别

asyncpg

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

DBAPI

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

连接中

连接字符串:

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

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

使用特殊的 asyncio 中介层,asyncpg 方言可用作 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 使用 Python 内置的 json.loads 函数为 jsonjsonb 类型设置默认类型解码器。可以通过在使用 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()}__',
    },
)

另请参阅

github.com/MagicStack/asyncpg/issues/837

github.com/sqlalchemy/sqlalchemy/issues/6467

警告

当使用 PGBouncer 时,为了防止应用程序中出现无用的准备语句堆积,使用 NullPool 连接池类很重要,并且要配置 PgBouncer 在返回连接时使用 DISCARD。DISCARD 命令用于释放 db 连接持有的资源,包括准备的语句。没有适当的设置,准备的语句可能会快速积累并导致性能问题。

禁用 PostgreSQL JIT 以改进 ENUM 数据类型处理

在使用 PostgreSQL ENUM 数据类型时,asyncpg 存在一个问题,在创建新数据库连接时,可能会发出一个昂贵的查询以检索有关已显示对性能产生负面影响的自定义类型的元数据。为了缓解此问题,可以通过将此设置传递给 create_async_engine() 来禁用客户端的 PostgreSQL “jit” 设置:

engine = create_async_engine(
    "postgresql+asyncpg://user:password@localhost/tmp",
    connect_args={"server_settings": {"jit": "off"}},
)

另请参见

github.com/MagicStack/asyncpg/issues/727

DBAPI

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

连接

连接字符串:

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

多主机连接

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,当自定义 PostgreSQL 数据类型(如 ENUM 对象)通过 DDL 操作进行更改时,这些缓存就会变得过时。此外,如上述描述的那样,由 SQLAlchemy 驱动程序可选缓存的预编译语句本身在发出修改特定预编译语句涉及的表或其他对象的 DDL 到 PostgreSQL 数据库时也可能变得“过时”。

当在本地连接上发出代表 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()}__',
    },
)

另请参阅

github.com/MagicStack/asyncpg/issues/837

github.com/sqlalchemy/sqlalchemy/issues/6467

警告

在使用 PGBouncer 时,为了防止应用程序中出现无用的预处理语句过多,重要的是使用NullPool池类,并配置 PgBouncer 在返回连接时使用DISCARD。DISCARD 命令用于释放由 db 连接持有的资源,包括预处理语句。如果没有正确设置,预处理语句可能会迅速积累并导致性能问题。

禁用 PostgreSQL JIT 以改善 ENUM 数据类型处理

当使用 PostgreSQL ENUM 数据类型时,Asyncpg 存在一个问题,在创建新数据库连接时,可能会发出一个昂贵的查询,以检索有关自定义类型的元数据,这已被证明对性能产生负面影响。为了缓解这个问题,可以通过将此设置传递给create_async_engine()来禁用客户端中的 PostgreSQL“jit”设置:

engine = create_async_engine(
    "postgresql+asyncpg://user:password@localhost/tmp",
    connect_args={"server_settings": {"jit": "off"}},
)

另请参阅

github.com/MagicStack/asyncpg/issues/727

psycopg2cffi

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

DBAPI

文档和下载信息(如果适用)可在以下网址找到:pypi.org/project/psycopg2cffi/

连接

连接字符串:

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

psycopg2cffipsycopg2的一种适配版本,使用 CFFI 作为 C 层。这使其适用于例如 PyPy 的使用。文档与psycopg2相同。

另请参阅

sqlalchemy.dialects.postgresql.psycopg2

DBAPI

文档和下载信息(如果适用)可在以下网址找到:pypi.org/project/psycopg2cffi/

连接

连接字符串:

postgresql+psycopg2cffi://user:password@host:port/dbname[?key=value&key=value...]
posted @ 2024-06-22 11:33  绝不原创的飞龙  阅读(15)  评论(0编辑  收藏  举报