原文:
docs.sqlalchemy.org/en/20/contents.html
列的插入/更新默认值
原文:
docs.sqlalchemy.org/en/20/core/defaults.html
列的插入和更新默认值是指在针对该行进行插入或更新语句时,为该列创建默认值的函数,前提是对该列的插入或更新语句未提供任何值。也就是说,如果一个表有一个名为“timestamp”的列,并且进行了不包含该列值的插入语句,那么插入默认值将创建一个新值,例如当前时间,该值将用作要插入到“timestamp”列的值。如果语句包含该列的值,则默认值不会发生。
列默认值可以是服务器端函数或与数据库中的架构一起定义的常量值,在 DDL 中,或者作为 SQLAlchemy 直接在 INSERT 或 UPDATE 语句中呈现的 SQL 表达式;它们也可以是由 SQLAlchemy 在将数据传递到数据库之前调用的客户端 Python 函数或常量值。
注意
列默认处理程序不应与拦截和修改传递给语句的插入和更新语句中的值的构造混淆。这称为数据编组,在这里,在将列值发送到数据库之前,应用程序以某种方式修改列值。SQLAlchemy 提供了几种实现这一点的方法,包括使用自定义数据类型、SQL 执行事件以及 ORM 中的自定义验证器以及属性事件。列默认值仅在 SQL DML 语句中的某一列没有值时调用。
SQLAlchemy 提供了一系列关于在插入和更新语句中针对不存在的值进行默认生成函数的特性。选项包括:
- 插入和更新操作中用作默认值的标量值
- 在插入和更新操作中执行的 Python 函数
- 嵌入到插入语句中的 SQL 表达式(或在某些情况下提前执行的表达式)
- 嵌入到更新语句中的 SQL 表达式
- 插入时使用的服务器端默认值
- 用于更新时的服务器端触发器的标记
所有插入/更新默认值的一般规则是,只有当某一列的值未作为execute()
参数传递时,它们才会生效;否则,将使用给定的值。
标量默认值
最简单的默认值是用作列的默认值的标量值:
代码语言:javascript复制Table("mytable", metadata_obj, Column("somecolumn", Integer, default=12))
在上述情况下,如果没有提供其他值,则“12”将绑定为插入时的列值。
标量值也可以与 UPDATE 语句关联,但这不是很常见(因为 UPDATE 语句通常正在寻找动态默认值):
代码语言:javascript复制Table("mytable", metadata_obj, Column("somecolumn", Integer, onupdate=25))
Python 执行的函数
Column.default
和 Column.onupdate
关键字参数也接受 Python 函数。如果没有为该列提供其他值,则在插入或更新时调用这些函数,并且返回的值将用于列的值。下面说明了一个简单的“序列”,它将递增的计数器分配给主键列:
# a function which counts upwards
i = 0
def mydefault():
global i
i = 1
return i
t = Table(
"mytable",
metadata_obj,
Column("id", Integer, primary_key=True, default=mydefault),
)
应该注意,对于真正的“递增序列”行为,通常应使用数据库的内置功能,这可能包括序列对象或其他自动增量功能。对于主键列,SQLAlchemy 在大多数情况下将自动使用这些功能。请参阅关于 Column
的 API 文档,包括 Column.autoincrement
标志,以及本章后面关于 Sequence
的部分,了解标准主键生成技术的背景。
为了说明 onupdate
,我们将 Python 的 datetime
函数 now
赋值给 Column.onupdate
属性:
import datetime
t = Table(
"mytable",
metadata_obj,
Column("id", Integer, primary_key=True),
# define 'last_updated' to be populated with datetime.now()
Column("last_updated", DateTime, onupdate=datetime.datetime.now),
)
当执行更新语句并且没有为 last_updated
传递值时,将执行 datetime.datetime.now()
Python 函数,并将其返回值用作 last_updated
的值。请注意,我们将 now
提供为函数本身而不是调用它(即后面没有括号) - SQLAlchemy 将在语句执行时执行该函数。
上下文敏感的默认函数
Column.default
和 Column.onupdate
使用的 Python 函数也可以利用当前语句的上下文来确定一个值。语句的上下文是一个内部的 SQLAlchemy 对象,它包含有关正在执行的语句的所有信息,包括其源表达式、与之关联的参数和游标。与默认生成相关的上下文的典型用例是访问正在插入或更新的行上的其他值。要访问上下文,请提供一个接受单个 context
参数的函数:
def mydefault(context):
return context.get_current_parameters()["counter"] 12
t = Table(
"mytable",
metadata_obj,
Column("counter", Integer),
Column("counter_plus_twelve", Integer, default=mydefault, onupdate=mydefault),
)
上述默认生成函数适用于所有 INSERT 和 UPDATE 语句,其中未提供 counter_plus_twelve
的值,其值将是执行 counter
列的值加上数字 12。
对于使用“executemany”样式执行的单个语句,例如传递给 Connection.execute()
的多个参数集,用户定义的函数将为每组参数集调用一次。对于多值 Insert
构造的用例(例如通过 Insert.values()
方法设置了多个 VALUES 子句),用户定义的函数也将为每组参数集调用一次。
当调用该函数时,上下文对象(DefaultExecutionContext
的子类)中可用特殊方法 DefaultExecutionContext.get_current_parameters()
。该方法返回一个列键到值的字典,表示 INSERT 或 UPDATE 语句的完整值集。在多值 INSERT 构造的情况下,与单个 VALUES 子句对应的参数子集被从完整参数字典中隔离并单独返回。
新版本 1.2 中:添加了 DefaultExecutionContext.get_current_parameters()
方法,它通过提供将多个 VALUES 子句组织成单独参数字典的服务,改进了仍然存在的 DefaultExecutionContext.current_parameters
属性。## 客户端调用的 SQL 表达式
Column.default
和 Column.onupdate
关键字还可以传递 SQL 表达式,大多数情况下,这些表达式将在 INSERT 或 UPDATE 语句中直接呈现。
t = Table(
"mytable",
metadata_obj,
Column("id", Integer, primary_key=True),
# define 'create_date' to default to now()
Column("create_date", DateTime, default=func.now()),
# define 'key' to pull its default from the 'keyvalues' table
Column(
"key",
String(20),
default=select(keyvalues.c.key).where(keyvalues.c.type="type1"),
),
# define 'last_modified' to use the current_timestamp SQL function on update
Column("last_modified", DateTime, onupdate=func.utc_timestamp()),
)
在上面的例子中,create_date
列将在插入语句中使用 now()
SQL 函数的结果填充(根据后端的不同,在大多数情况下编译为 NOW()
或 CURRENT_TIMESTAMP
),而 key
列将使用另一个表的 SELECT 子查询的结果填充。当为该表发出更新语句时,last_modified
列将填充为 SQL UTC_TIMESTAMP()
MySQL 函数的值。
注意
在使用 func
构造与 SQL 函数时,我们“调用”命名函数,例如在 func.now()
中使用括号。这与当我们将 Python 可调用对象指定为默认值时不同,例如 datetime.datetime
,在这种情况下,我们传递函数本身,但我们自己不调用它。对于 SQL 函数,调用 func.now()
返回将“NOW”函数渲染到正在发射的 SQL 中的 SQL 表达式对象。
Column.default
和 Column.onupdate
指定的默认值和更新 SQL 表达式在插入或更新语句发生时由 SQLAlchemy 明确调用,通常在 DML 语句中内联渲染,除了下面列出的特定情况。这与“服务器端”默认值不同,后者是表的 DDL 定义的一部分,例如作为“CREATE TABLE”语句的一部分,这种情况可能更常见。对于服务器端默认值,请参阅下一节 Server-invoked DDL-Explicit Default Expressions。
当通过 Column.default
指示的 SQL 表达式与主键列一起使用时,存在一些情况下,SQLAlchemy 必须“预执行”默认生成 SQL 函数,这意味着它在单独的 SELECT 语句中被调用,并且生成的值作为参数传递给 INSERT。这仅发生在要求返回此主键值的 INSERT 语句的主键列上,其中不能使用 RETURNING 或 cursor.lastrowid
。指定了 insert.inline
标志的 Insert
构造将始终内联渲染默认表达式。
当语句使用单个参数集执行时(即不是“executemany”样式的执行),返回的CursorResult
将包含通过CursorResult.postfetch_cols()
可访问的集合,该集合包含所有具有内联执行默认值的Column
对象的列表。同样,语句绑定的所有参数,包括预先执行的所有 Python 和 SQL 表达式,都存在于CursorResult.last_inserted_params()
或CursorResult.last_updated_params()
集合中的CursorResult
上。CursorResult.inserted_primary_key
集合包含插入行的主键值列表(列表格式,以便单列和复合列主键以相同的格式表示)。 ## 服务器调用的 DDL-显式默认表达式
SQL 表达式默认值的变体是Column.server_default
,在Table.create()
操作期间会放置在 CREATE TABLE 语句中:
t = Table(
"test",
metadata_obj,
Column("abc", String(20), server_default="abc"),
Column("created_at", DateTime, server_default=func.sysdate()),
Column("index_value", Integer, server_default=text("0")),
)
对于上述表格的创建调用将产生:
代码语言:javascript复制CREATE TABLE test (
abc varchar(20) default 'abc',
created_at datetime default sysdate,
index_value integer default 0
)
上面的示例说明了Column.server_default
的两种典型用例,即 SQL 函数(在上面的示例中为 SYSDATE)以及服务器端常量值(在上面的示例中为整数“0”)。建议对任何文字 SQL 值使用text()
构造,而不是传递原始值,因为 SQLAlchemy 通常不会对这些值执行任何引号添加或转义。
与客户端生成的表达式类似,Column.server_default
可以适应一般的 SQL 表达式,但通常预期这些将是简单的函数和表达式,而不是像嵌入式 SELECT 这样更复杂的情况。 ## 标记隐式生成的值、时间戳和触发列
列在插入或更新时基于其他服务器端数据库机制生成新值,例如某些平台上的时间戳列所见的数据库特定的自动生成行为,以及在插入或更新时调用的自定义触发器生成新值,可以使用FetchedValue
作为标记:
from sqlalchemy.schema import FetchedValue
t = Table(
"test",
metadata_obj,
Column("id", Integer, primary_key=True),
Column("abc", TIMESTAMP, server_default=FetchedValue()),
Column("def", String(20), server_onupdate=FetchedValue()),
)
FetchedValue
指示符不会影响 CREATE TABLE 的渲染 DDL。相反,它标记列将在 INSERT 或 UPDATE 语句的过程中由数据库填充新值,并且对于支持的数据库,可以用于指示该列应该是 RETURNING 或 OUTPUT 子句的一部分。诸如 SQLAlchemy ORM 之类的工具随后利用此标记以了解如何在此类操作之后获取列的值。特别是,ValuesBase.return_defaults()
方法可与Insert
或Update
构造一起使用,以指示应返回这些值。
有关在 ORM 中使用FetchedValue
的详细信息,请参阅获取服务器生成的默认值。
警告
Column.server_onupdate
指令目前不会生成 MySQL 的“ON UPDATE CURRENT_TIMESTAMP()”子句。请参阅为 MySQL / MariaDB 的 explicit_defaults_for_timestamp 渲染 ON UPDATE CURRENT TIMESTAMP 了解如何生成此子句的背景信息。
另请参阅
获取服务器生成的默认值 ## 定义序列
SQLAlchemy 使用Sequence
对象表示数据库序列,被视为“列默认值”的特例。它仅对显式支持序列的数据库产生影响,其中包括 PostgreSQL、Oracle、MS SQL Server 和 MariaDB 在内的 SQLAlchemy 包含的方言。否则,Sequence
对象将被忽略。
提示
在较新的数据库引擎中,应该优先使用Identity
构造而不是Sequence
生成整数主键值。请参阅 Identity Columns (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY) 了解此构造的背景信息。
Sequence
可以放置在任何列上作为“默认”生成器,在 INSERT 操作期间使用,并且如果需要,还可以配置为在 UPDATE 操作期间触发。它最常与单个整数主键列一起使用:
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
Sequence("cart_id_seq", start=1),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上述情况中,表cartitems
与名为cart_id_seq
的序列相关联。对上述表执行MetaData.create_all()
将包括:
CREATE SEQUENCE cart_id_seq START WITH 1
CREATE TABLE cartitems (
cart_id INTEGER NOT NULL,
description VARCHAR(40),
createdate TIMESTAMP WITHOUT TIME ZONE,
PRIMARY KEY (cart_id)
)
提示
当使用具有显式模式名称的表时(详见指定模式名称),Table
的配置模式不会自动与嵌入的Sequence
共享,而是需要指定Sequence.schema
:
Sequence("cart_id_seq", start=1, schema="some_schema")
Sequence
还可以自动使用正在使用的MetaData
中的MetaData.schema
设置;有关背景,请参阅将序列与 MetaData 关联。
当针对cartitems
表调用Insert
DML 构造时,如果未传递cart_id
列的显式值,则将使用cart_id_seq
序列在参与的后端生成值。通常,序列函数被嵌入到 INSERT 语句中,与 RETURNING 结合使用,以便将新生成的值返回给 Python 进程:
INSERT INTO cartitems (cart_id, description, createdate)
VALUES (next_val(cart_id_seq), 'some description', '2015-10-15 12:00:15')
RETURNING cart_id
当使用Connection.execute()
调用Insert
构造时,包括但不限于使用Sequence
生成的新生成的主键标识符,可通过CursorResult
构造的CursorResult.inserted_primary_key
属性获取。
当Sequence
与Column
作为其Python 端默认生成器关联时,Sequence
也将受到“CREATE SEQUENCE”和“DROP SEQUENCE” DDL 的影响,当为拥有的Table
发出类似 DDL 时,比如使用MetaData.create_all()
为一系列表生成 DDL 时。
Sequence
也可以直接与MetaData
构造关联。这允许Sequence
同时用于多个Table
,并且还允许继承MetaData.schema
参数。请参见将序列与 MetaData 关联部分了解背景信息。
在 SERIAL 列上关联序列
PostgreSQL 的 SERIAL 数据类型是一个自增类型,意味着在发出 CREATE TABLE 时隐式创建一个 PostgreSQL 序列。当为Column
指定Sequence
构造时,可以通过为Sequence.optional
参数指定True
的值来指示在这种特定情况下不应使用它。这允许给定的Sequence
用于没有其他主键生成系统的后端,但在后端(如 PostgreSQL)中会自动生成特定列的序列时忽略它:
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
# use an explicit Sequence where available, but not on
# PostgreSQL where SERIAL will be used
Sequence("cart_id_seq", start=1, optional=True),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上面的示例中,对于 PostgreSQL 的CREATE TABLE
将使用SERIAL
数据类型来创建cart_id
列,而cart_id_seq
序列将被忽略。然而在 Oracle 上,cart_id_seq
序列将被显式创建。
提示
SERIAL 和 SEQUENCE 的这种特定交互相当传统,就像其他情况一样,使用Identity
将简化操作,只需在所有支持的后端上使用IDENTITY
即可。
单独执行序列
SEQUENCE 是 SQL 中的一类一流模式对象,可用于独立生成数据库中的值。如果有一个Sequence
对象,可以通过直接将其传递给 SQL 执行方法来调用其“next value”指令:
with my_engine.connect() as conn:
seq = Sequence("some_sequence", start=1)
nextid = conn.execute(seq)
为了将Sequence
的“next value”函数嵌入 SQL 语句(如 SELECT 或 INSERT)中,使用Sequence.next_value()
方法,在语句编译时会生成适用于目标后端的 SQL 函数:
>>> my_seq = Sequence("some_sequence", start=1)
>>> stmt = select(my_seq.next_value())
>>> print(stmt.compile(dialect=postgresql.dialect()))
SELECT nextval('some_sequence') AS next_value_1
将序列与 MetaData 关联
对于要与任意Table
对象关联的Sequence
,可以使用Sequence.metadata
参数将Sequence
与特定的MetaData
关联:
seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)
这样的序列可以按照通常的方式与列关联:
代码语言:javascript复制table = Table(
"cartitems",
metadata_obj,
seq,
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上面的示例中,Sequence
对象被视为独立的模式构造,可以独立存在或在表之间共享。
明确将Sequence
与MetaData
关联允许以下行为:
-
Sequence
将继承目标MetaData
指定的MetaData.schema
参数,这会影响 CREATE / DROP DDL 的生成以及Sequence.next_value()
函数在 SQL 语句中的呈现方式。 -
MetaData.create_all()
和MetaData.drop_all()
方法将发出 CREATE / DROP 命令,即使此Sequence
没有与任何属于此MetaData
的Table
/Column
关联。
将序列关联为服务器端默认值
注意
以下技术仅已知适用于 PostgreSQL 数据库。它不适用于 Oracle。
上文说明了如何将 Sequence
关联到 Column
作为 Python 端的默认生成器:
Column(
"cart_id",
Integer,
Sequence("cart_id_seq", metadata=metadata_obj, start=1),
primary_key=True,
)
在上述情况下,当相关的 Table
被创建 / 删除时,Sequence
将自动受到 CREATE SEQUENCE / DROP SEQUENCE DDL 的影响。然而,当发出 CREATE TABLE 时,该序列不会作为列的服务器端默认值存在。
如果我们希望序列被用作服务器端默认值,即使我们从 SQL 命令行向表发出 INSERT 命令,它也会生效,我们可以使用 Column.server_default
参数与序列的值生成函数一起使用,该函数可从 Sequence.next_value()
方法中获得。下面我们展示了相同的 Sequence
与 Column
关联,既作为 Python 端的默认生成器,也作为服务器端的默认生成器:
cart_id_seq = Sequence("cart_id_seq", metadata=metadata_obj, start=1)
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
cart_id_seq,
server_default=cart_id_seq.next_value(),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
或者使用 ORM:
代码语言:javascript复制class CartItem(Base):
__tablename__ = "cartitems"
cart_id_seq = Sequence("cart_id_seq", metadata=Base.metadata, start=1)
cart_id = Column(
Integer, cart_id_seq, server_default=cart_id_seq.next_value(), primary_key=True
)
description = Column(String(40))
createdate = Column(DateTime)
当发出“CREATE TABLE”语句时,在 PostgreSQL 上,它将被表述为:
代码语言:javascript复制CREATE TABLE cartitems (
cart_id INTEGER DEFAULT nextval('cart_id_seq') NOT NULL,
description VARCHAR(40),
createdate TIMESTAMP WITHOUT TIME ZONE,
PRIMARY KEY (cart_id)
)
在 Python 端和服务器端默认生成上下文中放置Sequence
可确保“主键获取”逻辑在所有情况下都能正常工作。通常,支持序列的数据库也支持 INSERT 语句的 RETURNING,当发出此语句时,SQLAlchemy 会自动使用。但是,如果对于特定的插入操作不使用 RETURNING,则 SQLAlchemy 更倾向于在 INSERT 语句之外“预执行”序列,这仅在将序列包含为 Python 端默认生成函数时才有效。
该示例还直接将Sequence
与封闭的MetaData
关联,这再次确保Sequence
与MetaData
集合的参数完全关联,包括默认模式(如果有)。
另请参阅
Sequences/SERIAL/IDENTITY - 在 PostgreSQL 方言文档中
RETURNING 支持 - 在 Oracle 方言文档中 ## 计算列 (GENERATED ALWAYS AS)
版本 1.3.11 中的新功能。
Computed
构造允许在 DDL 中声明一个“GENERATED ALWAYS AS”列的Column
,即一个由数据库服务器计算值的列。该构造接受一个 SQL 表达式,通常使用字符串或text()
构造进行文本声明,类似于CheckConstraint
的方式。然后数据库服务器解释 SQL 表达式以确定行内列的值。
示例:
代码语言:javascript复制from sqlalchemy import Table, Column, MetaData, Integer, Computed
metadata_obj = MetaData()
square = Table(
"square",
metadata_obj,
Column("id", Integer, primary_key=True),
Column("side", Integer),
Column("area", Integer, Computed("side * side")),
Column("perimeter", Integer, Computed("4 * side")),
)
在 PostgreSQL 12 后端运行时,square
表的 DDL 如下所示:
CREATE TABLE square (
id SERIAL NOT NULL,
side INTEGER,
area INTEGER GENERATED ALWAYS AS (side * side) STORED,
perimeter INTEGER GENERATED ALWAYS AS (4 * side) STORED,
PRIMARY KEY (id)
)
值在 INSERT 和 UPDATE 时是否持久化,或者在获取时是否计算,是数据库的实现细节;前者称为“stored”,后者称为“virtual”。一些数据库实现支持两者,但有些只支持其中一个。可以指定可选的Computed.persisted
标志为 True
或 False
,以指示在 DDL 中是否应该呈现“STORED”或“VIRTUAL”关键字,但是如果目标后端不支持该关键字,则会引发错误;如果不设置,将为目标后端使用一个有效的默认值。
Computed
构造是 FetchedValue
对象的子类,将自己设置为目标 Column
的“服务器默认值”和“服务器更新”生成器,这意味着在生成 INSERT 和 UPDATE 语句时,它将被视为默认生成列,并且在使用 ORM 时将被作为生成列获取。这包括在数据库支持 RETURNING 且要急切地获取生成值时,它将成为数据库的 RETURNING 子句的一部分。
注意
使用 Computed
构造定义的 Column
可能不会存储除服务器应用于其外的任何值; 当为此类列传递值以在 INSERT 或 UPDATE 中写入时,SQLAlchemy 的行为目前是忽略该值。
“GENERATED ALWAYS AS” 目前已知受到支持的数据库有:
- MySQL 版本 5.7 及更高版本
- MariaDB 10.x 系列及更高版本
- PostgreSQL 版本 12 及更高版本
- Oracle - 值得注意的是,RETURNING 在 UPDATE 中不正确地工作(当包含计算列的 UPDATE…RETURNING 被渲染时,会发出此警告)
- Microsoft SQL Server
- SQLite 版本 3.31
当 Computed
与不受支持的后端一起使用时,如果目标方言不支持它,则在尝试渲染构造时会引发 CompileError
。否则,如果方言支持它但正在使用的特定数据库服务器版本不支持它,则在将 DDL 发送到数据库时会引发 DBAPIError
的子类,通常是 OperationalError
。
另请参阅
Computed
## 标识列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)
版本 1.4 中新增。
Identity
构造允许将 Column
声明为标识列,并在 DDL 中渲染为 “GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”。标识列的值是由数据库服务器自动使用递增(或递减)序列生成的。该构造与 Sequence
共享控制数据库行为的大多数选项。
示例:
代码语言:javascript复制from sqlalchemy import Table, Column, MetaData, Integer, Identity, String
metadata_obj = MetaData()
data = Table(
"data",
metadata_obj,
Column("id", Integer, Identity(start=42, cycle=True), primary_key=True),
Column("data", String),
)
在 PostgreSQL 12 后端运行时,data
表的 DDL 如下所示:
CREATE TABLE data (
id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
data VARCHAR,
PRIMARY KEY (id)
)
数据库将在插入时为 id
列生成值,从 42
开始,如果语句中尚未包含 id
列的值。标识列还可以要求数据库生成列的值,忽略语句中传递的值或引发错误,具体取决于后端。要激活此模式,请在 Identity
构造中将参数 Identity.always
设置为 True
。更新前面的示例以包含此参数将生成以下 DDL:
CREATE TABLE data (
id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
data VARCHAR,
PRIMARY KEY (id)
)
Identity
构造是 FetchedValue
对象的子类,并且将自身设置为目标 Column
的“服务器默认”生成器,这意味着当生成 INSERT 语句时,它将被视为默认生成列,以及在使用 ORM 时,它将被作为生成列提取。这包括对于支持 RETURNING 的数据库,它将成为 RETURNING 子句的一部分,并且生成的值将被急切地提取。
目前已知支持 Identity
构造的数据库有:
- PostgreSQL 版本为 10。
- Oracle 版本为 12。 还支持传递
always=None
以启用默认生成模式,并传递参数on_null=True
以指定在使用 “BY DEFAULT” 标识列时“ON NULL”。 - Microsoft SQL Server。 MSSQL 使用自定义语法,仅支持
start
和increment
参数,并忽略所有其他参数。
当与不受支持的后端一起使用时,Identity
将被忽略,并且将使用默认的 SQLAlchemy 逻辑自动递增列。
当 Column
同时指定 Identity
并将 Column.autoincrement
设置为 False
时,会引发错误。
另请参阅
Identity
默认对象 API
对象名称 | 描述 |
---|---|
ColumnDefault | 列的普通默认值。 |
Computed | 定义生成列,即“GENERATED ALWAYS AS”语法。 |
DefaultClause | 由 DDL 指定的默认列值。 |
DefaultGenerator | 列 默认 值的基类。 |
FetchedValue | 用于透明数据库端默认值的标记。 |
Identity | 定义标识列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。 |
Sequence | 表示命名的数据库序列。 |
class sqlalchemy.schema.Computed
定义一个生成列,即“GENERATED ALWAYS AS”语法。
Computed
构造是一个内联构造,添加到 Column
对象的参数列表中:
from sqlalchemy import Computed
Table('square', metadata_obj,
Column('side', Float, nullable=False),
Column('area', Float, Computed('side * side'))
)
详细信息请参阅下面链接的文档。
新于版本 1.3.11。
请参阅
计算列(GENERATED ALWAYS AS)
成员
init(), copy()
类签名
类sqlalchemy.schema.Computed
(sqlalchemy.schema.FetchedValue
,sqlalchemy.schema.SchemaItem
)
method __init__(sqltext: _DDLColumnArgument, persisted: bool | None = None) → None
构造一个 GENERATED ALWAYS AS DDL 构造,以配合 Column
。
参数:
-
sqltext
– 包含列生成表达式的字符串,该表达式将直接使用,或者是一个 SQL 表达式构造,比如text()
对象。如果以字符串形式给出,则将该对象转换为text()
对象。 警告 传递给Computed
的Computed.sqltext
参数可以作为 Python 字符串参数传递,它将被视为受信任的 SQL 文本并按给定方式呈现。请勿将不受信任的输入传递给此参数。 -
persisted
– 可选,控制该列在数据库中的持久化方式。可能的值包括:-
None
,默认值,它将使用数据库定义的默认持久化方式。 -
True
,将呈现GENERATED ALWAYS AS ... STORED
,或者如果目标数据库支持的话,将呈现等效值。 -
False
,将呈现GENERATED ALWAYS AS ... VIRTUAL
,或者如果目标数据库支持的话,将呈现等效值。
如果数据库不支持该持久化选项,则指定
True
或False
可能会在将 DDL 发出到目标数据库时引发错误。将此参数保留为其默认值None
保证在所有支持GENERATED ALWAYS AS
的数据库上都可以成功。 -
method copy(*, target_table: Table | None = None, **kw: Any) → Computed
自版本 1.4 起已弃用:Computed.copy()
方法已弃用,并将在将来的版本中删除。
class sqlalchemy.schema.ColumnDefault
列上的纯默认值。
这可能对应于一个常量、一个可调用函数或一个 SQL 子句。
ColumnDefault
在 Column
的 default
、onupdate
参数被使用时会自动生成。一个 ColumnDefault
也可以作为位置参数传递。
例如,以下内容:
代码语言:javascript复制Column('foo', Integer, default=50)
等价于:
代码语言:javascript复制Column('foo', Integer, ColumnDefault(50))
类签名
类 sqlalchemy.schema.ColumnDefault
(sqlalchemy.schema.DefaultGenerator
,abc.ABC
)
class sqlalchemy.schema.DefaultClause
DDL 指定的 DEFAULT 列值。
DefaultClause
是一个 FetchedValue
,当发出 “CREATE TABLE” 时也会生成一个“DEFAULT”子句。
当 Column
的 server_default
、server_onupdate
参数被使用时,DefaultClause
会自动生成。一个 DefaultClause
也可以作为位置参数传递。
例如,以下内容:
代码语言:javascript复制Column('foo', Integer, server_default="50")
等价于:
代码语言:javascript复制Column('foo', Integer, DefaultClause("50"))
类签名
类 sqlalchemy.schema.DefaultClause
(sqlalchemy.schema.FetchedValue
)
class sqlalchemy.schema.DefaultGenerator
列默认值的基类。
此对象仅出现在 column.default 或 column.onupdate。它不能作为服务器默认值有效。
类签名
类 sqlalchemy.schema.DefaultGenerator
(sqlalchemy.sql.expression.Executable
,sqlalchemy.schema.SchemaItem
)
class sqlalchemy.schema.FetchedValue
用于透明数据库端默认值的标记。
当数据库配置为为列提供一些自动默认值时,请使用 FetchedValue
。
例如:
代码语言:javascript复制Column('foo', Integer, FetchedValue())
将指示某个触发器或默认生成器在 INSERT 期间为 foo
列创建一个新值。
另请参阅
标记隐式生成的值、时间戳和触发列
类签名
类 sqlalchemy.schema.FetchedValue
(sqlalchemy.sql.expression.SchemaEventTarget
)
class sqlalchemy.schema.Sequence
表示一个命名的数据库序列。
Sequence
对象表示数据库序列的名称和配置参数。它还表示一个可以被 SQLAlchemy Engine
或 Connection
“执行”的结构,为目标数据库渲染适当的“下一个值”函数并返回结果。
Sequence
通常与主键列关联:
some_table = Table(
'some_table', metadata,
Column('id', Integer, Sequence('some_table_seq', start=1),
primary_key=True)
)
当为上述 Table
发射 CREATE TABLE 时,如果目标平台支持序列,则也会发射 CREATE SEQUENCE 语句。对于不支持序列的平台,将忽略 Sequence
构造。
另请参阅
定义序列
CreateSequence
DropSequence
成员
init(), create(), drop(), next_value()
类签名
类 sqlalchemy.schema.Sequence
(sqlalchemy.schema.HasSchemaAttr
, sqlalchemy.schema.IdentityOptions
, sqlalchemy.schema.DefaultGenerator
)
method __init__(name: str, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, schema: str | Literal[SchemaConst.BLANK_SCHEMA] | None = None, cache: int | None = None, order: bool | None = None, data_type: _TypeEngineArgument[int] | None = None, optional: bool = False, quote: bool | None = None, metadata: MetaData | None = None, quote_schema: bool | None = None, for_update: bool = False) → None
构建一个 Sequence
对象。
参数:
-
name
– 序列的名称。 -
start
– 开始索引。 序列的起始索引。在将 CREATE SEQUENCE 命令发射到数据库时,此值被用作“START WITH”子句的值。如果为None
,则省略该子句,大多数平台上表示起始值为 1。 从版本 2.0 开始更改:要求Sequence.start
参数以发射 DDL “START WITH”。这是在版本 1.4 中进行的一项更改的反转,该更改如果未包括Sequence.start
将隐式渲染“START WITH 1”。有关更多详细信息,请参阅 序列结构还原为没有任何显式默认“开始”值;影响 MS SQL Server。 -
increment
– 序列的增量值。在将 CREATE SEQUENCE 命令发射到数据库时,此值被用作“INCREMENT BY”子句的值。如果为None
,则省略该子句,大多数平台上表示增量为 1。 -
minvalue
– 序列的最小值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“MINVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和 -2⁶³-1。 -
maxvalue
– 序列的最大值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“MAXVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和 -1。 -
nominvalue
– 序列没有最小值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“NO MINVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和 -2⁶³-1。 -
nomaxvalue
– 序列没有最大值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“NO MAXVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和 -1。 -
cycle
– 当升序或降序序列达到最大值或最小值时,允许序列环绕。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“CYCLE”子句。如果达到限制,则下一个生成的数字将是最小值或最大值,分别是升序或降序。如果 cycle=False(默认值),在序列达到其最大值后,任何对 nextval 的调用都将返回错误。 -
schema
– 序列的可选模式名称,如果位于默认模式之外的模式中。当MetaData
也存在时,选择模式名称的规则与Table.schema
相同。 -
cache
– 可选整数值;提前计算序列中的未来值的数量。呈现 Oracle 和 PostgreSQL 可理解的 CACHE 关键字。 -
order
– 可选布尔值;如果为True
,则呈现 ORDER 关键字,Oracle 可理解,表示序列是有序的。可能需要使用 Oracle RAC 提供确定性排序。 -
data_type
– 序列返回的类型,适用于允许我们在 INTEGER、BIGINT 等之间进行选择的方言(例如,mssql)。 新版本 1.4.0 中新增。 -
optional
– 布尔值,当为True
时,表示此Sequence
对象只需在没有其他方法生成主键标识符的后端上显式生成。目前,这实际上意味着,“在 PostgreSQL 后端上不要创建此序列,因为 SERIAL 关键字会自动为我们创建序列”。 -
quote
– 布尔值,当为True
或False
时,明确地强制引用Sequence.name
的名称,打开或关闭。当保留其默认值None
时,基于大小写和保留字的常规引用规则生效。 -
quote_schema
– 设置对schema
名称的引用首选项。 -
metadata
– 可选的MetaData
对象,此Sequence
将与之关联。与MetaData
关联的Sequence
具有以下功能:-
Sequence
将继承指定给目标MetaData
的MetaData.schema
参数,这会影响 CREATE / DROP DDL 的生成(如果有)。 -
Sequence.create()
和Sequence.drop()
方法会自动使用绑定到MetaData
对象的引擎(如果有)。 -
MetaData.create_all()
和MetaData.drop_all()
方法将为此Sequence
发出 CREATE / DROP,即使此Sequence
未与此MetaData
的任何成员Table
/Column
关联。
上述行为只有在通过此参数将
Sequence
明确关联到MetaData
时才会发生。 另请参阅 将序列与 MetaData 关联 - 关于Sequence.metadata
参数的详细讨论。 -
-
for_update
– 表示当与Column
关联时,此Sequence
应在该列的表上进行 UPDATE 语句调用,而不是在该语句中否则在该列中没有值。
method create(bind: _CreateDropBind, checkfirst: bool = True) → None
在数据库中创建此序列。
代码语言:javascript复制method drop(bind: _CreateDropBind, checkfirst: bool = True) → None
从数据库中删除此序列。
代码语言:javascript复制method next_value() → Function[int]
返回一个next_value
函数元素,该函数将为此Sequence
在任何 SQL 表达式中呈现适当的增量函数。
class sqlalchemy.schema.Identity
定义一个标识列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。
Identity
结构是添加到Column
对象的参数列表中的内联结构:
from sqlalchemy import Identity
Table('foo', metadata_obj,
Column('id', Integer, Identity())
Column('description', Text),
)
请参阅下面链接的文档以获取完整详情。
从版本 1.4 开始新增。
另请参阅
标识列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)
成员
init(), copy()
类签名
类sqlalchemy.schema.Identity
(sqlalchemy.schema.IdentityOptions
,sqlalchemy.schema.FetchedValue
,sqlalchemy.schema.SchemaItem
)
method __init__(always: bool = False, on_null: bool | None = None, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, cache: int | None = None, order: bool | None = None) → None
创建一个 DDL 结构GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
,用于配合Column
。
请参阅Sequence
文档,了解大多数参数的完整描述。
注意
MSSQL 支持此结构作为在列上生成 IDENTITY 的首选替代方案,但它使用的非标准语法仅支持Identity.start
和Identity.increment
。所有其他参数都会被忽略。
参数:
-
always
– 一个布尔值,表示标识列的类型。如果指定了False
,则默认情况下用户指定的值优先。如果指定了True
,则不接受用户指定的值(在某些后端,如 PostgreSQL,可以在插入时指定 OVERRIDING SYSTEM VALUE 或类似语句以覆盖序列值)。某些后端也对此参数有默认值,None
可以用于在 DDL 中省略渲染此部分。如果后端没有默认值,则将其视为False
。 -
on_null
– 设置为True
以与always=False
标识列一起指定 ON NULL。此选项仅在某些后端(如 Oracle)上受支持。 -
start
– 序列的起始索引。 -
increment
– 序列的增量值。 -
minvalue
– 序列的最小值。 -
maxvalue
– 序列的最大值。 -
nominvalue
– 序列的最小值不存在。 -
nomaxvalue
– 序列的最大值不存在。 -
cycle
– 当达到最大值或最小值时允许序列循环。 -
cache
– 可选的整数值;提前计算的序列中未来值的数量。 -
order
– 可选的布尔值;如果为 true,则呈现 ORDER 关键字。
method copy(**kw: Any) → Identity
自版本 1.4 起已弃用:Identity.copy()
方法已弃用,将在将来的版本中移除。
标量默认值
最简单的默认值是作为列默认值使用的标量值:
代码语言:javascript复制Table("mytable", metadata_obj, Column("somecolumn", Integer, default=12))
上述,如果未提供其他值,则值“12”将在插入时绑定为列值。
标量值也可能与 UPDATE 语句关联,尽管这不是很常见(因为 UPDATE 语句通常寻找动态默认值):
代码语言:javascript复制Table("mytable", metadata_obj, Column("somecolumn", Integer, onupdate=25))
Python 执行的函数
Column.default
和Column.onupdate
关键字参数也接受 Python 函数。如果未提供该列的其他值,则在插入或更新时调用这些函数,并使用返回的值作为列的值。以下示例说明了一个粗糙的“序列”,将递增计数器分配给主键列:
# a function which counts upwards
i = 0
def mydefault():
global i
i = 1
return i
t = Table(
"mytable",
metadata_obj,
Column("id", Integer, primary_key=True, default=mydefault),
)
应该注意,对于真正的“增量序列”行为,通常应该使用数据库的内置功能,这可能包括序列对象或其他自增能力。对于主键列,SQLAlchemy 在大多数情况下将自动使用这些功能。请参阅Column
的 API 文档,包括Column.autoincrement
标志,以及本章后面关于Sequence
的部分,了解标准主键生成技术的背景。
为了说明 onupdate,我们将 Python 的datetime
函数now
赋值给Column.onupdate
属性:
import datetime
t = Table(
"mytable",
metadata_obj,
Column("id", Integer, primary_key=True),
# define 'last_updated' to be populated with datetime.now()
Column("last_updated", DateTime, onupdate=datetime.datetime.now),
)
当执行更新语句并且未传递last_updated
值时,将执行datetime.datetime.now()
Python 函数,并将其返回值用作last_updated
的值。请注意,我们将now
作为函数本身提供,而不调用它(即后面没有括号)- SQLAlchemy 将在执行语句时执行该函数。
上下文敏感的默认函数
Column.default
和Column.onupdate
使用的 Python 函数也可以利用当前语句上下文来确定值。语句的上下文是一个内部的 SQLAlchemy 对象,包含有关正在执行的语句的所有信息,包括其源表达式、与之关联的参数和游标。在默认生成的上下文中,典型的用例是访问正在插入或更新的行上的其他值。要访问上下文,请提供一个接受单个context
参数的函数:
def mydefault(context):
return context.get_current_parameters()["counter"] 12
t = Table(
"mytable",
metadata_obj,
Column("counter", Integer),
Column("counter_plus_twelve", Integer, default=mydefault, onupdate=mydefault),
)
上述默认生成函数是这样应用的:它将用于所有未提供counter_plus_twelve
值的 INSERT 和 UPDATE 语句,并且该值将是执行counter
列时的任何值加上 12 的值。
对于使用“executemany”样式执行的单个语句,例如通过Connection.execute()
传递多个参数集的情况,用户定义的函数将为每组参数集调用一次。对于多值Insert
结构的用例(例如通过Insert.values()
方法设置了多个 VALUES 子句),用户定义的函数也将为每组参数集调用一次。
当函数被调用时,上下文对象(DefaultExecutionContext
的一个子类)中可用的特殊方法DefaultExecutionContext.get_current_parameters()
。此方法返回一个字典,其中键-值对表示 INSERT 或 UPDATE 语句的完整值集。在多值 INSERT 结构的情况下,与单个 VALUES 子句对应的参数子集将从完整参数字典中隔离并单独返回。
1.2 版中的新功能:增加了DefaultExecutionContext.get_current_parameters()
方法,它改进了仍然存在的DefaultExecutionContext.current_parameters
属性,通过提供将多个 VALUES 子句组织成单独参数字典的服务。### 上下文敏感的默认函数
由Column.default
和Column.onupdate
使用的 Python 函数还可以利用当前语句的上下文来确定一个值。语句的上下文是一个内部的 SQLAlchemy 对象,其中包含关于正在执行的语句的所有信息,包括其源表达式、与之关联的参数和游标。与默认生成相关的此上下文的典型用例是访问要插入或更新的行上的其他值。要访问上下文,请提供一个接受单个context
参数的函数:
def mydefault(context):
return context.get_current_parameters()["counter"] 12
t = Table(
"mytable",
metadata_obj,
Column("counter", Integer),
Column("counter_plus_twelve", Integer, default=mydefault, onupdate=mydefault),
)
上述默认生成函数被应用于所有 INSERT 和 UPDATE 语句,其中未提供counter_plus_twelve
的值,并且该值将为执行counter
列时存在的任何值加上 12。
对于使用“executemany”风格执行的单个语句,例如向 Connection.execute()
传递多个参数集的情况,用户定义的函数会为每个参数集调用一次。对于多值 Insert
结构的用例(例如通过 Insert.values()
方法设置了多个 VALUES 子句),用户定义的函数也会为每个参数集调用一次。
当函数被调用时,上下文对象(DefaultExecutionContext
的子类)中可用特殊方法DefaultExecutionContext.get_current_parameters()
。该方法返回一个字典,列键到值的映射,表示 INSERT 或 UPDATE 语句的完整值集。对于多值 INSERT 结构的情况,与单个 VALUES 子句对应的参数子集被从完整参数字典中隔离并单独返回。
1.2 版本中新增:增加了 DefaultExecutionContext.get_current_parameters()
方法,它改进了仍然存在的 DefaultExecutionContext.current_parameters
属性,提供了将多个 VALUES 子句组织成单独参数字典的服务。
客户端调用的 SQL 表达式
也可以传递 SQL 表达式给 Column.default
和 Column.onupdate
关键字,这在大多数情况下会在 INSERT 或 UPDATE 语句中内联呈现:
t = Table(
"mytable",
metadata_obj,
Column("id", Integer, primary_key=True),
# define 'create_date' to default to now()
Column("create_date", DateTime, default=func.now()),
# define 'key' to pull its default from the 'keyvalues' table
Column(
"key",
String(20),
default=select(keyvalues.c.key).where(keyvalues.c.type="type1"),
),
# define 'last_modified' to use the current_timestamp SQL function on update
Column("last_modified", DateTime, onupdate=func.utc_timestamp()),
)
在上述情况中,create_date
列将在 INSERT 语句期间填充 now()
SQL 函数的结果(在大多数情况下,根据后端编译为 NOW()
或 CURRENT_TIMESTAMP
),而 key
列将填充另一张表的 SELECT 子查询的结果。当为此表发出 UPDATE 语句时,last_modified
列将填充 SQL UTC_TIMESTAMP()
MySQL 函数的值。
注意
使用func
构造和 SQL 函数时,我们会“调用”命名函数,例如在 func.now()
中使用括号。这与当我们将 Python 可调用对象(例如 datetime.datetime
)指定为默认值时不同,其中我们传递函数本身,但我们不自己调用它。对于 SQL 函数,调用func.now()
将返回将“NOW”函数呈现为正在发出的 SQL 中的 SQL 表达式对象。
当发生 INSERT 或 UPDATE 语句时,SQLAlchemy 在 Column.default
和 Column.onupdate
指定的默认和更新 SQL 表达式明确调用它们,通常在 DML 语句中内联渲染,除了下面列出的某些情况。这与“服务器端”默认值不同,后者是表的 DDL 定义的一部分,例如作为“CREATE TABLE”语句的一部分,这可能更常见。有关服务器端默认值,请参阅下一节服务器调用 DDL-显式默认表达式。
当由Column.default
指示的 SQL 表达式与主键列一起使用时,有些情况下 SQLAlchemy 必须“预先执行”默认生成的 SQL 函数,这意味着它在单独的 SELECT 语句中被调用,并且生成的值作为参数传递给 INSERT。这仅发生在主键列为 INSERT 语句被要求返回该主键值的情况下,其中不能使用 RETURNING 或 cursor.lastrowid
。指定了insert.inline
标志的 Insert
构造将始终将默认表达式呈现为内联。
当执行语句使用单一参数集合(即不是“executemany”风格执行)时,返回的CursorResult
将包含一个可通过CursorResult.postfetch_cols()
访问的集合,其中包含所有具有内联执行默认值的Column
对象的列表。同样,绑定到语句的所有参数,包括所有预先执行的 Python 和 SQL 表达式,都存在于CursorResult.last_inserted_params()
或CursorResult.last_updated_params()
集合中的CursorResult
。CursorResult.inserted_primary_key
集合包含插入的行的主键值列表(列表使得单列和复合列主键以相同格式表示)。
服务器调用的 DDL 显式默认表达式
SQL 表达式默认的一种变体是Column.server_default
,在Table.create()
操作期间会被放置在 CREATE TABLE 语句中:
t = Table(
"test",
metadata_obj,
Column("abc", String(20), server_default="abc"),
Column("created_at", DateTime, server_default=func.sysdate()),
Column("index_value", Integer, server_default=text("0")),
)
对上述表的创建调用将产生:
代码语言:javascript复制CREATE TABLE test (
abc varchar(20) default 'abc',
created_at datetime default sysdate,
index_value integer default 0
)
上述示例说明了Column.server_default
的两种典型用法,即 SQL 函数(上述示例中的 SYSDATE)以及服务器端常量值(上述示例中的整数“0”)。建议对任何文字 SQL 值使用text()
构造,而不是传递原始值,因为 SQLAlchemy 通常不对这些值执行任何引用或转义。
与客户端生成的表达式类似,Column.server_default
可以容纳一般的 SQL 表达式,但是预期这些通常会是简单的函数和表达式,而不是更复杂的情况,比如嵌套的 SELECT。
标记隐式生成的值、时间戳和触发列
当插入或更新时,基于其他服务器端数据库机制生成新值的列,例如在某些平台上与时间戳列一起看到的数据库特定的自动生成行为,以及在插入或更新时调用的自定义触发器以生成新值,可以使用FetchedValue
作为标记:
from sqlalchemy.schema import FetchedValue
t = Table(
"test",
metadata_obj,
Column("id", Integer, primary_key=True),
Column("abc", TIMESTAMP, server_default=FetchedValue()),
Column("def", String(20), server_onupdate=FetchedValue()),
)
FetchedValue
指示器不会影响 CREATE TABLE 的渲染 DDL。相反,它标记了在 INSERT 或 UPDATE 语句的过程中由数据库填充新值的列,并且对于支持的数据库,可能会用于指示该列应该是 RETURNING 或 OUTPUT 子句的一部分。然后,诸如 SQLAlchemy ORM 之类的工具使用此标记来了解如何获取此类操作后列的值。特别是,可以使用ValuesBase.return_defaults()
方法与Insert
或Update
构造来指示应返回这些值。
有关使用 ORM 中的FetchedValue
的详细信息,请参阅获取服务器生成的默认值。
警告
Column.server_onupdate
指令目前不会生成 MySQL 的“ON UPDATE CURRENT_TIMESTAMP()”子句。有关如何生成此子句的背景信息,请参阅为 MySQL / MariaDB 的 explicit_defaults_for_timestamp 渲染 ON UPDATE CURRENT TIMESTAMP。
另请参阅
获取服务器生成的默认值
定义序列
SQLAlchemy 使用Sequence
对象表示数据库序列,这被认为是“列默认值”的特殊情况。它仅对具有对序列的明确支持的数据库产生影响,其中包括 SQLAlchemy 包含的方言中的 PostgreSQL、Oracle、MS SQL Server 和 MariaDB。否则,Sequence
对象将被忽略。
提示
在较新的数据库引擎中,应该优先使用Identity
构造生成整数主键值,而不是Sequence
。有关此构造的背景信息,请参阅 Identity Columns (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)。
Sequence
可以放置在任何列上作为“默认”生成器,在 INSERT 操作期间使用,并且如果需要,还可以配置在 UPDATE 操作期间触发。它通常与单个整数主键列一起使用:
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
Sequence("cart_id_seq", start=1),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上述情况下,表cartitems
与名为cart_id_seq
的序列相关联。发出上述表的MetaData.create_all()
将包括:
CREATE SEQUENCE cart_id_seq START WITH 1
CREATE TABLE cartitems (
cart_id INTEGER NOT NULL,
description VARCHAR(40),
createdate TIMESTAMP WITHOUT TIME ZONE,
PRIMARY KEY (cart_id)
)
提示
当使用具有显式模式名称的表(详细信息请参阅指定模式名称)时,Table
的配置模式不会自动由嵌入的Sequence
共享,而是需要指定Sequence.schema
:
Sequence("cart_id_seq", start=1, schema="some_schema")
Sequence
也可以自动使用正在使用的MetaData
的设置中的MetaData.schema
;有关背景信息,请参阅将序列与 MetaData 关联。
当针对cartitems
表调用Insert
DML 构造时,如果没有为cart_id
列传递显式值,则cart_id_seq
序列将用于在参与的后端生成一个值。通常,序列函数嵌入在 INSERT 语句中,与 RETURNING 结合在一起,以便新生成的值可以返回给 Python 进程:
INSERT INTO cartitems (cart_id, description, createdate)
VALUES (next_val(cart_id_seq), 'some description', '2015-10-15 12:00:15')
RETURNING cart_id
当使用Connection.execute()
来调用Insert
构造时,包括但不限于使用Sequence
生成的新生成的主键标识符,可以通过CursorResult
构造使用CursorResult.inserted_primary_key
属性获得。
当将 Sequence
关联到 Column
作为其 Python-side 默认生成器时,当为拥有 Table
发出类似 DDL 的情况下,例如使用 MetaData.create_all()
为一系列表生成 DDL 时,该 Sequence
也将受到 “CREATE SEQUENCE” 和 “DROP SEQUENCE” DDL 的约束。
Sequence
也可以直接与 MetaData
构造关联。这允许 Sequence
在多个 Table
中同时使用,并且还允许继承 MetaData.schema
参数。有关详情,请参见 将序列与元数据关联 部分。
在 SERIAL 列上关联一个序列
PostgreSQL 的 SERIAL 数据类型是一种自增类型,意味着在发出 CREATE TABLE 命令时隐式创建了一个 PostgreSQL 序列。当为 Column
指定了 Sequence
构造时,可以通过将 Sequence.optional
参数的值设置为 True
来指示在这种特定情况下不应使用它。这允许给定的 Sequence
用于没有其他替代主键生成系统的后端,但对于自动为特定列生成序列的后端(例如 PostgreSQL),可以忽略它:
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
# use an explicit Sequence where available, but not on
# PostgreSQL where SERIAL will be used
Sequence("cart_id_seq", start=1, optional=True),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上面的示例中,对于 PostgreSQL,CREATE TABLE
将使用 SERIAL
数据类型来创建 cart_id
列,并且 cart_id_seq
序列将被忽略。然而在 Oracle 中,cart_id_seq
序列将被显式创建。
提示
SERIAL 和 SEQUENCE 的这种特定交互在相当程度上是遗留的,在其他情况下,使用 Identity
将简化操作,只需在所有支持的后端上使用 IDENTITY
即可。
执行一个独立的序列
SEQUENCE 是 SQL 中的一种一流模式对象,可用于在数据库中独立生成值。如果有 Sequence
对象,可以通过直接将其传递给 SQL 执行方法来调用其“next value”指令:
with my_engine.connect() as conn:
seq = Sequence("some_sequence", start=1)
nextid = conn.execute(seq)
为了将 Sequence
的“next value”函数嵌入到类似于 SELECT 或 INSERT 的 SQL 语句中,可以使用 Sequence.next_value()
方法,该方法将在语句编译时生成适用于目标后端的 SQL 函数:
>>> my_seq = Sequence("some_sequence", start=1)
>>> stmt = select(my_seq.next_value())
>>> print(stmt.compile(dialect=postgresql.dialect()))
SELECT nextval('some_sequence') AS next_value_1
将序列与 MetaData 关联
对于将与任意 Table
对象关联的 Sequence
,可以使用 Sequence.metadata
参数将 Sequence
关联到特定的 MetaData
:
seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)
然后可以以通常的方式将这样的序列与列关联起来:
代码语言:javascript复制table = Table(
"cartitems",
metadata_obj,
seq,
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上面的示例中,Sequence
对象被视为独立的模式构造,可以独立存在或在表之间共享。
明确将 Sequence
与 MetaData
关联允许以下行为:
-
Sequence
将继承指定给目标MetaData
的MetaData.schema
参数,这影响了 CREATE / DROP DDL 的生成以及 SQL 语句中Sequence.next_value()
函数的呈现方式。 -
MetaData.create_all()
和MetaData.drop_all()
方法将发出 CREATE / DROP 用于此Sequence
,即使该Sequence
未与任何此MetaData
的成员Table
/Column
相关联。
将序列关联为服务器端默认值
注意
以下技术仅在 PostgreSQL 数据库中有效,不适用于 Oracle。
前面的部分说明了如何将 Sequence
与 Column
关联为Python 端默认生成器:
Column(
"cart_id",
Integer,
Sequence("cart_id_seq", metadata=metadata_obj, start=1),
primary_key=True,
)
在上述情况下,当相关的 Table
被 CREATE / DROP 时,Sequence
将自动受到 CREATE SEQUENCE / DROP SEQUENCE DDL 的影响。但是,当发出 CREATE TABLE 时,该序列不会作为列的服务器端默认值存在。
如果我们希望序列被用作服务器端默认值,即使我们从 SQL 命令行向表中发出 INSERT 命令,我们可以使用 Column.server_default
参数与序列的值生成函数一起使用,该函数可以从 Sequence.next_value()
方法中获取。下面我们将演示相同的 Sequence
作为 Python 端默认生成器以及服务器端默认生成器与 Column
相关联的情况:
cart_id_seq = Sequence("cart_id_seq", metadata=metadata_obj, start=1)
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
cart_id_seq,
server_default=cart_id_seq.next_value(),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
或者使用 ORM:
代码语言:javascript复制class CartItem(Base):
__tablename__ = "cartitems"
cart_id_seq = Sequence("cart_id_seq", metadata=Base.metadata, start=1)
cart_id = Column(
Integer, cart_id_seq, server_default=cart_id_seq.next_value(), primary_key=True
)
description = Column(String(40))
createdate = Column(DateTime)
当发出“CREATE TABLE”语句时,在 PostgreSQL 上,它将被生成为:
代码语言:javascript复制CREATE TABLE cartitems (
cart_id INTEGER DEFAULT nextval('cart_id_seq') NOT NULL,
description VARCHAR(40),
createdate TIMESTAMP WITHOUT TIME ZONE,
PRIMARY KEY (cart_id)
)
在 Python 端和服务器端默认生成上下文中放置 Sequence
确保“主键获取”逻辑在所有情况下都能正常工作。通常,启用序列的数据库还支持 INSERT 语句的 RETURNING,当发出此语句时,SQLAlchemy 会自动使用它。但是,如果对于特定的插入未使用 RETURNING,则 SQLAlchemy 更愿意在 INSERT 语句本身之外“预先执行”序列,只有在将序列作为 Python 端默认生成函数包含时才能正常工作。
该示例还将 Sequence
直接与封闭的 MetaData
关联起来,这再次确保 Sequence
完全与 MetaData
集合的参数相关联,包括默认模式(如果有)。
另请参阅
序列/SERIAL/IDENTITY - 在 PostgreSQL 方言文档中
返回支持 - 在 Oracle 方言文档中
将序列关联到 SERIAL 列
PostgreSQL 的 SERIAL 数据类型是一种自增类型,它意味着在发出 CREATE TABLE 时会隐式创建一个 PostgreSQL 序列。当为 Column
指定 Sequence
构造时,可以通过为 Sequence.optional
参数指定 True
值来表明在这种特定情况下不应使用它。这允许给定的 Sequence
用于没有其他替代主键生成系统的后端,但对于诸如 PostgreSQL 之类的后端,它会自动生成一个特定列的序列:
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
# use an explicit Sequence where available, but not on
# PostgreSQL where SERIAL will be used
Sequence("cart_id_seq", start=1, optional=True),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上面的例子中,对于 PostgreSQL 的 CREATE TABLE
将使用 SERIAL
数据类型来创建 cart_id
列,而 cart_id_seq
序列将被忽略。然而,在 Oracle 中,cart_id_seq
序列将被显式创建。
提示
SERIAL 和 SEQUENCE 的这种特定交互相当古老,与其他情况一样,改用 Identity
将简化操作,只需在所有支持的后端上使用 IDENTITY
即可。
单独执行序列
SEQUENCE 是 SQL 中的一级模式对象,并且可以在数据库中独立生成值。如果你有一个 Sequence
对象,可以直接将其传递给 SQL 执行方法,通过其“next value”指令来调用它:
with my_engine.connect() as conn:
seq = Sequence("some_sequence", start=1)
nextid = conn.execute(seq)
为了将 Sequence
的“next value”函数嵌入到类似 SELECT 或 INSERT 的 SQL 语句中,可以使用 Sequence.next_value()
方法,该方法将在语句编译时生成适合目标后端的 SQL 函数:
>>> my_seq = Sequence("some_sequence", start=1)
>>> stmt = select(my_seq.next_value())
>>> print(stmt.compile(dialect=postgresql.dialect()))
SELECT nextval('some_sequence') AS next_value_1
将 Sequence 与 MetaData 关联起来
对于要与任意 Table
对象关联的 Sequence
,可以使用 Sequence.metadata
参数将 Sequence
关联到特定的 MetaData
:
seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)
这样的序列可以按照通常的方式与列关联起来:
代码语言:javascript复制table = Table(
"cartitems",
metadata_obj,
seq,
Column("description", String(40)),
Column("createdate", DateTime()),
)
在上面的例子中,Sequence
对象被视为一个独立的模式构造,可以独立存在或在表之间共享。
显式地将 Sequence
与 MetaData
关联起来,可以实现以下行为:
-
Sequence
会继承指定给目标MetaData
的MetaData.schema
参数,这会影响 CREATE / DROP DDL 的生成,以及Sequence.next_value()
函数在 SQL 语句中的呈现方式。 -
MetaData.create_all()
和MetaData.drop_all()
方法将为此Sequence
发出 CREATE / DROP,即使该Sequence
未与此MetaData
的任何成员Table
/Column
关联。
将 Sequence 关联为服务器端默认
注意
以下技术仅在 PostgreSQL 数据库中可用。它在 Oracle 中不起作用。
前面的部分演示了如何将 Sequence
关联到 Column
作为Python 端默认生成器:
Column(
"cart_id",
Integer,
Sequence("cart_id_seq", metadata=metadata_obj, start=1),
primary_key=True,
)
在上述情况下,当相关的 Table
要被创建 / 删除时,Sequence
将自动受到 CREATE SEQUENCE / DROP SEQUENCE DDL 的影响。但是,在发出 CREATE TABLE 时,该序列不会出现为该列的服务器端默认。
如果我们希望序列被用作服务器端默认,即使我们从 SQL 命令行向表中发出 INSERT 命令,我们可以使用 Column.server_default
参数,与序列的值生成函数一起使用,该函数可以从 Sequence.next_value()
方法获得。下面我们演示了相同的 Sequence
同时关联到 Column
,既作为 Python 端的默认生成器,又作为服务器端的默认生成器:
cart_id_seq = Sequence("cart_id_seq", metadata=metadata_obj, start=1)
table = Table(
"cartitems",
metadata_obj,
Column(
"cart_id",
Integer,
cart_id_seq,
server_default=cart_id_seq.next_value(),
primary_key=True,
),
Column("description", String(40)),
Column("createdate", DateTime()),
)
或使用 ORM:
代码语言:javascript复制class CartItem(Base):
__tablename__ = "cartitems"
cart_id_seq = Sequence("cart_id_seq", metadata=Base.metadata, start=1)
cart_id = Column(
Integer, cart_id_seq, server_default=cart_id_seq.next_value(), primary_key=True
)
description = Column(String(40))
createdate = Column(DateTime)
在发出“CREATE TABLE”语句时,在 PostgreSQL 上会发出:
代码语言:javascript复制CREATE TABLE cartitems (
cart_id INTEGER DEFAULT nextval('cart_id_seq') NOT NULL,
description VARCHAR(40),
createdate TIMESTAMP WITHOUT TIME ZONE,
PRIMARY KEY (cart_id)
)
在 Python 端和服务器端默认生成上下文中放置Sequence
可以确保“主键提取”逻辑在所有情况下都有效。 通常,启用序列的数据库也支持对 INSERT 语句使用 RETURNING,当发出此语句时,SQLAlchemy 会自动使用它。 但是,如果对特定插入未使用 RETURNING,则 SQLAlchemy 更愿意在 INSERT 语句本身之外“预执行”序列,这仅在序列作为 Python 端默认生成器函数时有效。
该示例还将Sequence
直接与封闭的MetaData
关联起来,这再次确保了Sequence
与MetaData
集合的参数完全关联,包括默认模式(如果有)。
另请参阅
序列/SERIAL/IDENTITY - 在 PostgreSQL 方言文档中
RETURNING 支持 - 在 Oracle 方言文档中
计算列(GENERATED ALWAYS AS)
1.3.11 版中新增。
Computed
构造允许将 Column
声明为“GENERATED ALWAYS AS”列,在 DDL 中,即由数据库服务器计算值的列。 该构造接受一个 SQL 表达式,通常使用字符串或 text()
构造进行文本声明,类似于 CheckConstraint
的方式。 然后,数据库服务器会解释该 SQL 表达式,以确定行内列的值。
示例:
代码语言:javascript复制from sqlalchemy import Table, Column, MetaData, Integer, Computed
metadata_obj = MetaData()
square = Table(
"square",
metadata_obj,
Column("id", Integer, primary_key=True),
Column("side", Integer),
Column("area", Integer, Computed("side * side")),
Column("perimeter", Integer, Computed("4 * side")),
)
在 PostgreSQL 12 后端上运行 square
表的 DDL 如下所示:
CREATE TABLE square (
id SERIAL NOT NULL,
side INTEGER,
area INTEGER GENERATED ALWAYS AS (side * side) STORED,
perimeter INTEGER GENERATED ALWAYS AS (4 * side) STORED,
PRIMARY KEY (id)
)
值是在 INSERT 和 UPDATE 时持久化,还是在获取时计算,是数据库的实现细节;前者称为“存储”,后者称为“虚拟”。 一些数据库实现支持两者,但有些只支持其中一个。 可以指定可选的 Computed.persisted
标志为 True
或 False
,以指示是否在 DDL 中渲染“STORED”或“VIRTUAL”关键字,但是如果目标后端不支持该关键字,则会引发错误; 如果将其设置为未设置,则将使用目标后端的有效默认值。
计算列
构造是 FetchedValue
对象的子类,并且会自行设置为目标 列
的“服务器默认值”和“服务器更新时生成器”,这意味着当生成 INSERT 和 UPDATE 语句时,它将被视为默认生成的列,以及当使用 ORM 时,它将被视为生成的列被获取。这包括它将作为数据库的 RETURNING 子句的一部分,对于支持 RETURNING 并且生成的值需要被急切地获取的数据库。
注
使用 计算列
构造定义的 列
可能不会存储除服务器应用之外的任何值;当尝试写入 INSERT 或 UPDATE 时,SQLAlchemy 目前的行为是将忽略该值。
“GENERATED ALWAYS AS” 目前已知受支持的数据库有:
- MySQL 版本 5.7 及以上
- MariaDB 10.x 系列及以上
- PostgreSQL 版本 12 及以上
- Oracle - 注意 RETURNING 在 UPDATE 中无法正常工作(在包含计算列的 UPDATE…RETURNING 被呈现时会发出警告)
- Microsoft SQL Server
- SQLite 版本 3.31 及以上
当 计算列
与不受支持的后端一起使用时,如果目标方言不支持它,则在尝试呈现构造时会引发 CompileError
。否则,如果方言支持它但使用的特定数据库服务器版本不支持它,则在将 DDL 发送到数据库时会引发 DBAPIError
的子类,通常是 OperationalError
。
请参见
计算列
自增列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)
1.4 版本中新增。
Identity
构造允许将 列
声明为自增列,并在 DDL 中呈现为“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”。自增列的值由数据库服务器自动生成,使用增量(或减量)序列。该构造与 Sequence
共享大部分用于控制数据库行为的选项。
示例:
代码语言:javascript复制from sqlalchemy import Table, Column, MetaData, Integer, Identity, String
metadata_obj = MetaData()
data = Table(
"data",
metadata_obj,
Column("id", Integer, Identity(start=42, cycle=True), primary_key=True),
Column("data", String),
)
在 PostgreSQL 12 后端上运行时,data
表的 DDL 如下所示:
CREATE TABLE data (
id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
data VARCHAR,
PRIMARY KEY (id)
)
数据库将在插入时为 id
列生成一个值,从 42
开始,如果语句尚未包含 id
列的值。身份列也可以要求数据库生成列的值,忽略语句中传递的值或者根据后端引发错误。要激活此模式,请在 Identity
构造函数中将参数 Identity.always
设置为 True
。将上一个示例更新以包含此参数将生成以下 DDL:
CREATE TABLE data (
id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
data VARCHAR,
PRIMARY KEY (id)
)
Identity
构造函数是 FetchedValue
对象的子类,并将自己设置为目标 Column
的“服务器默认”生成器,这意味着当生成 INSERT 语句时,它将被视为默认生成列,以及在使用 ORM 时,它将被视为生成列。这包括它将作为数据库的 RETURNING 子句的一部分,对于支持 RETURNING 并且要急切获取生成的值的数据库来说,它将被提前获取。
当前已知支持 Identity
构造函数的包括:
- PostgreSQL 版本为 10。
- Oracle 版本为 12. 还支持传递
always=None
以启用默认生成模式,以及传递参数on_null=True
以指定“ON NULL”与“BY DEFAULT”身份列一起使用。 - Microsoft SQL Server. MSSQL 使用一种自定义语法,仅支持
start
和increment
参数,而忽略所有其他参数。
当 Identity
与不受支持的后端一起使用时,它会被忽略,并且会使用默认的 SQLAlchemy 自增列逻辑。
当 Column
同时指定 Identity
并将 Column.autoincrement
设置为 False
时,将引发错误。
另请参阅
Identity
默认对象 API
对象名称 | 描述 |
---|---|
ColumnDefault | 列的普通默认值。 |
Computed | 定义了一个生成的列,即“GENERATED ALWAYS AS”语法。 |
DefaultClause | 由 DDL 指定的 DEFAULT 列值。 |
DefaultGenerator | 用于列默认值的基类。 |
FetchedValue | 透明数据库端默认值的标记。 |
Identity | 定义标识列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。 |
Sequence | 表示命名的数据库序列。 |
class sqlalchemy.schema.Computed
定义一个生成列,即“GENERATED ALWAYS AS”语法。
Computed
构造是添加到Column
对象的参数列表中的内联构造:
from sqlalchemy import Computed
Table('square', metadata_obj,
Column('side', Float, nullable=False),
Column('area', Float, Computed('side * side'))
)
请参阅下面链接的文档以获取完整详细信息。
版本 1.3.11 中的新功能。
另请参阅
计算列(GENERATED ALWAYS AS)
成员
init(), copy()
类签名
类sqlalchemy.schema.Computed
(sqlalchemy.schema.FetchedValue
,sqlalchemy.schema.SchemaItem
)
method __init__(sqltext: _DDLColumnArgument, persisted: bool | None = None) → None
构造一个生成的 DDL 构造,以配合Column
。
参数:
-
sqltext
– 包含列生成表达式的字符串,该表达式将逐字使用,或者 SQL 表达式构造,例如text()
对象。 如果以字符串形式给出,则将对象转换为text()
对象。 警告Computed.sqltext
参数可以作为 Python 字符串参数传递给Computed
,它将被视为受信任的 SQL 文本并按照给定的方式呈现。 不要将不受信任的输入传递给此参数。 -
persisted
– 可选,控制数据库如何持久化此列。 可能的值为:-
None
,默认值,将使用数据库定义的默认持久性。 -
True
,将呈现GENERATED ALWAYS AS ... STORED
,或者如果支持的话,将呈现目标数据库的等效值。 -
False
,将呈现GENERATED ALWAYS AS ... VIRTUAL
,或者如果支持的话,将呈现目标数据库的等效值。
当 DDL 发出到目标数据库时,如果数据库不支持持久性选项,则指定
True
或False
可能会引发错误。 将此参数保留在其默认值None
上可确保对所有支持GENERATED ALWAYS AS
的数据库都能成功。 -
method copy(*, target_table: Table | None = None, **kw: Any) → Computed
自版本 1.4 起已弃用:Computed.copy()
方法已弃用,并将在将来的版本中删除。
class sqlalchemy.schema.ColumnDefault
列上的普通默认值。
这可能对应于一个常量,一个可调用函数,或者一个 SQL 子句。
每当使用 Column
的 default
、onupdate
参数时,都会自动生成 ColumnDefault
。ColumnDefault
也可以按位置传递。
例如,以下内容:
代码语言:javascript复制Column('foo', Integer, default=50)
等同于:
代码语言:javascript复制Column('foo', Integer, ColumnDefault(50))
类签名
class sqlalchemy.schema.ColumnDefault
(sqlalchemy.schema.DefaultGenerator
, abc.ABC
)
class sqlalchemy.schema.DefaultClause
由 DDL 指定的 DEFAULT 列值。
DefaultClause
是一个 FetchedValue
,在发出“CREATE TABLE”时也会生成一个“DEFAULT”子句。
每当使用 Column
的 server_default
、server_onupdate
参数时,都会自动生成 DefaultClause
。DefaultClause
也可以按位置传递。
例如,以下内容:
代码语言:javascript复制Column('foo', Integer, server_default="50")
等同于:
代码语言:javascript复制Column('foo', Integer, DefaultClause("50"))
类签名
class sqlalchemy.schema.DefaultClause
(sqlalchemy.schema.FetchedValue
)
class sqlalchemy.schema.DefaultGenerator
列默认值的基类。
此对象仅存在于 column.default 或 column.onupdate。它不作为服务器默认值有效。
类签名
class sqlalchemy.schema.DefaultGenerator
(sqlalchemy.sql.expression.Executable
, sqlalchemy.schema.SchemaItem
)
class sqlalchemy.schema.FetchedValue
一个用于透明数据库端默认值的标记。
当数据库配置为为列提供一些自动默认值时,请使用 FetchedValue
。
例如:
代码语言:javascript复制Column('foo', Integer, FetchedValue())
将指示某个触发器或默认生成器在插入期间为 foo
列创建一个新值。
另请参阅
标记隐式生成的值、时间戳和触发列
类签名
class sqlalchemy.schema.FetchedValue
(sqlalchemy.sql.expression.SchemaEventTarget
)
class sqlalchemy.schema.Sequence
表示一个命名的数据库序列。
Sequence
对象表示数据库序列的名称和配置参数。它还表示可以由 SQLAlchemy Engine
或 Connection
“执行”的构造,为目标数据库渲染适当的 “下一个值” 函数并返回结果。
Sequence
通常与主键列相关联:
some_table = Table(
'some_table', metadata,
Column('id', Integer, Sequence('some_table_seq', start=1),
primary_key=True)
)
当为上述 Table
发出 CREATE TABLE 时,如果目标平台支持序列,则还将发出 CREATE SEQUENCE 语句。对于不支持序列的平台,将忽略 Sequence
构造。
另请参阅
定义序列
CreateSequence
DropSequence
成员
init(), create(), drop(), next_value()
类签名
类 sqlalchemy.schema.Sequence
(sqlalchemy.schema.HasSchemaAttr
, sqlalchemy.schema.IdentityOptions
, sqlalchemy.schema.DefaultGenerator
)
method __init__(name: str, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, schema: str | Literal[SchemaConst.BLANK_SCHEMA] | None = None, cache: int | None = None, order: bool | None = None, data_type: _TypeEngineArgument[int] | None = None, optional: bool = False, quote: bool | None = None, metadata: MetaData | None = None, quote_schema: bool | None = None, for_update: bool = False) → None
构造一个 Sequence
对象。
参数:
-
name
– 序列的名称。 -
start
– 序列的起始索引。当向数据库发出 CREATE SEQUENCE 命令时,此值用作 “START WITH” 子句的值。如果为None
,则省略子句,大多数平台上表示起始值为 1。 从版本 2.0 开始:要使 DDL 发出 “START WITH” 命令,Sequence.start
参数是必需的。这是对版本 1.4 中所做更改的逆转,该更改如果未包括Sequence.start
将隐式地渲染 “START WITH 1”。有关更多详细信息,请参见序列构造将恢复为没有任何显式默认的“start”值;影响 MS SQL Server。 -
increment
– 序列的增量值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作 “INCREMENT BY” 子句的值。如果为None
,则省略子句,大多数平台上表示增量为 1。 -
minvalue
– 序列的最小值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“MINVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和-2⁶³-1。 -
maxvalue
– 序列的最大值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“MAXVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和-1。 -
nominvalue
– 序列的无最小值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“NO MINVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和-2⁶³-1。 -
nomaxvalue
– 序列的无最大值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“NO MAXVALUE”子句的值。如果为None
,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和-1。 -
cycle
– 允许序列在达到最大值或最小值时循环。当升序或降序序列分别达到最大值或最小值时,此值用于在将 CREATE SEQUENCE 命令发送到数据库时作为“CYCLE”子句。如果达到限制,则生成的下一个数字将分别是最小值或最大值。如果 cycle=False(默认值),则在序列达到其最大值后调用 nextval 将返回错误。 -
schema
– 序列的可选模式名称,如果位于除默认模式之外的模式中。当MetaData
也存在时,选择模式名称的规则与Table.schema
的规则相同。 -
cache
– 可选的整数值;提前计算序列中未来值的数量。渲染 Oracle 和 PostgreSQL 理解的 CACHE 关键字。 -
order
– 可选的布尔值;如果为True
,则渲染 ORDER 关键字,Oracle 可理解此关键字,表示序列是有确定顺序的。可能需要使用 Oracle RAC 提供确定性排序。 -
data_type
– 序列要返回的类型,对于允许我们在 INTEGER、BIGINT 等之间选择的方言(例如 mssql)。 自 1.4.0 版本新增。 -
optional
– 布尔值,当为True
时,表示这个Sequence
对象只需在不提供其他方法生成主键标识符的后端上显式生成。目前,它基本上意味着“在 PostgreSQL 后端上不要创建这个序列,在那里,SERIAL 关键字会自动为我们创建一个序列”。 -
quote
– 布尔值,当为True
或False
时,显式地强制对Sequence.name
进行引用或取消引用。当保持其默认值None
时,将根据大小写和保留字规则进行正常的引用。 -
quote_schema
– 设置对schema
名称的引用偏好。 -
metadata
– 可选的MetaData
对象,这个Sequence
将与之关联。与MetaData
关联的Sequence
将获得以下功能:-
Sequence
将继承指定给目标MetaData
的MetaData.schema
参数,这会影响创建/删除 DDL 的生成,如果有的话。 -
Sequence.create()
和Sequence.drop()
方法会自动使用绑定到MetaData
对象的引擎(如果有的话)。 -
MetaData.create_all()
和MetaData.drop_all()
方法将为这个Sequence
发出 CREATE / DROP,即使这个Sequence
没有与任何属于这个MetaData
的Table
/Column
相关联也是如此。
上述行为只有在通过此参数将
Sequence
显式关联到MetaData
时才会发生。 另请参见 将 Sequence 与 MetaData 关联 - 对Sequence.metadata
参数的完整讨论。 -
-
for_update
– 当与Column
相关联时,表示应该在该列的表上对 UPDATE 语句调用此Sequence
,而不是在 INSERT 语句中,当该列在语句中没有其他值时。
method create(bind: _CreateDropBind, checkfirst: bool = True) → None
在数据库中创建此序列。
代码语言:javascript复制method drop(bind: _CreateDropBind, checkfirst: bool = True) → None
从数据库中删除此序列。
代码语言:javascript复制method next_value() → Function[int]
返回一个next_value
函数元素,该函数将在任何 SQL 表达式中为此Sequence
呈现适当的增量函数。
class sqlalchemy.schema.Identity
定义一个 identity 列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。
Identity
构造是一个内联构造,添加到Column
对象的参数列表中:
from sqlalchemy import Identity
Table('foo', metadata_obj,
Column('id', Integer, Identity())
Column('description', Text),
)
详细信息请参见下面的链接文档。
版本 1.4 中新增。
另请参阅
Identity 列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)
成员
init(), copy()
类签名
class sqlalchemy.schema.Identity
(sqlalchemy.schema.IdentityOptions
, sqlalchemy.schema.FetchedValue
, sqlalchemy.schema.SchemaItem
)
method __init__(always: bool = False, on_null: bool | None = None, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, cache: int | None = None, order: bool | None = None) → None
构造一个 GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY 的 DDL 构造,以配合一个Column
。
有关大多数参数的完整描述,请参阅Sequence
文档。
注意
MSSQL 支持此构造作为在列上生成 IDENTITY 的首选替代方法,但它使用的非标准语法仅支持Identity.start
和Identity.increment
。所有其他参数都将被忽略。
参数:
-
always
– 一个布尔值,表示身份列的类型。如果指定为False
,则用户指定的值优先。如果指定为True
,则不接受用户指定的值(在某些后端,如 PostgreSQL,可以在 INSERT 中指定 OVERRIDING SYSTEM VALUE 或类似的内容来覆盖序列值)。一些后端也对此参数有一个默认值,None
可以用来省略在 DDL 中呈现这部分。如果后端没有默认值,则将其视为False
。 -
on_null
– 设置为True
以指定在always=False
身份列中与ON NULL
一起使用。此选项仅在某些后端(如 Oracle)上受支持。 -
start
– 序列的起始索引。 -
increment
– 序列的增量值。 -
minvalue
– 序列的最小值。 -
maxvalue
– 序列的最大值。 -
nominvalue
– 序列没有最小值。 -
nomaxvalue
– 序列没有最大值。 -
cycle
– 允许序列在达到maxvalue
或minvalue
时循环。 -
cache
– 可选整数值;提前计算的序列中未来值的数量。 -
order
– 可选布尔值;如果为真,则呈现 ORDER 关键字。
method copy(**kw: Any) → Identity
自版本 1.4 弃用:Identity.copy()
方法已弃用,并将在将来的版本中移除。
定义约束和索引
原文:
docs.sqlalchemy.org/en/20/core/constraints.html
这一部分将讨论 SQL 的约束和索引。在 SQLAlchemy 中,关键类包括ForeignKeyConstraint
和Index
。
定义外键
SQL 中的外键是一个表级构造,它将该表中的一个或多个列约束为仅允许存在于另一组列中的值,通常但不总是位于不同的表上。我们称被约束的列为外键列,它们被约束到的列为引用列。引用列几乎总是定义其拥有表的主键,尽管也有例外情况。外键是连接具有关系的行对的“关节”,SQLAlchemy 在其几乎每个操作的每个区域都赋予了这个概念非常深的重要性。
在 SQLAlchemy 中以及在 DDL 中,外键约束可以被定义为表子句中的附加属性,或者对于单列外键,它们可以选择地在单列的定义中指定。单列外键更常见,在列级别上是通过将ForeignKey
对象构造为Column
对象的参数来指定的:
user_preference = Table(
"user_preference",
metadata_obj,
Column("pref_id", Integer, primary_key=True),
Column("user_id", Integer, ForeignKey("user.user_id"), nullable=False),
Column("pref_name", String(40), nullable=False),
Column("pref_value", String(100)),
)
上面,我们定义了一个新表user_preference
,其中每一行必须包含一个存在于user
表的user_id
列中的值。
参数ForeignKey
最常见的形式是一个字符串,格式为*.,或者对于远程模式或者“owner”的表格是..*。它也可以是一个实际的Column
对象,稍后我们将看到它是通过其c
集合从现有的Table
对象中访问的:
ForeignKey(user.c.user_id)
使用字符串的优点是,在首次需要时才解析user
和user_preference
之间的 Python 链接,因此表对象可以轻松地分布在多个模块中并按任何顺序定义。
外键也可以在表级别使用 ForeignKeyConstraint
对象定义。此对象可以描述单列或多列外键。多列外键称为复合外键,几乎总是引用具有复合主键的表。下面我们定义一个具有复合主键的表 invoice
:
invoice = Table(
"invoice",
metadata_obj,
Column("invoice_id", Integer, primary_key=True),
Column("ref_num", Integer, primary_key=True),
Column("description", String(60), nullable=False),
)
然后是一个引用 invoice
的复合外键的表 invoice_item
:
invoice_item = Table(
"invoice_item",
metadata_obj,
Column("item_id", Integer, primary_key=True),
Column("item_name", String(60), nullable=False),
Column("invoice_id", Integer, nullable=False),
Column("ref_num", Integer, nullable=False),
ForeignKeyConstraint(
["invoice_id", "ref_num"], ["invoice.invoice_id", "invoice.ref_num"]
),
)
注意,ForeignKeyConstraint
是定义复合外键的唯一方式。虽然我们也可以将单独的 ForeignKey
对象放置在 invoice_item.invoice_id
和 invoice_item.ref_num
列上,但 SQLAlchemy 不会意识到这两个值应该配对在一起 - 它将是两个单独的外键约束,而不是一个引用两个列的单个复合外键。
通过 ALTER 创建/删除外键约束
我们在教程和其他地方看到的涉及 DDL 的外键行为表明,约束通常以“内联”的方式在 CREATE TABLE 语句中呈现,例如:
代码语言:javascript复制CREATE TABLE addresses (
id INTEGER NOT NULL,
user_id INTEGER,
email_address VARCHAR NOT NULL,
PRIMARY KEY (id),
CONSTRAINT user_id_fk FOREIGN KEY(user_id) REFERENCES users (id)
)
CONSTRAINT .. FOREIGN KEY
指令用于在 CREATE TABLE 定义中以“内联”的方式创建约束。 MetaData.create_all()
和 MetaData.drop_all()
方法默认使用所有涉及的 Table
对象的拓扑排序,以便按照它们的外键依赖顺序创建和删除表(此排序也可通过 MetaData.sorted_tables
访问器获取)。
当涉及两个或更多外键约束参与“依赖循环”时,这种方法无法工作,其中一组表彼此相互依赖,假设后端执行外键(除了 SQLite、MySQL/MyISAM 之外总是是这样的情况)。因此,这些方法将在除 SQLite 之外的所有后端上将循环中的约束拆分为单独的 ALTER 语句,SQLite 不支持大多数形式的 ALTER。给定这样的模式:
代码语言:javascript复制node = Table(
"node",
metadata_obj,
Column("node_id", Integer, primary_key=True),
Column("primary_element", Integer, ForeignKey("element.element_id")),
)
element = Table(
"element",
metadata_obj,
Column("element_id", Integer, primary_key=True),
Column("parent_node_id", Integer),
ForeignKeyConstraint(
["parent_node_id"], ["node.node_id"], name="fk_element_parent_node_id"
),
)
当我们在像 PostgreSQL 这样的后端上调用 MetaData.create_all()
时,这两个表之间的循环被解析,并且约束被分别创建:
>>> with engine.connect() as conn:
... metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
element_id SERIAL NOT NULL,
parent_node_id INTEGER,
PRIMARY KEY (element_id)
)
CREATE TABLE node (
node_id SERIAL NOT NULL,
primary_element INTEGER,
PRIMARY KEY (node_id)
)
ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
FOREIGN KEY(parent_node_id) REFERENCES node (node_id)
ALTER TABLE node ADD FOREIGN KEY(primary_element)
REFERENCES element (element_id)
为了发出这些表的 DROP,相同的逻辑也适用,但是请注意,在 SQL 中,发出 DROP CONSTRAINT 需要约束具有名称。在上面的 'node'
表的情况下,我们还没有为此约束命名;因此系统将仅尝试发出对具有名称的约束的 DROP:
>>> with engine.connect() as conn:
... metadata_obj.drop_all(conn, checkfirst=False)
ALTER TABLE element DROP CONSTRAINT fk_element_parent_node_id
DROP TABLE node
DROP TABLE element
在无法解决循环的情况下,例如如果我们在这里没有对约束应用名称,则将收到以下错误:
代码语言:javascript复制sqlalchemy.exc.CircularDependencyError: Can't sort tables for DROP;
an unresolvable foreign key dependency exists between tables:
element, node. Please ensure that the ForeignKey and ForeignKeyConstraint
objects involved in the cycle have names so that they can be dropped
using DROP CONSTRAINT.
此错误仅适用于 DROP 情况,因为我们可以在 CREATE 情况下发出 “ADD CONSTRAINT” 而无需名称;数据库通常会自动分配一个名称。
ForeignKeyConstraint.use_alter
和 ForeignKey.use_alter
关键字参数可用于手动解决依赖循环。我们可以仅将此标志添加到 'element'
表中,如下所示:
element = Table(
"element",
metadata_obj,
Column("element_id", Integer, primary_key=True),
Column("parent_node_id", Integer),
ForeignKeyConstraint(
["parent_node_id"],
["node.node_id"],
use_alter=True,
name="fk_element_parent_node_id",
),
)
在我们的 CREATE DDL 中,我们将只看到此约束的 ALTER 语句,而不是另一个约束的 ALTER 语句:
代码语言:javascript复制>>> with engine.connect() as conn:
... metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
element_id SERIAL NOT NULL,
parent_node_id INTEGER,
PRIMARY KEY (element_id)
)
CREATE TABLE node (
node_id SERIAL NOT NULL,
primary_element INTEGER,
PRIMARY KEY (node_id),
FOREIGN KEY(primary_element) REFERENCES element (element_id)
)
ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
FOREIGN KEY(parent_node_id) REFERENCES node (node_id)
当与删除操作结合使用时,ForeignKeyConstraint.use_alter
和 ForeignKey.use_alter
将要求约束具有名称,否则将生成类似以下的错误:
sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint
ForeignKeyConstraint(...); it has no name
另请参阅
配置约束命名约定
sort_tables_and_constraints()
### ON UPDATE 和 ON DELETE
大多数数据库都支持外键值的级联,即当父行更新时,新值会放在子行中,或者当父行删除时,所有相应的子行都会被设置为 null 或删除。在数据定义语言中,这些是使用诸如 “ON UPDATE CASCADE”,“ON DELETE CASCADE” 和 “ON DELETE SET NULL” 之类的短语来指定的,对应于外键约束。在 “ON UPDATE” 或 “ON DELETE” 之后的短语可能还允许使用特定于正在使用的数据库的其他短语。ForeignKey
和 ForeignKeyConstraint
对象通过 onupdate
和 ondelete
关键字参数支持生成此子句。该值是任何字符串,该字符串将在适当的 “ON UPDATE” 或 “ON DELETE” 短语之后输出:
child = Table(
"child",
metadata_obj,
Column(
"id",
Integer,
ForeignKey("parent.id", onupdate="CASCADE", ondelete="CASCADE"),
primary_key=True,
),
)
composite = Table(
"composite",
metadata_obj,
Column("id", Integer, primary_key=True),
Column("rev_id", Integer),
Column("note_id", Integer),
ForeignKeyConstraint(
["rev_id", "note_id"],
["revisions.id", "revisions.note_id"],
onupdate="CASCADE",
ondelete="SET NULL",
),
)
请注意,这些子句在与 MySQL 配合使用时需要 InnoDB
表。它们在其他数据库上也可能不受支持。
另请参阅
有关将 ON DELETE CASCADE
与 ORM relationship()
结构集成的背景,请参阅以下部分:
使用外键 ON DELETE cascade 处理 ORM 关系
使用外键 ON DELETE 处理多对多关系 ## 唯一约束
可以使用 Column
上的 unique
关键字在单个列上匿名创建唯一约束。显式命名的唯一约束和/或具有多个列的约束通过 UniqueConstraint
表级构造创建。
from sqlalchemy import UniqueConstraint
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
# per-column anonymous unique constraint
Column("col1", Integer, unique=True),
Column("col2", Integer),
Column("col3", Integer),
# explicit/composite unique constraint. 'name' is optional.
UniqueConstraint("col2", "col3", name="uix_1"),
)
检查约束
检查约束可以具有命名或未命名,可以在列或表级别使用 CheckConstraint
构造。检查约束的文本直接传递到数据库,因此具有有限的“数据库独立”行为。列级检查约束通常只应引用它们放置的列,而表级约束可以引用表中的任何列。
请注意,一些数据库不支持主动支持检查约束,例如旧版本的 MySQL(在 8.0.16 之前)。
代码语言:javascript复制from sqlalchemy import CheckConstraint
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
# per-column CHECK constraint
Column("col1", Integer, CheckConstraint("col1>5")),
Column("col2", Integer),
Column("col3", Integer),
# table level CHECK constraint. 'name' is optional.
CheckConstraint("col2 > col3 5", name="check1"),
)
mytable.create(engine)
CREATE TABLE mytable (
col1 INTEGER CHECK (col1>5),
col2 INTEGER,
col3 INTEGER,
CONSTRAINT check1 CHECK (col2 > col3 5)
)
主键约束
任何 Table
对象的主键约束在本质上是隐式存在的,基于标记有 Column.primary_key
标志的 Column
对象。PrimaryKeyConstraint
对象提供了对此约束的显式访问,其中包括直接配置的选项:
from sqlalchemy import PrimaryKeyConstraint
my_table = Table(
"mytable",
metadata_obj,
Column("id", Integer),
Column("version_id", Integer),
Column("data", String(50)),
PrimaryKeyConstraint("id", "version_id", name="mytable_pk"),
)
另请参阅
PrimaryKeyConstraint
- 详细的 API 文档。
使用 Declarative ORM 扩展设置约束
Table
是 SQLAlchemy 核心构造,允许定义表元数据,其中可以用于 SQLAlchemy ORM 作为映射类的目标。Declarative 扩展允许自动创建 Table
对象,主要根据表的内容作为 Column
对象的映射。
要将表级约束对象(例如 ForeignKeyConstraint
)应用于使用 Declarative 定义的表,请使用 __table_args__
属性,详见 表配置。
配置约束命名约定
关系数据库通常会为所有约束和索引分配明确的名称。在常见情况下,使用CREATE TABLE
创建表时,约束(如 CHECK、UNIQUE 和 PRIMARY KEY 约束)会与表定义一起内联生成,如果未另行指定名称,则数据库通常会自动为这些约束分配名称。当在使用诸如ALTER TABLE
之类的命令更改数据库中的现有数据库表时,此命令通常需要为新约束指定显式名称,以及能够指定要删除或修改的现有约束的名称。
使用Constraint.name
参数可以明确命名约束,对于索引,可以使用Index.name
参数。然而,在约束的情况下,此参数是可选的。还有使用Column.unique
和Column.index
参数的用例,这些参数创建UniqueConstraint
和Index
对象时未明确指定名称。
对现有表和约束进行更改的用例可以由模式迁移工具(如Alembic)处理。然而,Alembic 和 SQLAlchemy 目前都不会为未指定名称的约束对象创建名称,导致可以更改现有约束的情况下,必须反向工程关系数据库用于自动分配名称的命名系统,或者必须注意确保所有约束都已命名。
与必须为所有Constraint
和Index
对象分配显式名称相比,可以使用事件构建自动命名方案。这种方法的优势在于,约束将获得一致的命名方案,无需在整个代码中使用显式名称参数,并且约定也适用于由Column.unique
和Column.index
参数生成的那些约束和索引。从 SQLAlchemy 0.9.2 开始,包含了这种基于事件的方法,并且可以使用参数MetaData.naming_convention
进行配置。
配置元数据集合的命名约定
MetaData.naming_convention
指的是一个接受Index
类或单独的Constraint
类作为键,Python 字符串模板作为值的字典。它还接受一系列字符串代码作为备用键,分别为外键、主键、索引、检查和唯一约束的"fk"
、"pk"
、"ix"
、"ck"
、"uq"
。在这个字典中的字符串模板在与这个MetaData
对象关联的约束或索引没有给出现有名称的情况下���用。(包括一个例外情况,其中现有名称可以进一步装饰)。
适用于基本情况的一个命名约定示例如下:
代码语言:javascript复制convention = {
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
metadata_obj = MetaData(naming_convention=convention)
上述约定将为目标MetaData
集合中的所有约束建立名称。例如,当我们创建一个未命名的UniqueConstraint
时,我们可以观察到生成的名称:
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("name", String(30), nullable=False),
... UniqueConstraint("name"),
... )
>>> list(user_table.constraints)[1].name
'uq_user_name'
即使我们只使用Column.unique
标志,这个相同的特性也会生效:
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("name", String(30), nullable=False, unique=True),
... )
>>> list(user_table.constraints)[1].name
'uq_user_name'
命名约定方法的一个关键优势是,名称是在 Python 构建时建立的,而不是在 DDL 发出时建立的。当使用 Alembic 的--autogenerate
功能时,这个特性的效果是,当生成新的迁移脚本时,命名约定将是明确的:
def upgrade():
op.create_unique_constraint("uq_user_name", "user", ["name"])
上述的"uq_user_name"
字符串是从--autogenerate
在我们的元数据中定位的UniqueConstraint
对象复制而来。
可用的令牌包括 %(table_name)s
、%(referred_table_name)s
、%(column_0_name)s
、%(column_0_label)s
、%(column_0_key)s
、%(referred_column_0_name)s
,以及每个令牌的多列版本,包括 %(column_0N_name)s
、%(column_0_N_name)s
、%(referred_column_0_N_name)s
,它们以带有或不带有下划线的形式呈现所有列名称。关于 MetaData.naming_convention
的文档进一步详细说明了这些约定。
默认命名约定
MetaData.naming_convention
的默认值处理了长期以来 SQLAlchemy 的行为,即使用 Column.index
参数创建 Index
对象时分配名称的情况:
>>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
>>> DEFAULT_NAMING_CONVENTION
immutabledict({'ix': 'ix_%(column_0_label)s'})
长名称的截断
当生成的名称,特别是使用多列令牌的名称,超出目标数据库的标识符长度限制(例如,PostgreSQL 具有 63 个字符的限制)时,名称将使用基于长名称的 md5 哈希的 4 个字符后缀进行确定性截断。例如,以下命名约定将根据使用的列名生成非常长的名称:
代码语言:javascript复制metadata_obj = MetaData(
naming_convention={"uq": "uq_%(table_name)s_%(column_0_N_name)s"}
)
long_names = Table(
"long_names",
metadata_obj,
Column("information_channel_code", Integer, key="a"),
Column("billing_convention_name", Integer, key="b"),
Column("product_identifier", Integer, key="c"),
UniqueConstraint("a", "b", "c"),
)
在 PostgreSQL 方言中,长度超过 63 个字符的名称将被截断,如以下示例所示:
代码语言:javascript复制CREATE TABLE long_names (
information_channel_code INTEGER,
billing_convention_name INTEGER,
product_identifier INTEGER,
CONSTRAINT uq_long_names_information_channel_code_billing_conventi_a79e
UNIQUE (information_channel_code, billing_convention_name, product_identifier)
)
上述后缀 a79e
基于长名称的 md5 哈希,并且每次生成相同的值,以便为给定模式生成一致的名称。
创建用于命名约定的自定义令牌
还可以通过在 naming_convention 字典中指定额外的令牌和可调用对象来添加新的令牌。例如,如果我们想要使用 GUID 方案对外键约束进行命名,我们可以这样做:
代码语言:javascript复制import uuid
def fk_guid(constraint, table):
str_tokens = (
[
table.name,
]
[element.parent.name for element in constraint.elements]
[element.target_fullname for element in constraint.elements]
)
guid = uuid.uuid5(uuid.NAMESPACE_OID, "_".join(str_tokens).encode("ascii"))
return str(guid)
convention = {
"fk_guid": fk_guid,
"ix": "ix_%(column_0_label)s",
"fk": "fk_%(fk_guid)s",
}
在创建新的 ForeignKeyConstraint
时,我们将获得以下名称:
>>> metadata_obj = MetaData(naming_convention=convention)
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("version", Integer, primary_key=True),
... Column("data", String(30)),
... )
>>> address_table = Table(
... "address",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("user_id", Integer),
... Column("user_version_id", Integer),
... )
>>> fk = ForeignKeyConstraint(["user_id", "user_version_id"], ["user.id", "user.version"])
>>> address_table.append_constraint(fk)
>>> fk.name
fk_0cd51ab5-8d70-56e8-a83c-86661737766d
另请参阅
MetaData.naming_convention
- 附加使用详细信息以及所有可用命名组件的列表。
命名约束的重要性 - 在 Alembic 文档中。
版本 1.3.0 中的新功能:添加了诸如 %(column_0_N_name)s
等多列命名令牌。超出目标数据库字符限制的生成名称将被确定性地截断。
命名 CHECK 约束
CheckConstraint
对象配置针对任意 SQL 表达式,该表达式可以有任意数量的列,并且通常使用原始 SQL 字符串进行配置。因此,通常与 CheckConstraint
一起使用的约定是,我们希望对象已经有一个名称,然后我们使用其他约定元素增强它。一个典型的约定是 "ck_%(table_name)s_%(constraint_name)s"
:
metadata_obj = MetaData(
naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)
Table(
"foo",
metadata_obj,
Column("value", Integer),
CheckConstraint("value > 5", name="value_gt_5"),
)
上述表格将产生名称 ck_foo_value_gt_5
:
CREATE TABLE foo (
value INTEGER,
CONSTRAINT ck_foo_value_gt_5 CHECK (value > 5)
)
CheckConstraint
还支持 %(columns_0_name)s
token;我们可以通过确保在约束表达式中使用 Column
或 column()
元素来利用它,无论是通过单独声明约束表达式还是内联到表中:
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
foo = Table("foo", metadata_obj, Column("value", Integer))
CheckConstraint(foo.c.value > 5)
或通过内联使用 column()
:
from sqlalchemy import column
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
foo = Table(
"foo", metadata_obj, Column("value", Integer), CheckConstraint(column("value") > 5)
)
两者都将产生名称 ck_foo_value
:
CREATE TABLE foo (
value INTEGER,
CONSTRAINT ck_foo_value CHECK (value > 5)
)
“column zero”的名称确定是通过扫描给定表达式中的列对象来执行的。如果表达式中有多个列,扫描将使用确定性搜索,但是表达式的结构将决定哪个列被标记为“column zero”。### 针对布尔、枚举和其他模式类型进行命名配置
SchemaType
类指的是诸如 Boolean
和 Enum
等类型对象,它们生成与类型相伴随的 CHECK 约束。这里约束的名称最直接是通过发送“name”参数来设置的,例如 Boolean.name
:
Table("foo", metadata_obj, Column("flag", Boolean(name="ck_foo_flag")))
命名约定功能也可以与这些类型结合使用,通常是通过使用包含 %(constraint_name)s
的约定,然后将名称应用于类型:
metadata_obj = MetaData(
naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)
Table("foo", metadata_obj, Column("flag", Boolean(name="flag_bool")))
上述表格将产生约束名称 ck_foo_flag_bool
:
CREATE TABLE foo (
flag BOOL,
CONSTRAINT ck_foo_flag_bool CHECK (flag IN (0, 1))
)
SchemaType
类使用特殊的内部符号,以便命名约定仅在 DDL 编译时确定。在 PostgreSQL 上,有一个原生的 BOOLEAN 类型,因此不需要Boolean
的 CHECK 约束;即使为检查约束设置了命名约定,我们也可以安全地设置不带名称的Boolean
类型。如果我们针对没有原生 BOOLEAN 类型的数据库运行,如 SQLite 或 MySQL,那么仅当我们运行时才会参考此约定 CHECK 约束。
CHECK 约束也可以使用column_0_name
标记,与SchemaType
很好地配合使用,因为这些约束只有一个列:
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
Table("foo", metadata_obj, Column("flag", Boolean()))
以上模式将产生:
代码语言:javascript复制CREATE TABLE foo (
flag BOOL,
CONSTRAINT ck_foo_flag CHECK (flag IN (0, 1))
)
使用 ORM 声明式混合与命名约定
使用命名约定功能与 ORM 声明性混合一起使用时,必须为每个实际表映射的子类存在单独的约束对象。有关背景和示例,请参见使用命名约定在混合上创建索引和约束部分。
约束 API
对象名称 | 描述 |
---|---|
CheckConstraint | 表级或列级 CHECK 约束。 |
ColumnCollectionConstraint | 代理 ColumnCollection 的约束。 |
ColumnCollectionMixin | Column对象的ColumnCollection。 |
Constraint | 表级 SQL 约束。 |
conv | 标记一个字符串,指示名称已经由命名约定转换。 |
ForeignKey | 定义两列之间的依赖关系。 |
ForeignKeyConstraint | 表级 FOREIGN KEY 约束。 |
HasConditionalDDL | 定义一个包括HasConditionalDDL.ddl_if()方法的类,允许对 DDL 进行条件渲染。 |
PrimaryKeyConstraint | 表级主键约束。 |
UniqueConstraint | 表级 UNIQUE 约束。 |
class sqlalchemy.schema.Constraint
表级 SQL 约束。
Constraint
作为一系列约束对象的基类,可以与 Table
对象关联,包括 PrimaryKeyConstraint
、ForeignKeyConstraint
、UniqueConstraint
和 CheckConstraint
。
成员
init(), argument_for(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
类 sqlalchemy.schema.Constraint
(sqlalchemy.sql.base.DialectKWArgs
, sqlalchemy.schema.HasConditionalDDL
, sqlalchemy.schema.SchemaItem
)
method __init__(name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, comment: str | None = None, _create_rule: Any | None = None, _type_bound: bool = False, **dialect_kw: Any) → None
创建一个 SQL 约束。
参数:
-
name
– 可选,此Constraint
的数据库名称。 -
deferrable
– 可选布尔值。如果设置,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。 -
info
– 可选数据字典,将填充到此对象的SchemaItem.info
属性中。 -
comment
– 可选字符串,���在创建外键约束时呈现 SQL 注释。 2.0 版本中的新功能。 -
**dialect_kw
– 附加关键字参数是特定于方言的,并以<dialectname>_<argname>
的形式传递。有关单个方言的文档参数详细信息,请参阅 方言。 -
_create_rule
– 一些数据类型内部使用,也创建约束。 -
_type_bound
– 内部使用,表示此约束与特定数据类型相关联。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为此类添加一种新的特定于方言的关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种为DefaultDialect.construct_arguments
字典添加额外参数的每个参数的方式。该字典提供了由各种模式级构造所接受的参数名称列表,代表一个方言。
新方言通常应该一次性指定此字典为方言类的数据成员。临时添加参数名称的用例通常是用于使用自定义编译方案并消耗额外参数的最终用户代码。
参数:
-
dialect_name
– 方言名称。 方言必须是可定位的,否则会引发NoSuchModuleError
。 方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表示它参与关键字参数验证和默认系统,否则会引发ArgumentError
。 如果方言不包含此集合,则可以已为该方言指定任何关键字参数。SQLAlchemy 中打包的所有方言都包含此集合,但对于第三方方言,支持可能会有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
method copy(**kw: Any) → Self
自 1.4 版本弃用:Constraint.copy()
方法已弃用,并将在将来的版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
的方法 HasConditionalDDL
对此模式项目应用条件 DDL 规则。
这些规则的工作方式与ExecutableDDLElement.execute_if()
类似,不同之处在于可以在 DDL 编译阶段检查条件,例如CreateTable
这样的结构。 HasConditionalDDL.ddl_if()
目前适用于Index
结构以及所有Constraint
结构。
参数:
-
dialect
– 方言的字符串名称,或字符串名称的元组,表示多个方言类型。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
中描述的相同形式构建的可调用对象。 -
state
– 将传递给可调用对象的任意任意对象(如果存在)。
2.0 版本中的新功能。
另请参阅
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为针对此结构的方言特定选项指定的关键字参数的集合。
这里的参数以原始的<dialect>_<kwarg>
格式呈现。仅包含实际传递的参数;与包含此方言的所有选项(包括默认值)的DialectKWArgs.dialect_options
集合不同。
该集合也是可写的;键采用<dialect>_<kwarg>
形式,其中的值将被组装成选项列表。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为针对此结构的方言特定选项指定的关键字参数的集合。
这是一个两级嵌套的注册表,键为 <dialect_name>
和 <argument_name>
。例如,postgresql_where
参数可定位为:
arg = my_object.dialect_options['postgresql']['where']
0.9.2 版本中的新功能。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象相关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联。
当首次访问时,字典会自动生成。它也可以在某些对象的构造函数中指定,例如Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
的 DialectKWArgs
属性
DialectKWArgs.dialect_kwargs
的同义词。
class sqlalchemy.schema.ColumnCollectionMixin
一个Column
对象的ColumnCollection
。
此集合表示此对象引用的列。
代码语言:javascript复制class sqlalchemy.schema.ColumnCollectionConstraint
代理列集合的约束。
成员
init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
class sqlalchemy.schema.ColumnCollectionConstraint
(sqlalchemy.schema.ColumnCollectionMixin
, sqlalchemy.schema.Constraint
)
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None
参数:
-
*columns
– 一系列列名或列对象。 -
name
– 可选项,此约束的数据库中的名称。 -
deferrable
– 可选布尔值。如果设置,发出 DDL 时会发出 DEFERRABLE 或 NOT DEFERRABLE 用于此约束。 -
initially
– 可选字符串。如果设置,发出 DDL 时会发出 INITIALLY 用于此约束。 -
**dialect_kw
– 其他关键字参数,包括方言特定参数,都会传播到Constraint
超类。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为此类添加一种新的特定于方言的关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是向 DefaultDialect.construct_arguments
字典添加额外参数的每个参数的方法。 此字典提供了代表方言的各种模式级构造所接受的参数名称列表。
新方言通常应一次性指定此字典为方言类的数据成员。 通常,为了使用自定义编译方案并使用附加参数的最终用户代码,使用情形是添加参数名称的即兴增加。
参数:
-
dialect_name
– 方言的名称。 方言必须可定位,否则会引发NoSuchModuleError
。 方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,指示其参与关键字参数验证和默认系统,否则将引发ArgumentError
。 如果方言不包括此集合,则可以代表此方言已经指定任何关键字参数。 SQLAlchemy 中打包的所有方言都包括此集合,但是对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin
属性 ColumnCollectionMixin.columns
的。
代表此约束的一组列的 ColumnCollection
。
method contains_column(col: Column[Any]) → bool
如果此约束包含给定的列,则返回 True。
请注意,此对象还包含一个属性 .columns
,它是 Column
对象的 ColumnCollection
。
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint
从版本 1.4 开始弃用:ColumnCollectionConstraint.copy()
方法已弃用,并将在将来的版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
对此模式项应用条件 DDL 规则。
这些规则的工作方式与ExecutableDDLElement.execute_if()
可调用对象类似,额外的特性是可以在 DDL 编译阶段检查条件,例如CreateTable
构造中的条件。HasConditionalDDL.ddl_if()
目前也适用于Index
构造以及所有Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或表示多个方言类型的字符串名称元组。 -
callable_
– 一个可调用对象,其构造方式与ExecutableDDLElement.execute_if.callable_
中描述的形式相同。 -
state
– 任意对象,如果存在将传递给可调用对象。
版本 2.0 中的新功能。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为特定于方言的选项指定为此构造的关键字参数集合。
这里的参数以原始的<dialect>_<kwarg>
格式呈现。仅包括实际传递的参数;与包含所有已知选项的默认值的DialectKWArgs.dialect_options
集合不同。
该集合也是可写的;键的形式为<dialect>_<kwarg>
,其中的值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项指定的关键字参数集合。
这是一个两级嵌套的注册表,键入 <dialect_name>
和 <argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
新版本 0.9.2 中新增。
另见
DialectKWArgs.dialect_kwargs
- 扁平字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联。
第一次访问时自动生成该字典。也可以在某些对象的构造函数中指定,例如 Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
class sqlalchemy.schema.CheckConstraint
表或列级别的检查约束。
可以包含在表或列的定义中。
成员
init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
类 sqlalchemy.schema.CheckConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)
method __init__(sqltext: _TextCoercedExpressionArgument[Any], name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, table: Table | None = None, info: _InfoType | None = None, _create_rule: Any | None = None, _autoattach: bool = True, _type_bound: bool = False, **dialect_kw: Any) → None
构建一个检查约束。
参数:
sqltext
–
包含约束定义的字符串,将会原样使用,或者是一个 SQL 表达式构造。如果给定为字符串,则将对象转换为 text()
对象。如果文本字符串包含冒号字符,则使用反斜杠进行转义:
CheckConstraint(r"foo ~ E'a(?:b|c)d")
警告
CheckConstraint.sqltext
参数可以作为 Python 字符串参数传递给 CheckConstraint
,该参数将被视为受信任的 SQL 文本并按原样呈现。不要将不受信任的输入传递给此参数。
name
– 可选的,约束在数据库中的名称。
deferrable
– 可选布尔值。如果设置了,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。
initially
– 可选字符串。如果设置了,则在为此约束发出 DDL 时发出 INITIALLY 。
info
– 可选的数据字典,将填充到该对象的 SchemaItem.info
属性中。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为此类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种逐个方式向 DefaultDialect.construct_arguments
字典添加额外参数的方法。该字典提供了方言代表各种模式级别构造接受的参数名称列表。
新的方言通常应该一次性指定该字典,作为方言类的数据成员。临时添加参数名称的用例通常是用于最终用户代码,该代码还使用了自定义编译方案,该方案会使用额外的参数。
参数:
-
dialect_name
– 方言的名称。如果无法找到该方言,则会引发NoSuchModuleError
。该方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表示它参与关键字参数的验证和默认系统,否则将引发ArgumentError
。如果该方言不包括此集合,则可以代表该方言指定任何关键字参数。所有 SQLAlchemy 打包的方言都包括此集合,但是对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin.columns
属性的 ColumnCollectionMixin
表示此约束的列集合。
代码语言:javascript复制method contains_column(col: Column[Any]) → bool
继承自 ColumnCollectionConstraint.contains_column()
方法的 ColumnCollectionConstraint
如果此约束包含给定的列,则返回 True。
注意,此对象还包含一个属性 .columns
,它是一个 ColumnCollection
,其中包含 Column
对象。
method copy(*, target_table: Table | None = None, **kw: Any) → CheckConstraint
自版本 1.4 起已弃用:CheckConstraint.copy()
方法已弃用,并将在将来的版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
对此模式项应用条件 DDL 规则。
这些规则的工作方式与ExecutableDDLElement.execute_if()
可调用对象类似,但增加了一个功能,即可以在 DDL 编译阶段检查条件,例如CreateTable
构造。 HasConditionalDDL.ddl_if()
目前也适用于Index
构造以及所有Constraint
构造。
参数:
-
dialect
- 方言的字符串名称,或字符串名称的元组以指示多个方言类型。 -
callable_
- 使用与ExecutableDDLElement.execute_if.callable_
描述的相同形式构造的可调用对象。 -
state
- 任意对象,如果存在,将传递给可调用对象。
版本 2.0 中的新功能。
另请参阅
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为方言特定选项传递给此构造函数的关键字参数集合。
这里的参数以其原始的<dialect>_<kwarg>
格式存在。只包括实际传递的参数;与包含此方言的所有选项的DialectKWArgs.dialect_options
集合不同,后者包含了所有已知选项,包括默认值。
该集合也可写入;键的形式为<dialect>_<kwarg>
,其中的值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项传递给此构造函数的关键字参数集合。
这是一个两级嵌套的注册表,键为<dialect_name>
和<argument_name>
。例如,postgresql_where
参数可定位为:
arg = my_object.dialect_options['postgresql']['where']
版本 0.9.2 中的新功能。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
。
与对象相关联的信息字典,允许将用户定义的数据与此SchemaItem
相关联。
当首次访问时,字典会自动生成。也可以在某些对象的构造函数中指定,例如Table
和Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
。
DialectKWArgs.dialect_kwargs
的同义词。
class sqlalchemy.schema.ForeignKey
定义了两个列之间的依赖关系。
ForeignKey
被指定为Column
对象的一个参数,例如:
t = Table("remote_table", metadata,
Column("remote_id", ForeignKey("main_table.id"))
)
注意ForeignKey
只是一个标记对象,它定义了两个列之间的依赖关系。在所有情况下,实际的约束由ForeignKeyConstraint
对象表示。当ForeignKey
与一个与Table
关联的Column
相关联时,此对象将自动生成。相反,当ForeignKeyConstraint
应用于一个与Table
相关联的Table
时,将自动生成ForeignKey
标记,这些标记也与约束对象相关联。
请注意,您不能使用ForeignKey
对象定义“复合”外键约束,即多个父/子列的分组之间的约束。要定义此分组,必须使用ForeignKeyConstraint
对象,并将其应用于Table
。相关的ForeignKey
对象会自动生成。
与单个Column
对象关联的ForeignKey
对象可在该列的 foreign_keys 集合中使用。
更多外键配置示例见定义外键。
成员
init(), argument_for(), column, copy(), dialect_kwargs, dialect_options, get_referent(), info, kwargs, references(), target_fullname
类签名
类sqlalchemy.schema.ForeignKey
(sqlalchemy.sql.base.DialectKWArgs
, sqlalchemy.schema.SchemaItem
)
method __init__(column: _DDLColumnArgument, _constraint: ForeignKeyConstraint | None = None, use_alter: bool = False, name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, link_to_name: bool = False, match: str | None = None, info: _InfoType | None = None, comment: str | None = None, _unresolvable: bool = False, **dialect_kw: Any)
构造列级 FOREIGN KEY。
构造ForeignKey
对象时生成与父Table
对象的约束集合关联的ForeignKeyConstraint
。
参数:
-
column
– 关键关系的单个目标列。一个Column
对象或作为字符串的列名:tablename.columnkey
或schema.tablename.columnkey
。除非link_to_name
为True
,否则columnkey
是分配给列的key
(默认为列名本身)。 -
name
– 可选的字符串。如果未提供约束,则用于键的数据库内名称。 -
onupdate
– 可选的字符串。如果设置,发出 ON UPDATE 的 DDL。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
ondelete
– 可选的字符串。如果设置,发出 ON DELETE 的 DDL。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
deferrable
– 可选的布尔值。如果设置,发出 DEFERRABLE 或 NOT DEFERRABLE 的 DDL。 -
initially
– 可选的字符串。如果设置,发出 INITIALLY 的 DDL。 -
link_to_name
– 如果为 True,则column
中给定的字符串名称是引用列的呈现名称,而不是其本地分配的key
。 -
use_alter
– 传递给底层ForeignKeyConstraint
以指示应该从 CREATE TABLE/ DROP TABLE 语句外部生成/删除约束。 有关详细信息,请参阅ForeignKeyConstraint.use_alter
。 另请参见ForeignKeyConstraint.use_alter
通过 ALTER 创建/删除外键约束 -
match
– 可选字符串。 如果设置,当为此约束发出 DDL 时,将发出 MATCH 。 典型值包括 SIMPLE、PARTIAL 和 FULL。 -
info
– 可选数据字典,将填充到此对象的SchemaItem.info
属性中。 -
comment
– 可选字符串,将在外键约束创建时渲染 SQL 注释。 2.0 版中的新内容。 -
**dialect_kw
– 额外的关键字参数是特定于方言的,并以<dialectname>_<argname>
的形式传递。 这些参数最终由相应的ForeignKeyConstraint
处理。 有关已记录参数的详细信息,请参阅 方言 中有关单个方言的文档。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为此类添加一种新类型的特定于方言的关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种逐个参数方式向 DefaultDialect.construct_arguments
字典添加额外参数的方法。 此字典提供了由各种基于模式的构造物代表方言的参数名列表。
新方言通常应将此字典一次性指定为方言类的数据成员。 通常,临时添加参数名称的用例是为了同时使用自定义编译方案的最终用户代码,该方案使用附加参数。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,指示其参与关键字参数验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则已经可以代表此方言指定任何关键字参数。SQLAlchemy 中打包的所有方言都包括此集合,但对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute column
返回由此 ForeignKey
引用的目标 Column
。
如果没有建立目标列,则会引发异常��
代码语言:javascript复制method copy(*, schema: str | None = None, **kw: Any) → ForeignKey
自版本 1.4 弃用:ForeignKey.copy()
方法已弃用,并将在将来的版本中移除。
attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性 的 DialectKWArgs
作为特定于方言的选项指定的关键字参数集合。
这里的参数以其原始的 <dialect>_<kwarg>
格式呈现。只包括实际传递的参数;不像 DialectKWArgs.dialect_options
集合,该集合包含此方言已知的所有选项,包括默认值。
该集合也是可写的;键的形式为 <dialect>_<kwarg>
,其中的值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性 的 DialectKWArgs
作为特定于方言的选项指定的关键字参数集合。
这是一个两级嵌套的注册表,键入为<dialect_name>
和<argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
版本 0.9.2 中的新功能。
另请参阅
DialectKWArgs.dialect_kwargs
- 扁平字典形式
method get_referent(table: FromClause) → Column[Any] | None
返回此ForeignKey
引用的给定Table
(或任何FromClause
)中的Column
。
如果此ForeignKey
未引用给定的Table
,则返回 None。
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此SchemaItem
关联。
字典在首次访问时自动生成。也可以在一些对象的构造函数中指定,例如Table
和Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
method references(table: Table) → bool
如果此ForeignKey
引用给定的Table
,则返回 True。
attribute target_fullname
返回此ForeignKey
的基于字符串的‘列规范’。
这通常相当于首先传递给对象构造函数的基于字符串的“tablename.colname”参数。
代码语言:javascript复制class sqlalchemy.schema.ForeignKeyConstraint
表级别的外键约束。
定义单列或复合 FOREIGN KEY … REFERENCES 约束。对于简单的、单列的外键,将 ForeignKey
添加到 Column
的定义中相当于一个未命名的、单列的 ForeignKeyConstraint
。
外键配置示例位于 定义外键 中。
成员
init(), argument_for(), column_keys, columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, elements, info, kwargs, referred_table
类签名
类 sqlalchemy.schema.ForeignKeyConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)
method __init__(columns: _typing_Sequence[_DDLColumnArgument], refcolumns: _typing_Sequence[_DDLColumnArgument], name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, use_alter: bool = False, link_to_name: bool = False, match: str | None = None, table: Table | None = None, info: _InfoType | None = None, comment: str | None = None, **dialect_kw: Any) → None
构造一个能够处理复合键的 FOREIGN KEY。
参数:
-
columns
– 一系列本地列名称。所命名的列必须在父表中定义并存在。除非link_to_name
为 True,否则名称应与每列给定的key
匹配(默认为名称)。 -
refcolumns
– 一系列外键列名称或 Column 对象。这些列必须全部位于同一张表内。 -
name
– 可选,键的数据库内名称。 -
onupdate
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON UPDATE 。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
ondelete
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON DELETE 。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
deferrable
– 可选布尔值。如果设置,则在发出此约束的 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。 -
link_to_name
– 如果为 True,则column
中给定的字符串名称是引用列的渲染名称,而不是其本地分配的key
。 -
use_alter
– 如果为 True,则不会将此约束的 DDL 作为 CREATE TABLE 定义的一部分输出。相反,在创建完整的表集合之后,通过 ALTER TABLE 语句生成它,在删除完整的表集合之前,通过 ALTER TABLE 语句将其删除。ForeignKeyConstraint.use_alter
的使用特别适用于两个或多个表在相互依赖的外键约束关系内建立的情况;然而,MetaData.create_all()
和MetaData.drop_all()
方法将自动执行此解析,因此通常不需要该标志。 另请参阅 通过 ALTER 创建/删除外键约束 -
match
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 MATCH 。典型值包括 SIMPLE、PARTIAL 和 FULL。 -
info
– 将填充到此对象的SchemaItem.info
属性中的可选数据字典。 -
comment
– 可选字符串,将在创建外键约束时呈现 SQL 注释。 新版本 2.0 中新增。 -
**dialect_kw
– 附加关键字参数是方言特定的,并以<方言名称>_<参数名称>
形式传递。有关文档中记录的参数的详细信息,请参阅方言中有关单个方言的文档。
classmethod argument_for(dialect_name, argument_name, default)
来自 DialectKWArgs
的 DialectKWArgs.argument_for()
方法继承
为此类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是向DefaultDialect.construct_arguments
字典中各种模式级构造所接受的参数名称添加额外参数的方法。
新方言通常应一次性指定此字典作为方言类的数据成员。临时添加参数名称的用例通常是终端用户代码,该代码还使用自定义编译方案,该方案消耗附加参数。
参数:
-
dialect_name
– 方言的名称。如果无法定位方言,将引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表示它参与关键字参数的验证和默认系统,否则将引发ArgumentError
。如果方言不包括此集合,则可以代表此方言已经指定任何关键字参数。SQLAlchemy 中打包的所有方言都包括此集合,但是对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute column_keys
返回表示此 ForeignKeyConstraint
中本地列的字符串键列表。
此列表是发送到 ForeignKeyConstraint
构造函数的原始字符串参数,或者如果约束已使用 Column
对象进行初始化,则是每个元素的字符串 .key
。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
从 ColumnCollectionMixin
的 ColumnCollectionMixin.columns
属性继承
表示此约束的列集合的 ColumnCollection
。
method contains_column(col: Column[Any]) → bool
从 ColumnCollectionConstraint.contains_column()
方法继承
如果此约束包含给定的列,则返回 True。
请注意,此对象还包含一个属性 .columns
,它是 Column
对象的 ColumnCollection
。
method copy(*, schema: str | None = None, target_table: Table | None = None, **kw: Any) → ForeignKeyConstraint
从版本 1.4 起弃用:ForeignKeyConstraint.copy()
方法已弃用,并将在将来的版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
从 HasConditionalDDL
的 HasConditionalDDL.ddl_if()
方法继承
对此模式项应用条件 DDL 规则。
这些规则的工作方式与ExecutableDDLElement.execute_if()
可调用对象类似,但增加了在 DDL 编译阶段检查条件的功能,例如CreateTable
构造。HasConditionalDDL.ddl_if()
当前还适用于Index
构造以及所有Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或一个字符串名称元组,表示多个方言类型。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
描述的相同形式构造的可调用对象。 -
state
– 如果存在,则会传递给可调用对象的任意对象。
版本 2.0 中的新功能。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
一组关键字参数,指定为此构造的方言特定选项。
这些参数在这里以其原始的<dialect>_<kwarg>
格式呈现。只包括实际传递的参数;与包含此方言的所有选项(包括默认值)的DialectKWArgs.dialect_options
集合不同。
该集合也是可写的;接受形式为<dialect>_<kwarg>
的键,值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
一组关键字参数,指定为此构造的方言特定选项。
这是一个两级嵌套的注册表,键为<dialect_name>
和<argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
版本 0.9.2 中的新功能。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
attribute elements: List[ForeignKey]
一系列ForeignKey
对象。
每个ForeignKey
表示一个引用列/被引用列对。
此集合预期为只读。
代码语言:javascript复制attribute info
继承自SchemaItem.info
属性的
与对象关联的信息字典,允许将用户定义的数据与此SchemaItem
关联。
字典在首次访问时自动生成。它也可以在某些对象的构造函数中指定,例如Table
和Column
。
attribute kwargs
继承自DialectKWArgs.kwargs
属性的
DialectKWArgs.dialect_kwargs
的同义词。
attribute referred_table
此ForeignKeyConstraint
引用的Table
对象。
这是一个动态计算的属性,如果约束和/或父表尚未与包含所引用表的元数据集合关联,则可能无法使用此属性。
代码语言:javascript复制class sqlalchemy.schema.HasConditionalDDL
定义一个包含HasConditionalDDL.ddl_if()
方法的类,允许对 DDL 进行条件渲染。
目前适用于约束和索引。
成员
ddl_if()
版本 2.0 中的新功能。
代码语言:javascript复制method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
对此模式项应用条件 DDL 规则。
这些规则的工作方式类似于 ExecutableDDLElement.execute_if()
可调用对象,但增加了一个特性,即在 DDL 编译阶段可以检查条件,例如 CreateTable
等构造中的条件。 HasConditionalDDL.ddl_if()
目前也适用于 Index
构造以及所有 Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或者字符串名称的元组,表示多种方言类型。 -
callable_
– 一个可调用对象,其构造方式与ExecutableDDLElement.execute_if.callable_
中描述的相同。 -
state
– 如果存在,则将传递给可调用对象的任意对象。
版本 2.0 中的新增内容。
另请参阅
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制class sqlalchemy.schema.PrimaryKeyConstraint
表级别的主键约束。
Table
对象上自动存在 PrimaryKeyConstraint
对象;它被分配了一组与标记有 Column.primary_key
标志的列对应的 Column
对象:
>>> my_table = Table('mytable', metadata,
... Column('id', Integer, primary_key=True),
... Column('version_id', Integer, primary_key=True),
... Column('data', String(50))
... )
>>> my_table.primary_key
PrimaryKeyConstraint(
Column('id', Integer(), table=<mytable>,
primary_key=True, nullable=False),
Column('version_id', Integer(), table=<mytable>,
primary_key=True, nullable=False)
)
也可以通过显式使用 PrimaryKeyConstraint
对象来指定 Table
的主键;在这种用法模式下,还可以指定约束的“名称”,以及方言可能识别的其他选项:
my_table = Table('mytable', metadata,
Column('id', Integer),
Column('version_id', Integer),
Column('data', String(50)),
PrimaryKeyConstraint('id', 'version_id',
name='mytable_pk')
)
通常不应混合两种列规范样式。如果同时存在 PrimaryKeyConstraint
中的列与标记为 primary_key=True
的列不匹配,则会发出警告;在这种情况下,列严格来自 PrimaryKeyConstraint
声明,并且其他标记为 primary_key=True
的列将被忽略。此行为旨在向后兼容以前的行为。
对于需要在 PrimaryKeyConstraint
上指定特定选项的用例,但仍希望使用 primary_key=True
标志的常规方式,可以指定一个空的 PrimaryKeyConstraint
,该约束将根据标志从 Table
中获取主键列集合:
my_table = Table('mytable', metadata,
Column('id', Integer, primary_key=True),
Column('version_id', Integer, primary_key=True),
Column('data', String(50)),
PrimaryKeyConstraint(name='mytable_pk',
mssql_clustered=True)
)
成员
argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
class sqlalchemy.schema.PrimaryKeyConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为此类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种逐个参数地向 DefaultDialect.construct_arguments
字典添加额外参数的方法。此字典提供了各种模式级别构造接受的参数名称列表,代表方言。
新的方言通常应将此字典一次性指定为方言类的数据成员。通常,对参数名称进行临时添加的用例是针对终端用户代码的,该代码还使用了消耗额外参数的自定义编译方案。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则将引发NoSuchModuleError
。方言还必须包含一个现有的DefaultDialect.construct_arguments
集合,表明它参与关键字参数验证和默认系统,否则将引发ArgumentError
。如果方言不包括此集合,则可以代表此方言已经指定任何关键字参数。SQLAlchemy 中打包的所有方言都包括此集合,但是对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin.columns
属性的 ColumnCollectionMixin
代表此约束的一组列的 ColumnCollection
。
method contains_column(col: Column[Any]) → bool
继承自 ColumnCollectionConstraint.contains_column()
方法的 ColumnCollectionConstraint
如果此约束包含给定的列,则返回 True。
请注意,此对象还包含一个名为 .columns
的属性,它是 Column
对象的 ColumnCollection
。
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint
继承自 ColumnCollectionConstraint.copy()
方法的 ColumnCollectionConstraint
从版本 1.4 开始已弃用:ColumnCollectionConstraint.copy()
方法已弃用,并将在将来的版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
对这个模式项应用一个条件 DDL 规则。
这些规则与ExecutableDDLElement.execute_if()
可调用对象的工作方式类似,额外的特性是可以在 DDL 编译阶段检查条件,例如CreateTable
这样的结构。 HasConditionalDDL.ddl_if()
目前也适用于Index
结构以及所有Constraint
结构。
参数:
-
dialect
– 方言的字符串名称,或者字符串名称的元组以指示多个方言类型。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
中描述的相同形式构造的可调用对象。 -
state
– 如果存在,将传递给可调用对象的任意对象。
版本 2.0 中的新功能。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
一组作为特定于方言的选项指定为此结构的关键字参数。
这些参数以原始的 <dialect>_<kwarg>
格式出现在此处。仅包括实际传递的参数;不像DialectKWArgs.dialect_options
集合,该集合包含该方言知道的所有选项,包括默认值。
该集合也是可写的;键以 <dialect>_<kwarg>
形式接受,其中值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
一组作为特定于方言的选项指定为此结构的关键字参数。
这是一个两级嵌套的注册表,键为 <dialect_name>
和 <argument_name>
。例如,postgresql_where
参数可定位为:
arg = my_object.dialect_options['postgresql']['where']
版本 0.9.2 中的新功能。
另请参阅
DialectKWArgs.dialect_kwargs
- 平展的字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
的
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联起来。
字典在首次访问时会自动生成。也可以在某些对象的构造函数中指定,例如 Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
class sqlalchemy.schema.UniqueConstraint
表级别的唯一约束。
定义单列或组合唯一约束。对于简单的单列约束,向 Column
定义中添加 unique=True
是一个等效的缩写,相当于未命名的单列 UniqueConstraint。
成员
init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
类 sqlalchemy.schema.UniqueConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)。
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None
继承自 sqlalchemy.schema.ColumnCollectionConstraint.__init__
方法的 ColumnCollectionConstraint
参数:
-
*columns
– 一系列列名或 Column 对象。 -
name
– 可选项,此约束的数据库内名称。 -
deferrable
– 可选的布尔值。如果设置,当为此约束发出 DDL 时会发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。如果设置,当为此约束发出 DDL 时,会发出 INITIALLY 。 -
**dialect_kw
– 其他关键字参数,包括方言特定参数,将传播到Constraint
超类。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs
的 DialectKWArgs.argument_for()
方法。
为此类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是逐个参数地向 DefaultDialect.construct_arguments
字典添加额外参数的方式。此字典提供了各种模式级别构造所接受的参数名称列表,代表方言。
新方言通常应该将此字典一次性指定为方言类的数据成员。通常情况下,对参数名称的临时添加用例是用于还使用自定义编译方案的端用户代码,该方案会消耗额外的参数。
参数:
-
dialect_name
– 方言的名称。方言必须可定位,否则会引发NoSuchModuleError
。方言还必须包括现有的DefaultDialect.construct_arguments
集合,指示其参与关键字参数验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则已经可以代表此方言指定任何关键字参数。SQLAlchemy 中打包的所有方言都包含此集合,但是对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin
的 ColumnCollectionMixin.columns
属性。
表示此约束的列集合的 ColumnCollection
。
method contains_column(col: Column[Any]) → bool
继承自 ColumnCollectionConstraint.contains_column()
方法的 ColumnCollectionConstraint
如果此约束包含给定的列,则返回 True。
请注意,此对象还包含一个属性.columns
,它是Column
对象的ColumnCollection
。
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint
继承自 ColumnCollectionConstraint.copy()
方法的 ColumnCollectionConstraint
自版本 1.4 开始已弃用:ColumnCollectionConstraint.copy()
方法已弃用,将在未来版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
对此模式项应用一个条件 DDL 规则。
这些规则的工作方式与ExecutableDDLElement.execute_if()
可调用对象类似,但添加了一个特性,即可以在 DDL 编译阶段检查条件,例如CreateTable
构造。 HasConditionalDDL.ddl_if()
目前也适用于Index
构造以及所有Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或者一个字符串名称的元组,表示多个方言类型。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
描述的相同形式构建的可调用对象。 -
state
– 如果存在,将传递给可调用对象的任意对象。
2.0 版中的新功能。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
一个关键字参数的集合,指定为此构造函数的特定于方言的选项。
这里的参数以其原始的 <dialect>_<kwarg>
格式呈现。仅包括实际传递的参数;与 DialectKWArgs.dialect_options
集合不同,后者包含此方言的所有已知选项,包括默认值。
该集合也是可写的;接受形式为 <dialect>_<kwarg>
的键,其值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
一个关键字参数的集合,指定为此构造函数的特定于方言的选项。
这是一个两级嵌套的注册表,键入为 <dialect_name>
和 <argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
新版本中新增 0.9.2。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与此 SchemaItem
关联的信息字典,允许将用户定义的数据与此对象关联。
当首次访问时,该字典将自动生成。也可以在某些对象的构造函数中指定它,例如 Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
function sqlalchemy.schema.conv(value: str, quote: bool | None = None) → Any
标记字符串,指示名称已经被命名约定转换。
这是一个字符串子类,指示不应再受任何进一步命名约定的影响的名称。
例如,当我们按照以下命名约定创建一个 Constraint
时:
m = MetaData(naming_convention={
"ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
CheckConstraint('x > 5', name='x5'))
上述约束的名称将呈现为 "ck_t_x5"
。也就是说,现有名称 x5
被用作命名约定中的 constraint_name
令牌。
在某些情况下,例如在迁移脚本中,我们可能会使用已经转换过的名称渲染上述 CheckConstraint
。为了确保名称不被双重修改,新名称使用 conv()
标记应用。我们可以显式地使用如下:
m = MetaData(naming_convention={
"ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
CheckConstraint('x > 5', name=conv('ck_t_x5')))
在上述情况中,conv()
标记指示此处约束名为最终名称,名称将呈现为 "ck_t_x5"
而不是 "ck_t_ck_t_x5"
另请参见
配置约束命名约定
索引
可以匿名创建索引(使用自动生成的名称 ix_<column label>
)来为单个列使用内联 index
关键字,该关键字还修改了 unique
的使用,将唯一性应用于索引本身,而不是添加单独的 UNIQUE 约束。对于具有特定名称或涵盖多个列的索引,请使用 Index
构造,该构造需要一个名称。
下面我们示例了一个带有多个相关 Index
对象的 Table
。DDL “创建索引”的语句会在表的创建语句之后立即发出:
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
# an indexed column, with index "ix_mytable_col1"
Column("col1", Integer, index=True),
# a uniquely indexed column with index "ix_mytable_col2"
Column("col2", Integer, index=True, unique=True),
Column("col3", Integer),
Column("col4", Integer),
Column("col5", Integer),
Column("col6", Integer),
)
# place an index on col3, col4
Index("idx_col34", mytable.c.col3, mytable.c.col4)
# place a unique index on col5, col6
Index("myindex", mytable.c.col5, mytable.c.col6, unique=True)
mytable.create(engine)
CREATE TABLE mytable (
col1 INTEGER,
col2 INTEGER,
col3 INTEGER,
col4 INTEGER,
col5 INTEGER,
col6 INTEGER
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)
CREATE UNIQUE INDEX ix_mytable_col2 ON mytable (col2)
CREATE UNIQUE INDEX myindex ON mytable (col5, col6)
CREATE INDEX idx_col34 ON mytable (col3, col4)
请注意,在上面的示例中,Index
构造是在对应的表之外创建的,直接使用 Column
对象。Index
还支持在 Table
内部“内联”定义,使用字符串名称标识列:
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
Column("col1", Integer),
Column("col2", Integer),
Column("col3", Integer),
Column("col4", Integer),
# place an index on col1, col2
Index("idx_col12", "col1", "col2"),
# place a unique index on col3, col4
Index("idx_col34", "col3", "col4", unique=True),
)
Index
对象还支持自己的 create()
方法:
i = Index("someindex", mytable.c.col5)
i.create(engine)
CREATE INDEX someindex ON mytable (col5)
函数索引
索引
支持 SQL 和函数表达式,正如目标后端所支持的那样。要针对列使用降序值创建索引,可以使用 ColumnElement.desc()
修饰符:
from sqlalchemy import Index
Index("someindex", mytable.c.somecol.desc())
或者使用支持功能性索引的后端,比如 PostgreSQL,可以使用 lower()
函数创建“不区分大小写”的索引:
from sqlalchemy import func, Index
Index("someindex", func.lower(mytable.c.somecol))
索引 API
对象名称 | 描述 |
---|---|
Index | 表级别的索引。 |
class sqlalchemy.schema.Index
表级别的索引。
定义一个复合(一个或多个列)索引。
例如:
代码语言:javascript复制sometable = Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100))
)
Index("some_index", sometable.c.name)
对于一个简单的单列索引,添加 Column
也支持 index=True
:
sometable = Table("sometable", metadata,
Column("name", String(50), index=True)
)
对于一个复合索引,可以指定多列:
代码语言:javascript复制Index("some_index", sometable.c.name, sometable.c.address)
也支持功能性索引,通常通过结合绑定到表的 Column
对象使用 func
构造来实现:
Index("some_index", func.lower(sometable.c.name))
Index
也可以通过内联声明或使用 Table.append_constraint()
与 Table
手动关联。当使用这种方法时,索引列的名称可以指定为字符串:
Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100)),
Index("some_index", "name", "address")
)
为了在此形式中支持功能性或基于表达式的索引,可以使用 text()
构造:
from sqlalchemy import text
Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100)),
Index("some_index", text("lower(name)"))
)
另请参阅
索引 - 关于 Index
的一般信息。
PostgreSQL 特定索引选项 - 用于 Index
构造的特定于 PostgreSQL 的选项。
MySQL / MariaDB 特定索引选项 - 用于 Index
构造的特定于 MySQL 的选项。
聚集索引支持 - 用于 Index
构造的特定于 MSSQL 的选项。
成员
init(), argument_for(), create(), ddl_if(), dialect_kwargs, dialect_options, drop(), info, kwargs
类签名
类 sqlalchemy.schema.Index
(sqlalchemy.sql.base.DialectKWArgs
, sqlalchemy.schema.ColumnCollectionMixin
, sqlalchemy.schema.HasConditionalDDL
, sqlalchemy.schema.SchemaItem
)
method __init__(name: str | None, *expressions: _DDLColumnArgument, unique: bool = False, quote: bool | None = None, info: _InfoType | None = None, _table: Table | None = None, _column_flag: bool = False, **dialect_kw: Any) → None
构造索引对象。
参数:
-
name
– 索引的名称 -
*expressions
– 要包含在索引中的列表达式。这些表达式通常是Column
的实例,但也可以是最终引用Column
的任意 SQL 表达式。 -
unique=False
– 仅限关键字参数;如果为 True,则创建唯一索引。 -
quote=None
– 仅限关键字参数;是否对索引名称应用引号。其工作方式与Column.quote
相同。 -
info=None
– 可选数据字典,将填充到此对象的SchemaItem.info
属性中。 -
**dialect_kw
– 除上述未提及的其他关键字参数是方言特定的,并以<dialectname>_<argname>
的形式传递。有关文档中列出的参数的详细信息,请参阅有关单个方言的文档 方言 。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为此类添加一种新的特定于方言的关键字参数类型。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种通过每个参数的方式向 DefaultDialect.construct_arguments
字典添加额外参数的方法。该字典提供了各种模式级构造接受的参数名称列表,代表方言。
新方言通常应将此字典一次性指定为方言类的数据成员。通常情况下,临时添加参数名称的用例是用于终端用户代码,该代码还使用了自定义编译方案,该方案使用了额外的参数。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表示它参与关键字参数验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则可以代表该方言已经指定任何关键字参数。SQLAlchemy 中打包的所有方言都包括此集合,但对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
method create(bind: _CreateDropBind, checkfirst: bool = False) → None
为这个 Index
发出一个 CREATE
语句,使用给定的 Connection
或 Engine
进行连接。
另请参见
MetaData.create_all()
.
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
对此模式项应用条件 DDL 规则。
这些规则的工作方式类似于 ExecutableDDLElement.execute_if()
可调用对象,额外的功能是可以在 DDL 编译阶段检查条件,例如 CreateTable
这样的构造。HasConditionalDDL.ddl_if()
目前也适用于 Index
构造以及所有 Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或者字符串名称的元组,表示多个方言类型。 -
callable_
– 一个可调用对象,其构造方式与ExecutableDDLElement.execute_if.callable_
中描述的形式相同。 -
state
– 如果存在,将传递给可调用对象的任意对象。
版本 2.0 中的新功能。
另请参见
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为特定于方言的选项指定的关键字参数集合,用于此构造。
这里的参数以原始的<dialect>_<kwarg>
格式呈现。仅包括实际传递的参数;不像DialectKWArgs.dialect_options
集合,该集合包含此方言已知的所有选项,包括默认值。
该集合也是可写的;接受形式为<dialect>_<kwarg>
的键,其值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为特定于方言的选项指定的关键字参数集合。
这是一个两级嵌套的注册表,键为<dialect_name>
和<argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
从版本 0.9.2 开始。
另请参阅
DialectKWArgs.dialect_kwargs
- 扁平字典形式
method drop(bind: _CreateDropBind, checkfirst: bool = False) → None
使用给定的Connection
或Engine
进行此Index
的DROP
语句。
另请参阅
MetaData.drop_all()
。
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与该对象关联的信息字典,允许将用户定义的数据与此SchemaItem
关联。
当首次访问时,字典将自动生成。它也可以在某些对象的构造函数中指定,例如Table
和Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的一个同义词。
定义外键
在 SQL 中,外键是一个表级构造,它限制该表中的一个或多个列只允许存在于另一组列中的值,通常但不总是位于不同的表中。我们将受到限制的列称为外键列,它们被约束到的列称为引用列。引用列几乎总是定义其所属表的主键,尽管也有例外情况。外键是连接具有彼此关系的行对的“接头部分”,在几乎每个操作中,SQLAlchemy 都将这个概念赋予了非常重要的意义。
在 SQLAlchemy 以及 DDL 中,外键约束可以作为表子句中的附加属性来定义,或者对于单列外键,它们可以选择地在单列的定义中指定。单列外键更常见,在列级别上通过将 ForeignKey
对象构造为 Column
对象的参数来指定:
user_preference = Table(
"user_preference",
metadata_obj,
Column("pref_id", Integer, primary_key=True),
Column("user_id", Integer, ForeignKey("user.user_id"), nullable=False),
Column("pref_name", String(40), nullable=False),
Column("pref_value", String(100)),
)
在上面的示例中,我们为 user_preference
定义了一个新表,其中每行必须包含一个存在于 user
表的 user_id
列中的值。
ForeignKey
的参数最常见的是形式为 . 的字符串,或者对于远程架构或“拥有者”的表,形式为 ..。它也可以是一个实际的 Column
对象,稍后我们将看到,它通过其 c
集合从现有的 Table
对象中访问:
ForeignKey(user.c.user_id)
使用字符串的优势在于,user
和 user_preference
之间的 python 链接只有在首次需要时才会解析,因此表对象可以轻松地分布在多个模块中,并且以任何顺序定义。
外键也可以在表级别定义,使用ForeignKeyConstraint
对象。此对象可以描述单列或多列外键。多列外键被称为复合外键,并且几乎总是引用具有复合主键的表。下面我们定义一个具有复合主键的invoice
表:
invoice = Table(
"invoice",
metadata_obj,
Column("invoice_id", Integer, primary_key=True),
Column("ref_num", Integer, primary_key=True),
Column("description", String(60), nullable=False),
)
然后一个具有引用invoice
的复合外键的invoice_item
表:
invoice_item = Table(
"invoice_item",
metadata_obj,
Column("item_id", Integer, primary_key=True),
Column("item_name", String(60), nullable=False),
Column("invoice_id", Integer, nullable=False),
Column("ref_num", Integer, nullable=False),
ForeignKeyConstraint(
["invoice_id", "ref_num"], ["invoice.invoice_id", "invoice.ref_num"]
),
)
需要注意的是,ForeignKeyConstraint
是定义复合外键的唯一方法。虽然我们也可以将单独的 ForeignKey
对象放置在invoice_item.invoice_id
和invoice_item.ref_num
列上,但 SQLAlchemy 不会意识到这两个值应该成对出现 - 它将成为两个单独的外键约束,而不是引用两列的单个复合外键。
通过 ALTER 创建/删除外键约束
我们在教程和其他地方看到的关于 DDL 中外键的行为表明,约束通常以“内联”的方式在 CREATE TABLE 语句中呈现,例如:
代码语言:javascript复制CREATE TABLE addresses (
id INTEGER NOT NULL,
user_id INTEGER,
email_address VARCHAR NOT NULL,
PRIMARY KEY (id),
CONSTRAINT user_id_fk FOREIGN KEY(user_id) REFERENCES users (id)
)
CONSTRAINT .. FOREIGN KEY
指令用于在 CREATE TABLE 定义内“内联”创建约束。MetaData.create_all()
和 MetaData.drop_all()
方法默认使用拓扑排序对所有涉及的 Table
对象进行排序,以便按外键依赖关系的顺序创建和删除表(此排序也可通过 MetaData.sorted_tables
访问器获得)。
当涉及两个或更多外键约束的“依赖循环”时,此方法无法工作,在这种情况下,一组表彼此相互依赖,假设后端执行外键(SQLite 除外,MySQL/MyISAM 总是如此)。因此,该方法将在除 SQLite 之外的所有后端上将循环中的约束分解为单独的 ALTER 语句,因为 SQLite 不支持大多数形式的 ALTER。给定一个类似的模式:
代码语言:javascript复制node = Table(
"node",
metadata_obj,
Column("node_id", Integer, primary_key=True),
Column("primary_element", Integer, ForeignKey("element.element_id")),
)
element = Table(
"element",
metadata_obj,
Column("element_id", Integer, primary_key=True),
Column("parent_node_id", Integer),
ForeignKeyConstraint(
["parent_node_id"], ["node.node_id"], name="fk_element_parent_node_id"
),
)
当我们在后端(如 PostgreSQL 后端)调用MetaData.create_all()
时,这两个表之间的循环被解决,约束被分别创建:
>>> with engine.connect() as conn:
... metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
element_id SERIAL NOT NULL,
parent_node_id INTEGER,
PRIMARY KEY (element_id)
)
CREATE TABLE node (
node_id SERIAL NOT NULL,
primary_element INTEGER,
PRIMARY KEY (node_id)
)
ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
FOREIGN KEY(parent_node_id) REFERENCES node (node_id)
ALTER TABLE node ADD FOREIGN KEY(primary_element)
REFERENCES element (element_id)
为了对这些表发出 DROP,相同的逻辑适用,但是请注意,在 SQL 中,发出 DROP CONSTRAINT 需要约束具有名称。 在上述'node'
表的情况下,我们没有命名此约束; 因此,系统将仅尝试为具有名称的约束发出 DROP:
>>> with engine.connect() as conn:
... metadata_obj.drop_all(conn, checkfirst=False)
ALTER TABLE element DROP CONSTRAINT fk_element_parent_node_id
DROP TABLE node
DROP TABLE element
在无法解析循环的情况下,例如,如果我们没有在这里为任一约束指定名称,我们将收到以下错误:
代码语言:javascript复制sqlalchemy.exc.CircularDependencyError: Can't sort tables for DROP;
an unresolvable foreign key dependency exists between tables:
element, node. Please ensure that the ForeignKey and ForeignKeyConstraint
objects involved in the cycle have names so that they can be dropped
using DROP CONSTRAINT.
此错误仅适用于 DROP 情况,因为在 CREATE 情况下我们可以不带名称发出“ADD CONSTRAINT”; 数据库通常会自动分配一个名称。
当手动解析依赖关系循环时,可以使用ForeignKeyConstraint.use_alter
和 ForeignKey.use_alter
关键字参数。 我们可以仅将此标志添加到'element'
表中,如下所示:
element = Table(
"element",
metadata_obj,
Column("element_id", Integer, primary_key=True),
Column("parent_node_id", Integer),
ForeignKeyConstraint(
["parent_node_id"],
["node.node_id"],
use_alter=True,
name="fk_element_parent_node_id",
),
)
在我们的 CREATE DDL 中,我们将只看到这个约束的 ALTER 语句,而不是其他约束:
代码语言:javascript复制>>> with engine.connect() as conn:
... metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
element_id SERIAL NOT NULL,
parent_node_id INTEGER,
PRIMARY KEY (element_id)
)
CREATE TABLE node (
node_id SERIAL NOT NULL,
primary_element INTEGER,
PRIMARY KEY (node_id),
FOREIGN KEY(primary_element) REFERENCES element (element_id)
)
ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
FOREIGN KEY(parent_node_id) REFERENCES node (node_id)
当与删除操作一起使用时,ForeignKeyConstraint.use_alter
和 ForeignKey.use_alter
关键字参数将要求约束具有名称,否则将生成以下错误:
sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint
ForeignKeyConstraint(...); it has no name
请参见
配置约束命名约定
sort_tables_and_constraints()
### ON UPDATE and ON DELETE
大多数数据库支持外键值的级联,即当父行更新时,新值将放置在子行中,或者当父行删除时,所有相应的子行都将设置为 null 或删除。 在数据定义语言中,这些是使用诸如“ON UPDATE CASCADE”,“ON DELETE CASCADE”和“ON DELETE SET NULL”之类的短语来指定的,这些短语对应于外键约束。 “ON UPDATE”或“ON DELETE”后面的短语还可以允许其他与正在使用的数据库特定的短语相对应的短语。 ForeignKey
和 ForeignKeyConstraint
对象通过 onupdate
和 ondelete
关键字参数支持通过生成此子句。 值是任何字符串,将在适当的“ON UPDATE”或“ON DELETE”短语之后输出:
child = Table(
"child",
metadata_obj,
Column(
"id",
Integer,
ForeignKey("parent.id", onupdate="CASCADE", ondelete="CASCADE"),
primary_key=True,
),
)
composite = Table(
"composite",
metadata_obj,
Column("id", Integer, primary_key=True),
Column("rev_id", Integer),
Column("note_id", Integer),
ForeignKeyConstraint(
["rev_id", "note_id"],
["revisions.id", "revisions.note_id"],
onupdate="CASCADE",
ondelete="SET NULL",
),
)
请注意,这些子句在与 MySQL 一起使用时需要InnoDB
表。 它们在其他数据库上也可能不受支持。
请参见
关于与 ORM relationship()
构造的 ON DELETE CASCADE
集成的背景,请参见以下各节:
使用 ORM 关系中的外键 ON DELETE cascade
在多对多关系中使用外键 ON DELETE ### 通过 ALTER 创建/删除外键约束
我们在教程和其他地方看到的涉及 DDL 的外键的行为表明,约束通常在 CREATE TABLE 语句中“内联”呈现,例如:
代码语言:javascript复制CREATE TABLE addresses (
id INTEGER NOT NULL,
user_id INTEGER,
email_address VARCHAR NOT NULL,
PRIMARY KEY (id),
CONSTRAINT user_id_fk FOREIGN KEY(user_id) REFERENCES users (id)
)
CONSTRAINT .. FOREIGN KEY
指令用于以“内联”方式在 CREATE TABLE 定义中创建约束。 MetaData.create_all()
和 MetaData.drop_all()
方法默认使用所有涉及的 Table
对象的拓扑排序,这样表就按照它们的外键依赖顺序创建和删除(此排序也可以通过 MetaData.sorted_tables
访问器获得)。
当涉及两个或更多个外键约束参与“依赖循环”时,此方法无法工作,在此循环中一组表相互依赖,假设后端强制执行外键(除 SQLite、MySQL/MyISAM 之外的情况始终如此)。因此,方法将在除不支持大多数 ALTER 形式的 SQLite 外的所有后端上将此类循环中的约束拆分为单独的 ALTER 语句。给定这样的模式:
代码语言:javascript复制node = Table(
"node",
metadata_obj,
Column("node_id", Integer, primary_key=True),
Column("primary_element", Integer, ForeignKey("element.element_id")),
)
element = Table(
"element",
metadata_obj,
Column("element_id", Integer, primary_key=True),
Column("parent_node_id", Integer),
ForeignKeyConstraint(
["parent_node_id"], ["node.node_id"], name="fk_element_parent_node_id"
),
)
当我们在诸如 PostgreSQL 后端之类的后端上调用 MetaData.create_all()
时,这两个表之间的循环被解决,并且约束被单独创建:
>>> with engine.connect() as conn:
... metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
element_id SERIAL NOT NULL,
parent_node_id INTEGER,
PRIMARY KEY (element_id)
)
CREATE TABLE node (
node_id SERIAL NOT NULL,
primary_element INTEGER,
PRIMARY KEY (node_id)
)
ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
FOREIGN KEY(parent_node_id) REFERENCES node (node_id)
ALTER TABLE node ADD FOREIGN KEY(primary_element)
REFERENCES element (element_id)
为了发出这些表的 DROP 命令,相同的逻辑适用,但是请注意,SQL 中,要发出 DROP CONSTRAINT 需要约束具有名称。在上面的 'node'
表的情况下,我们没有为此约束命名;因此系统将尝试仅发出命名的约束的 DROP:
>>> with engine.connect() as conn:
... metadata_obj.drop_all(conn, checkfirst=False)
ALTER TABLE element DROP CONSTRAINT fk_element_parent_node_id
DROP TABLE node
DROP TABLE element
如果无法解决循环,例如我们在这里未给任何约束应用名称的情况,我们将收到以下错误:
代码语言:javascript复制sqlalchemy.exc.CircularDependencyError: Can't sort tables for DROP;
an unresolvable foreign key dependency exists between tables:
element, node. Please ensure that the ForeignKey and ForeignKeyConstraint
objects involved in the cycle have names so that they can be dropped
using DROP CONSTRAINT.
此错误仅适用于 DROP 案例,因为我们可以在 CREATE 案例中发出“ADD CONSTRAINT”而无需名称;数据库通常会自动分配一个名称。
ForeignKeyConstraint.use_alter
和 ForeignKey.use_alter
关键字参数可用于手动解决依赖循环。我们可以将此标志仅添加到 'element'
表中,如下所示:
element = Table(
"element",
metadata_obj,
Column("element_id", Integer, primary_key=True),
Column("parent_node_id", Integer),
ForeignKeyConstraint(
["parent_node_id"],
["node.node_id"],
use_alter=True,
name="fk_element_parent_node_id",
),
)
在我们的 CREATE DDL 中,我们将只看到该约束的 ALTER 语句,而不是其他的:
代码语言:javascript复制>>> with engine.connect() as conn:
... metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
element_id SERIAL NOT NULL,
parent_node_id INTEGER,
PRIMARY KEY (element_id)
)
CREATE TABLE node (
node_id SERIAL NOT NULL,
primary_element INTEGER,
PRIMARY KEY (node_id),
FOREIGN KEY(primary_element) REFERENCES element (element_id)
)
ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
FOREIGN KEY(parent_node_id) REFERENCES node (node_id)
当与删除操作一起使用时,ForeignKeyConstraint.use_alter
和 ForeignKey.use_alter
需要命名约束,否则会生成以下错误:
sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint
ForeignKeyConstraint(...); it has no name
另见
配置约束命名约定
sort_tables_and_constraints()
ON UPDATE 和 ON DELETE
大多数数据库支持外键值的级联,也就是当父行更新时,新值将放置在子行中,或者当父行删除时,所有相应的子行都设置为 null 或删除。在数据定义语言中,这些是使用诸如“ON UPDATE CASCADE”、“ON DELETE CASCADE”和“ON DELETE SET NULL”之类的短语指定的,对应于外键约束。在“ON UPDATE”或“ON DELETE”之后的短语可能还允许其他特定于正在使用的数据库的短语。 ForeignKey
和 ForeignKeyConstraint
对象支持通过 onupdate
和 ondelete
关键字参数生成此子句。该值是任何字符串,将在适当的“ON UPDATE”或“ON DELETE”短语之后输出:
child = Table(
"child",
metadata_obj,
Column(
"id",
Integer,
ForeignKey("parent.id", onupdate="CASCADE", ondelete="CASCADE"),
primary_key=True,
),
)
composite = Table(
"composite",
metadata_obj,
Column("id", Integer, primary_key=True),
Column("rev_id", Integer),
Column("note_id", Integer),
ForeignKeyConstraint(
["rev_id", "note_id"],
["revisions.id", "revisions.note_id"],
onupdate="CASCADE",
ondelete="SET NULL",
),
)
请注意,当与 MySQL 一起使用时,这些子句需要 InnoDB
表。它们在其他数据库上也可能不受支持。
另见
关于将 ON DELETE CASCADE
与 ORM relationship()
构造集成的背景信息,请参见以下部分:
使用 ORM 关联的外键 ON DELETE cascade
在多对多关系中使用外键 ON DELETE
唯一约束
可以使用 Column
上的 unique
关键字匿名地在单个列上创建唯一约束。通过 UniqueConstraint
表级构造显式命名的唯一约束和/或具有多列的约束。
from sqlalchemy import UniqueConstraint
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
# per-column anonymous unique constraint
Column("col1", Integer, unique=True),
Column("col2", Integer),
Column("col3", Integer),
# explicit/composite unique constraint. 'name' is optional.
UniqueConstraint("col2", "col3", name="uix_1"),
)
CHECK 约束
检查约束可以具有命名或未命名,并且可以在列级别或表级别上创建,使用 CheckConstraint
构造。检查约束的文本直接传递到数据库,因此具有有限的“数据库独立”行为。列级别的检查约束通常只应引用它们所放置的列,而表级别的约束可以引用表中的任何列。
请注意,一些数据库不支持主动支持检查约束,例如较旧版本的 MySQL(在 8.0.16 之前)。
代码语言:javascript复制from sqlalchemy import CheckConstraint
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
# per-column CHECK constraint
Column("col1", Integer, CheckConstraint("col1>5")),
Column("col2", Integer),
Column("col3", Integer),
# table level CHECK constraint. 'name' is optional.
CheckConstraint("col2 > col3 5", name="check1"),
)
mytable.create(engine)
CREATE TABLE mytable (
col1 INTEGER CHECK (col1>5),
col2 INTEGER,
col3 INTEGER,
CONSTRAINT check1 CHECK (col2 > col3 5)
)
主键约束
任何 Table
对象的主键约束都是隐式存在的,基于标记有 Column.primary_key
标志的 Column
对象。PrimaryKeyConstraint
对象提供对此约束的显式访问,包括直接配置的选项:
from sqlalchemy import PrimaryKeyConstraint
my_table = Table(
"mytable",
metadata_obj,
Column("id", Integer),
Column("version_id", Integer),
Column("data", String(50)),
PrimaryKeyConstraint("id", "version_id", name="mytable_pk"),
)
另请参阅
PrimaryKeyConstraint
- 详细的 API 文档。
使用 Declarative ORM 扩展时设置约束
Table
是 SQLAlchemy 核心的构造,允许定义表元数据,这些元数据可以被 SQLAlchemy ORM 用作映射类的目标之一。Declarative 扩展允许自动创建 Table
对象,主要是将表的内容作为 Column
对象的映射。
要将诸如 ForeignKeyConstraint
等表级约束对象应用于使用 Declarative 定义的表,请使用 __table_args__
属性,详见 表配置。
配置约束命名约定
关系数据库通常为所有约束和索引分配显式名称。在创建表时使用CREATE TABLE
的常见情况下,约束(如 CHECK、UNIQUE 和 PRIMARY KEY 约束)会与表定义一起内联生成,如果未另有规定,则数据库通常会自动分配名称给这些约束。在使用诸如ALTER TABLE
之类的命令在数据库中更改现有数据库表时,此命令通常需要为新约束指定显式名称,以及能够指定要删除或修改的现有约束的名称。
可以使用Constraint.name
参数和索引的Index.name
参数明确地为约束命名。然而,在约束的情况下,此参数是可选的。还有使用Column.unique
和Column.index
参数的用例,这些参数会创建未指定显式名称的UniqueConstraint
和Index
对象。
通过架构迁移工具,如Alembic,可以处理现有表格和约束的更改用例。但是,目前既不是 Alembic 也不是 SQLAlchemy 创建约束对象的名称,除非另有规定,否则导致能够更改现有约束的情况,这意味着必须逆向工程关系数据库用于自动分配名称的命名系统,或者必须小心确保所有约束都有名称。
与不得不为所有Constraint
和Index
对象分配显式名称相比,可以使用事件构建自动命名方案。这种方法的优点是,约束将获得一致的命名方案,无需在代码中的所有位置都使用显式名称参数,而且约定也会对由Column.unique
和Column.index
参数生成的约束和索引同样适用。从 SQLAlchemy 0.9.2 开始,包含了这种基于事件的方法,可以使用参数MetaData.naming_convention
进行配置。
为 MetaData 集合配置命名约定
MetaData.naming_convention
指的是一个字典,接受 Index
类或单独的 Constraint
类作为键,并接受 Python 字符串模板作为值。它还接受一系列字符串代码作为替代键,分别为外键、主键、索引、检查和唯一约束的 "fk"
、"pk"
、"ix"
、"ck"
、"uq"
。在这个字典中的字符串模板在与此 MetaData
对象关联的约束或索引没有给出现有名称时使用(包括一个例外情况,即可以进一步装饰现有名称的情况)。
适用于基本情况的一个示例命名约定如下:
代码语言:javascript复制convention = {
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
metadata_obj = MetaData(naming_convention=convention)
上述约定将为目标 MetaData
集合中的所有约束建立名称。例如,当我们创建一个未命名的 UniqueConstraint
时,我们可以观察到生成的名称:
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("name", String(30), nullable=False),
... UniqueConstraint("name"),
... )
>>> list(user_table.constraints)[1].name
'uq_user_name'
即使只是使用 Column.unique
标志,这个相同的特性也会生效:
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("name", String(30), nullable=False, unique=True),
... )
>>> list(user_table.constraints)[1].name
'uq_user_name'
命名约定方法的一个关键优势是名称在 Python 构造时建立,而不是在 DDL 发射时建立。使用 Alembic 的 --autogenerate
功能时的影响是,当生成新的迁移脚本时,命名约定将是明确的:
def upgrade():
op.create_unique_constraint("uq_user_name", "user", ["name"])
上面的 "uq_user_name"
字符串是从我们的元数据中 --autogenerate
定位到的 UniqueConstraint
对象中复制的。
可用的标记包括 %(table_name)s
、%(referred_table_name)s
、%(column_0_name)s
、%(column_0_label)s
、%(column_0_key)s
、%(referred_column_0_name)s
,以及每个的多列版本,包括 %(column_0N_name)s
、%(column_0_N_name)s
、%(referred_column_0_N_name)s
,它们以带有或不带有下划线的形式呈现所有列名称。关于 MetaData.naming_convention
的文档对每个约定有进一步的详细信息。
默认命名规则
MetaData.naming_convention
的默认值处理了 SQLAlchemy 长期以来的行为,即为使用Column.index
参数创建的Index
对象分配名称:
>>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
>>> DEFAULT_NAMING_CONVENTION
immutabledict({'ix': 'ix_%(column_0_label)s'})
长名称的截断
当一个生成的名称,特别是那些使用多列令牌的名称,超出了目标数据库的标识符长度限制时(例如,PostgreSQL 的限制为 63 个字符),名称将使用基于长名称的 md5 哈希的 4 字符后缀进行确定性截断。例如,以下命名约定将基于正在使用的列名称生成非常长的名称:
代码语言:javascript复制metadata_obj = MetaData(
naming_convention={"uq": "uq_%(table_name)s_%(column_0_N_name)s"}
)
long_names = Table(
"long_names",
metadata_obj,
Column("information_channel_code", Integer, key="a"),
Column("billing_convention_name", Integer, key="b"),
Column("product_identifier", Integer, key="c"),
UniqueConstraint("a", "b", "c"),
)
在 PostgreSQL 方言上,长度超过 63 个字符的名称将被截断,如下例所示:
代码语言:javascript复制CREATE TABLE long_names (
information_channel_code INTEGER,
billing_convention_name INTEGER,
product_identifier INTEGER,
CONSTRAINT uq_long_names_information_channel_code_billing_conventi_a79e
UNIQUE (information_channel_code, billing_convention_name, product_identifier)
)
上述后缀a79e
是基于长名称的 md5 哈希值,并且每次都会生成相同的值,以便为给定模式生成一致的名称。
创建用于命名约定的自定义令牌
还可以通过在 naming_convention 字典中指定一个额外的令牌和一个可调用对象来添加新的令牌。例如,如果我们想要使用 GUID 方案来命名我们的外键约束,我们可以这样做:
代码语言:javascript复制import uuid
def fk_guid(constraint, table):
str_tokens = (
[
table.name,
]
[element.parent.name for element in constraint.elements]
[element.target_fullname for element in constraint.elements]
)
guid = uuid.uuid5(uuid.NAMESPACE_OID, "_".join(str_tokens).encode("ascii"))
return str(guid)
convention = {
"fk_guid": fk_guid,
"ix": "ix_%(column_0_label)s",
"fk": "fk_%(fk_guid)s",
}
上面,当我们创建一个新的ForeignKeyConstraint
时,我们将获得如下名称:
>>> metadata_obj = MetaData(naming_convention=convention)
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("version", Integer, primary_key=True),
... Column("data", String(30)),
... )
>>> address_table = Table(
... "address",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("user_id", Integer),
... Column("user_version_id", Integer),
... )
>>> fk = ForeignKeyConstraint(["user_id", "user_version_id"], ["user.id", "user.version"])
>>> address_table.append_constraint(fk)
>>> fk.name
fk_0cd51ab5-8d70-56e8-a83c-86661737766d
另请参阅
MetaData.naming_convention
- 用于额外的用法详情以及所有可用命名组件的列表。
命名约束的重要性 - 在 Alembic 文档中。
版本 1.3.0 中的新功能:添加了多列命名令牌,如%(column_0_N_name)s
。生成的名称如果超出目标数据库的字符限制将被确定性截断。
命名 CHECK 约束
CheckConstraint
对象配置为针对任意 SQL 表达式,该表达式可以有任意数量的列,并且通常使用原始 SQL 字符串进行配置。因此,我们通常使用的与CheckConstraint
配合使用的约定是,我们期望对象已经有一个名称,然后我们使用其他约定元素增强它。一个典型的约定是"ck_%(table_name)s_%(constraint_name)s"
:
metadata_obj = MetaData(
naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)
Table(
"foo",
metadata_obj,
Column("value", Integer),
CheckConstraint("value > 5", name="value_gt_5"),
)
上述表将生成名称ck_foo_value_gt_5
:
CREATE TABLE foo (
value INTEGER,
CONSTRAINT ck_foo_value_gt_5 CHECK (value > 5)
)
CheckConstraint
还支持%(columns_0_name)s
令牌;我们可以通过确保在约束的表达式中使用Column
或column()
元素来使用此令牌,无论是通过将约束声明为表的一部分:
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
foo = Table("foo", metadata_obj, Column("value", Integer))
CheckConstraint(foo.c.value > 5)
或者通过使用column()
内联:
from sqlalchemy import column
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
foo = Table(
"foo", metadata_obj, Column("value", Integer), CheckConstraint(column("value") > 5)
)
两者都将生成名称ck_foo_value
:
CREATE TABLE foo (
value INTEGER,
CONSTRAINT ck_foo_value CHECK (value > 5)
)
对“列零”的名称确定是通过扫描给定表达式以查找列对象进行的。如果表达式中存在多个列,则扫描会使用确定性搜索,但是表达式的结构将确定哪一列被指定为“列零”。 ### 对布尔、枚举和其他模式类型进行命名配置
SchemaType
类引用诸如 Boolean
和 Enum
之类的类型对象,这些对象生成伴随类型的 CHECK 约束。此处约束的名称最直接通过发送“name”参数设置,例如 Boolean.name
:
Table("foo", metadata_obj, Column("flag", Boolean(name="ck_foo_flag")))
命名约定功能也可以与这些类型结合使用,通常是通过使用包含%(constraint_name)s
的约定,然后将名称应用于类型:
metadata_obj = MetaData(
naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)
Table("foo", metadata_obj, Column("flag", Boolean(name="flag_bool")))
上述表将产生约束名称ck_foo_flag_bool
:
CREATE TABLE foo (
flag BOOL,
CONSTRAINT ck_foo_flag_bool CHECK (flag IN (0, 1))
)
SchemaType
类使用特殊的内部符号,以便命名约定仅在 DDL 编译时确定。在 PostgreSQL 上,有一个原生的 BOOLEAN 类型,因此不需要 Boolean
的 CHECK 约束;我们可以安全地设置 Boolean
类型而不需要名称,即使对于检查约束已经设置了命名约定。如果我们在没有原生 BOOLEAN 类型的数据库上运行,例如 SQLite 或 MySQL,则仅会查阅此约定以获取 CHECK 约束。
CHECK 约束也可以使用column_0_name
令牌,与SchemaType
非常匹配,因为这些约束只有一列:
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
Table("foo", metadata_obj, Column("flag", Boolean()))
上述模式将产生:
代码语言:javascript复制CREATE TABLE foo (
flag BOOL,
CONSTRAINT ck_foo_flag CHECK (flag IN (0, 1))
)
使用 ORM 声明性混合物时使用命名约定
当使用命名约定功能与 ORM 声明式 Mixins 时,每个实际表映射子类必须存在单独的约束对象。有关背景和示例,请参阅使用命名约定在 Mixins 上创建索引和约束的部分。
配置 MetaData 集合的命名约定
MetaData.naming_convention
指的是一个字典,接受Index
类或个别Constraint
类作为键,以及 Python 字符串模板作为值。它还接受一系列字符串代码作为替代键,分别为外键、主键、索引、检查和唯一约束的 "fk"
、"pk"
、"ix"
、"ck"
、"uq"
。这个字典中的字符串模板在与这个MetaData
对象相关联的约束或索引没有给出现有名称时使用(包括一个现有名称可以进一步修饰的例外情况)。
适用于基本情况的示例命名约定如下:
代码语言:javascript复制convention = {
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
metadata_obj = MetaData(naming_convention=convention)
上述约定将为目标MetaData
集合中的所有约束建立名称。例如,当我们创建一个未命名的UniqueConstraint
时,我们可以观察到生成的名称。
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("name", String(30), nullable=False),
... UniqueConstraint("name"),
... )
>>> list(user_table.constraints)[1].name
'uq_user_name'
即使我们只是使用Column.unique
标志,同样的特性也会生效:
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("name", String(30), nullable=False, unique=True),
... )
>>> list(user_table.constraints)[1].name
'uq_user_name'
命名约定方法的一个关键优势是名称在 Python 构造时建立,而不是在 DDL 发射时。当使用 Alembic 的 --autogenerate
特性时,这个效果是命名约定在生成新的迁移脚本时将是明确的:
def upgrade():
op.create_unique_constraint("uq_user_name", "user", ["name"])
上述"uq_user_name"
字符串是从我们的元数据中--autogenerate
定位到的UniqueConstraint
对象中复制的。
可用的标记包括%(table_name)s
、%(referred_table_name)s
、%(column_0_name)s
、%(column_0_label)s
、%(column_0_key)s
、%(referred_column_0_name)s
,以及每个的多列版本,包括%(column_0N_name)s
、%(column_0_N_name)s
、%(referred_column_0_N_name)s
,它们用下划线分隔或不分隔所有列名。有关MetaData.naming_convention
的文档还详细介绍了每个约定。
默认命名约定
MetaData.naming_convention
的默认值处理了 SQLAlchemy 的长期行为,即为使用Column.index
参数创建的Index
对象分配名称:
>>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
>>> DEFAULT_NAMING_CONVENTION
immutabledict({'ix': 'ix_%(column_0_label)s'})
截断长名称
当生成的名称特别是那些使用多列令牌的名称,超出目标数据库的标识符长度限制时(例如,PostgreSQL 的限制为 63 个字符),名称将使用基于长名称的 md5 哈希的 4 字符后缀进行确定性截断。例如,给定以下命名约定,根据使用的列名称,将生成非常长的名称:
代码语言:javascript复制metadata_obj = MetaData(
naming_convention={"uq": "uq_%(table_name)s_%(column_0_N_name)s"}
)
long_names = Table(
"long_names",
metadata_obj,
Column("information_channel_code", Integer, key="a"),
Column("billing_convention_name", Integer, key="b"),
Column("product_identifier", Integer, key="c"),
UniqueConstraint("a", "b", "c"),
)
在 PostgreSQL 方言中,名称长度超过 63 个字符的将被截断,如以下示例所示:
代码语言:javascript复制CREATE TABLE long_names (
information_channel_code INTEGER,
billing_convention_name INTEGER,
product_identifier INTEGER,
CONSTRAINT uq_long_names_information_channel_code_billing_conventi_a79e
UNIQUE (information_channel_code, billing_convention_name, product_identifier)
)
上述后缀a79e
是基于长名称的 md5 哈希值,并且每次生成相同的值,以便为给定模式生成一致的名称。
创建自定义令牌以用于命名约定
也可以通过在 naming_convention 字典中指定额外的令牌和可调用对象来添加新令牌。例如,如果我们想要使用 GUID 方案为外键约束命名,我们可以这样做:
代码语言:javascript复制import uuid
def fk_guid(constraint, table):
str_tokens = (
[
table.name,
]
[element.parent.name for element in constraint.elements]
[element.target_fullname for element in constraint.elements]
)
guid = uuid.uuid5(uuid.NAMESPACE_OID, "_".join(str_tokens).encode("ascii"))
return str(guid)
convention = {
"fk_guid": fk_guid,
"ix": "ix_%(column_0_label)s",
"fk": "fk_%(fk_guid)s",
}
上面,当我们创建一个新的ForeignKeyConstraint
时,我们将得到以下名称:
>>> metadata_obj = MetaData(naming_convention=convention)
>>> user_table = Table(
... "user",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("version", Integer, primary_key=True),
... Column("data", String(30)),
... )
>>> address_table = Table(
... "address",
... metadata_obj,
... Column("id", Integer, primary_key=True),
... Column("user_id", Integer),
... Column("user_version_id", Integer),
... )
>>> fk = ForeignKeyConstraint(["user_id", "user_version_id"], ["user.id", "user.version"])
>>> address_table.append_constraint(fk)
>>> fk.name
fk_0cd51ab5-8d70-56e8-a83c-86661737766d
另请参阅
MetaData.naming_convention
- 有关更多使用详细信息以及所有可用命名组件的列表。
命名约束的重要性 - Alembic 文档中的内容。
从版本 1.3.0 开始:添加了多列命名令牌,例如%(column_0_N_name)s
。生成的名称如果超过目标数据库的字符限制,将被确定性地截断。
命名 CHECK 约束
CheckConstraint
对象针对任意 SQL 表达式进行配置,该表达式可以有任意数量的列,而且通常使用原始 SQL 字符串进行配置。因此,与CheckConstraint
一起使用的一种常见约定是,我们期望对象已经具有名称,然后我们使用其他约定元素来增强它。一个典型的约定是"ck_%(table_name)s_%(constraint_name)s"
:
metadata_obj = MetaData(
naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)
Table(
"foo",
metadata_obj,
Column("value", Integer),
CheckConstraint("value > 5", name="value_gt_5"),
)
上述表将生成名称ck_foo_value_gt_5
:
CREATE TABLE foo (
value INTEGER,
CONSTRAINT ck_foo_value_gt_5 CHECK (value > 5)
)
CheckConstraint
还支持%(columns_0_name)s
令牌;我们可以通过确保在约束表达式中使用Column
或column()
元素来利用这一点,无论是通过单独声明约束还是通过在表内:
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
foo = Table("foo", metadata_obj, Column("value", Integer))
CheckConstraint(foo.c.value > 5)
或通过使用column()
内联:
from sqlalchemy import column
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
foo = Table(
"foo", metadata_obj, Column("value", Integer), CheckConstraint(column("value") > 5)
)
两者都会生成名称为ck_foo_value
的内容:
CREATE TABLE foo (
value INTEGER,
CONSTRAINT ck_foo_value CHECK (value > 5)
)
“列零”的名称确定是通过扫描给定表达式中的列对象执行的。如果表达式中存在多个列,则扫描将使用确定性搜索,但表达式的结构将确定哪一列被标记为“列零”。
针对布尔型、枚举型和其他模式类型进行命名配置
SchemaType
类引用诸如Boolean
和Enum
之类的类型对象,这些对象生成伴随类型的 CHECK 约束。此处约束的名称最直接通过发送“name”参数设置,例如Boolean.name
:
Table("foo", metadata_obj, Column("flag", Boolean(name="ck_foo_flag")))
命名约定功能也可以与这些类型结合使用,通常是使用包含%(constraint_name)s
的约定,然后将名称应用于类型:
metadata_obj = MetaData(
naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)
Table("foo", metadata_obj, Column("flag", Boolean(name="flag_bool")))
上述表将产生约束名为ck_foo_flag_bool
:
CREATE TABLE foo (
flag BOOL,
CONSTRAINT ck_foo_flag_bool CHECK (flag IN (0, 1))
)
SchemaType
类使用特殊的内部符号,以便命名约定仅在 DDL 编译时确定。在 PostgreSQL 上,有一种原生的 BOOLEAN 类型,因此不需要Boolean
的 CHECK 约束;即使有检查约定,我们也可以安全地设置一个不带名称的Boolean
类型。只有在没有原生 BOOLEAN 类型的数据库(如 SQLite 或 MySQL)上运行时,才会咨询此约定以进行 CHECK 约束。
CHECK 约束也可以使用column_0_name
令牌,这与SchemaType
非常匹配,因为这些约束只有一个列:
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})
Table("foo", metadata_obj, Column("flag", Boolean()))
上述模式将产生:
代码语言:javascript复制CREATE TABLE foo (
flag BOOL,
CONSTRAINT ck_foo_flag CHECK (flag IN (0, 1))
)
使用 ORM 声明性 Mixin 配置命名约定
在使用命名约定功能与 ORM 声明性混合时,每个实际表映射的子类必须存在单独的约束对象。有关背景和示例,请参见使用命名约定在混合上创建索引和约束部分。
约束 API
对象名称 | 描述 |
---|---|
检查约束 | 表级或列级检查约束。 |
列集合约束 | 代理列集合的约束。 |
ColumnCollectionMixin | 一个ColumnCollection对象的Column集合。 |
约束 | 表级 SQL 约束。 |
conv | 标记一个字符串,指示名称已经通过命名约定转换。 |
外键 | 定义两列之间的依赖关系。 |
外键约束 | 表级外键约束。 |
具有条件 DDL | 定义一个包括HasConditionalDDL.ddl_if()方法的类,允许对 DDL 进行条件渲染。 |
主键约束 | 表级主键约束。 |
唯一约束 | 表级唯一约束。 |
class sqlalchemy.schema.Constraint
表级 SQL 约束。
Constraint
作为可以与Table
对象关联的一系列约束对象的基类,包括PrimaryKeyConstraint
、ForeignKeyConstraint
、UniqueConstraint
和CheckConstraint
。
成员
init(), argument_for(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
类 sqlalchemy.schema.Constraint
(sqlalchemy.sql.base.DialectKWArgs
, sqlalchemy.schema.HasConditionalDDL
, sqlalchemy.schema.SchemaItem
)
method __init__(name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, comment: str | None = None, _create_rule: Any | None = None, _type_bound: bool = False, **dialect_kw: Any) → None
创建一个 SQL 约束。
参数:
-
name
– 可选的,这个Constraint
在数据库中的名称。 -
deferrable
– 可选布尔值。如果设置,当为这个约束发出 DDL 时,会发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。如果设置,当为这个约束发出 DDL 时,会发出 INITIALLY 。 -
info
– 可选的数据字典,将被填充到此对象的SchemaItem.info
属性中。 -
comment
– 在外键约束创建时渲染 SQL 注释的可选字符串。 新版本 2.0 中新增。 -
**dialect_kw
– 附加的关键字参数是方言特定的,并以<dialectname>_<argname>
的形式传递。有关每个方言的文档参数的详细信息,请参见 Dialects 中的文档。 -
_create_rule
– 由一些也创建约束的数据类型内部使用。 -
_type_bound
– 用于内部指示此约束与特定数据类型相关联。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为这个类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种通过每个参数方式向 DefaultDialect.construct_arguments
字典添加额外参数的方法。该字典提供了接受方言各种架构级别构造的参数名称列表。
新方言通常应该一次性将此字典指定为方言类的数据成员。通常,对于使用自定义编译方案并消耗额外参数的端用户代码,额外添加参数名的用例是使用这些参数。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
异常。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表明它参与关键字参数验证和默认系统,否则会引发ArgumentError
异常。如果方言不包含此集合,则可以代表该方言已经指定任何关键字参数。SQLAlchemy 中打包的所有方言都包含此集合,但对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
method copy(**kw: Any) → Self
从 1.4 版开始已弃用:Constraint.copy()
方法已弃用,并将在未来的版本中移除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
将条件 DDL 规则应用于此模式项。
这些规则的工作方式类似于ExecutableDDLElement.execute_if()
可调用对象,但增加了一个特性,即可以在 DDL 编译阶段为CreateTable
等结构检查条件。HasConditionalDDL.ddl_if()
目前适用于Index
结构以及所有Constraint
结构。
参数:
-
dialect
– 方言的字符串名称,或者表示多个方言类型的字符串名称元组。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
描述的相同形式构造的可调用对象。 -
state
– 如果存在,则将传递给可调用对象的任意对象。
2.0 版中的新功能。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为方言特定选项指定为关键字参数的集合。
这些参数以原始的 <dialect>_<kwarg>
格式呈现在这里。仅包括实际传递的参数;不像DialectKWArgs.dialect_options
集合那样,它包含了该方言已知的所有选项,包括默认值。
该集合也是可写的;键的形式为 <dialect>_<kwarg>
,其中的值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项指定为关键字参数的集合。
这是一个两级嵌套的注册表,以 <dialect_name>
和 <argument_name>
为键。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
在版本 0.9.2 中新增。
另请参阅
DialectKWArgs.dialect_kwargs
- 扁平字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象相关联的信息字典,允许将用户定义的数据与此SchemaItem
关联起来。
字典在首次访问时会自动生成。它也可以在某些对象的构造函数中指定,比如Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
一个与DialectKWArgs.dialect_kwargs
同义的词语。
class sqlalchemy.schema.ColumnCollectionMixin
一个Column
对象的ColumnCollection
。
此集合代表此对象引用的列。
代码语言:javascript复制class sqlalchemy.schema.ColumnCollectionConstraint
代理列集合的约束。
成员
init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
class sqlalchemy.schema.ColumnCollectionConstraint
(sqlalchemy.schema.ColumnCollectionMixin
, sqlalchemy.schema.Constraint
)
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None
参数:
-
*columns
– 一系列列名或列对象。 -
name
– 可选,此约束在数据库中的名称。 -
deferrable
– 可选布尔值。如果设置,当为此约束发���DDL 时,发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。如果设置,当为此约束发出 DDL 时,发出 INITIALLY 。 -
**dialect_kw
– 其他关键字参数,包括方言特定参数,将传播到Constraint
超类。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs
的 DialectKWArgs.argument_for()
方法
为这个类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种逐个参数地向DefaultDialect.construct_arguments
字典添加额外参数的方式。该字典提供了一个由方言代表接受各种模式级构造的参数名称列表。
新方言通常应一次性将此字典指定为方言类的数据成员。临时添加参数名称的用例通常是针对同时使用自定义编译方案的最终用户代码,该编译方案使用额外的参数。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表明它参与关键字参数的验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则可以代表此方言已经指定任何关键字参数。SQLAlchemy 中打包的所有方言都包括此集合,但是对于第三方方言,支持可能会有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin.columns
属性,来自于 ColumnCollectionMixin
一个 ColumnCollection
表示这个约束的列集合。
method contains_column(col: Column[Any]) → bool
如果此约束包含给定的列,则返回 True。
注意,此对象还包含一个属性 .columns
,它是一个 ColumnCollection
,包含了 Column
对象。
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint
从版本 1.4 开始不推荐使用:ColumnCollectionConstraint.copy()
方法已弃用,将在未来的版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法,来自于 HasConditionalDDL
为此模式项应用条件性 DDL 规则。
这些规则的工作方式类似于 ExecutableDDLElement.execute_if()
可调用对象,额外的功能是可以在 DDL 编译阶段检查条件,例如 CreateTable
这样的结构。 HasConditionalDDL.ddl_if()
目前也适用于 Index
结构以及所有 Constraint
结构。
参数:
-
dialect
– 方言的字符串名称,或指示多个方言类型的字符串名称的元组。 -
callable_
– 一个可调用对象,其构造方式与ExecutableDDLElement.execute_if.callable_
中描述的形式相同。 -
state
– 如果存在,将传递给可调用对象的任意对象。
新版本 2.0 中新增。
另请参阅
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制attribute dialect_kwargs
从 DialectKWArgs.dialect_kwargs
属性继承
作为此结构的方言特定选项指定的关键字参数集合。
这里的参数以其原始 <dialect>_<kwarg>
格式呈现。只包括实际传递的参数;与 DialectKWArgs.dialect_options
集合不同,后者包含此方言知道的所有选项,包括默认值。
此集合也是可写的;接受形式为 <dialect>_<kwarg>
的键,其值将组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
从 DialectKWArgs.dialect_options
属性继承
作为此结构的方言特定选项指定的关键字参数集合。
这是一个两级嵌套的注册表,键入为 <dialect_name>
和 <argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
新版本 0.9.2 中新增。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联。
字典在首次访问时会自动生成。也可以在某些对象的构造函数中指定,例如 Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
class sqlalchemy.schema.CheckConstraint
表或列级别的 CHECK 约束。
可以包含在表或列的定义中。
成员
init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
类 sqlalchemy.schema.CheckConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)
method __init__(sqltext: _TextCoercedExpressionArgument[Any], name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, table: Table | None = None, info: _InfoType | None = None, _create_rule: Any | None = None, _autoattach: bool = True, _type_bound: bool = False, **dialect_kw: Any) → None
构造一个 CHECK 约束。
参数:
sqltext
–
包含约束定义的字符串,将直接使用,或者是一个 SQL 表达式构造。如果给定为字符串,则对象将转换为 text()
对象。如果文本字符串包含冒号字符,请使用反斜杠进行转义:
CheckConstraint(r"foo ~ E'a(?:b|c)d")
警告
CheckConstraint
的CheckConstraint.sqltext
参数可以作为 Python 字符串参数传递,该字符串参数将被视为可信任的 SQL 文本并按照给定的方式呈现。不要将不受信任的输入传递给此参数。
name
– 可选,约束的数据库中名称。
deferrable
– 可选布尔值。如果设置,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。
initially
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。
info
– 可选数据字典,将填充到此对象的SchemaItem.info
属性中。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs
类的 DialectKWArgs.argument_for()
方法
为此类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是向DefaultDialect.construct_arguments
字典添加额外参数的一种逐参数方式。此字典为代表方言的各种模式级构造接受的参数名称提供了列表。
新方言通常应一次性将此字典指定为方言类的数据成员。通常情况下,用于添加参数名称的临时用例是终端用户代码,该代码还使用了自定义编译方案,该方案消耗了额外的参数。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则将引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,指示它参与关键字参数验证和默认系统,否则将引发ArgumentError
。如果方言不包括此集合,则可以代表此方言已经指定任何关键字参数。SQLAlchemy 中打包的所有方言都包括此集合,但是对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin
的 ColumnCollectionMixin.columns
属性
表示此约束的列集合。
代码语言:javascript复制method contains_column(col: Column[Any]) → bool
继承自 ColumnCollectionConstraint
的 ColumnCollectionConstraint.contains_column()
方法
如果此约束包含给定列,则返回 True。
请注意,此对象还包含一个属性 .columns
,它是 Column
对象的 ColumnCollection
。
method copy(*, target_table: Table | None = None, **kw: Any) → CheckConstraint
自版本 1.4 弃用:CheckConstraint.copy()
方法已弃用,将在未来的版本中移除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL
的 HasConditionalDDL.ddl_if()
方法
将条件 DDL 规则应用于此模式项。
这些规则的工作方式与 ExecutableDDLElement.execute_if()
可调用对象类似,额外的功能是可以在 DDL 编译阶段检查标准,例如 CreateTable
构造。 HasConditionalDDL.ddl_if()
目前也适用于 Index
构造以及所有 Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或字符串名称的元组,以指示多个方言类型。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
中描述的相同形式构建的可调用对象。 -
state
– 将传递给可调用对象的任意对象(如果存在)。
自版本 2.0 新增。
另请参阅
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为方言特定选项指定为此结构的关键字参数的集合。
这里的参数以其原始 <dialect>_<kwarg>
格式呈现。仅包含实际传递的参数;不像 DialectKWArgs.dialect_options
集合,该集合包含此方言已知的所有选项,包括默认值。
该集合也是可写的;接受的键的形式为 <dialect>_<kwarg>
,其中值将被组装成选项列表。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项指定为此结构的关键字参数的集合。
这是一个两级嵌套的注册表,键入 <dialect_name>
和 <argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
版本 0.9.2 中新增。
另请参阅
DialectKWArgs.dialect_kwargs
- 扁平字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联。
第一次访问时,字典会自动生成。它也可以在某些对象的构造函数中指定,例如 Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
class sqlalchemy.schema.ForeignKey
定义两列之间的依赖关系。
ForeignKey
被指定为 Column
对象的参数,例如:
t = Table("remote_table", metadata,
Column("remote_id", ForeignKey("main_table.id"))
)
请注意,ForeignKey
仅是一个标记对象,定义了两列之间的依赖关系。在所有情况下,实际约束都由 ForeignKeyConstraint
对象表示。当ForeignKey
与一个 Column
相关联,而这个列又与一个 Table
相关联时,此对象将自动生成。反之,当 ForeignKeyConstraint
应用于一个 Table
时,ForeignKey
标记将自动在每个相关联的 Column
上存在,这些列也与约束对象相关联。
请注意,您不能使用 ForeignKey
对象定义“复合”外键约束,即多个父/子列的分组约束。要定义此分组,必须使用 ForeignKeyConstraint
对象,并应用于 Table
。相关联的ForeignKey
对象将自动创建。
与单个 Column
对象相关联的 ForeignKey
对象可在该列的 foreign_keys 集合中找到。
关于外键配置的更多示例在定义外键中。
成员
init(), argument_for(), column, copy(), dialect_kwargs, dialect_options, get_referent(), info, kwargs, references(), target_fullname
类签名
类 sqlalchemy.schema.ForeignKey
(sqlalchemy.sql.base.DialectKWArgs
, sqlalchemy.schema.SchemaItem
)
method __init__(column: _DDLColumnArgument, _constraint: ForeignKeyConstraint | None = None, use_alter: bool = False, name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, link_to_name: bool = False, match: str | None = None, info: _InfoType | None = None, comment: str | None = None, _unresolvable: bool = False, **dialect_kw: Any)
构建一个列级的外键。
构造时生成 ForeignKey
对象,与父 Table
对象的约束集合关联的 ForeignKeyConstraint
。
参数:
-
column
– 键关系的单个目标列。Column
对象或列名称字符串:tablename.columnkey
或schema.tablename.columnkey
。columnkey
是分配给列的key
(默认为列名称本身),除非link_to_name
为True
,此时使用列的呈现名称。 -
name
– 可选字符串。如果未提供约束,则键的数据库名称。 -
onupdate
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON UPDATE 。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
ondelete
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON DELETE 。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
deferrable
– 可选布尔值。如果设置,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。 -
link_to_name
– 如果为 True,则column
中给定的字符串名称是引用列的呈现名称,而不是其本地分配的key
。 -
use_alter
– 传递给底层ForeignKeyConstraint
,以指示约束应从 CREATE TABLE/ DROP TABLE 语句外部生成/删除。有关详细描述,请参阅ForeignKeyConstraint.use_alter
。 另请参阅ForeignKeyConstraint.use_alter
通过 ALTER 创建/删除外键约束 -
match
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 MATCH 。典型值包括 SIMPLE、PARTIAL 和 FULL。 -
info
– 可选数据字典,将填充到此对象的SchemaItem.info
属性中。 -
comment
– 可选字符串,将在创建外键约束时呈现 SQL 注释。 版本 2.0 中的新内容。 -
**dialect_kw
– 附加的关键字参数是方言特定的,并以<dialectname>_<argname>
的形式传递。这些参数最终由相应的ForeignKeyConstraint
处理。有关文档化参数的详细信息,请参阅 Dialects 中关于各个方言的文档。
classmethod argument_for(dialect_name, argument_name, default)
从 DialectKWArgs
的 DialectKWArgs.argument_for()
方法继承
为这个类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是向 DefaultDialect.construct_arguments
字典添加额外参数的逐个参数方式。该字典提供了在方言代表各种模式级构造时代表方言接受的参数名称的列表。
新方言通常应将此字典一次性指定为方言类的数据成员。临时添加参数名称的用例通常用于同时使用自定义编译方案的最终用户代码,该编译方案使用额外的参数。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表示它参与关键字参数验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则已经可以代表该方言指定任何关键字参数。所有打包在 SQLAlchemy 中的方言都包括此集合,但对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute column
返回由此 ForeignKey
引用的目标 Column
。
如果没有建立目标列,则会引发异常。
代码语言:javascript复制method copy(*, schema: str | None = None, **kw: Any) → ForeignKey
自版本 1.4 起弃用:ForeignKey.copy()
方法已弃用,并将在未来版本中移除。
attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
这是作为方言特定选项指定的关键字参数的集合。
这些参数以原始的 <dialect>_<kwarg>
格式显示在此处。仅包括实际传递的参数;与 DialectKWArgs.dialect_options
不同,后者包含此方言已知的所有选项,包括默认值。
该集合也是可写的;接受形式为 <dialect>_<kwarg>
的键,其中值将被组装成选项列表。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
这是作为方言特定选项指定的关键字参数的集合。
这是一个两级嵌套的注册表,以 <dialect_name>
和 <argument_name>
为键。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
新版本为 0.9.2。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
method get_referent(table: FromClause) → Column[Any] | None
返回由此 ForeignKey
引用的给定 Table
(或任何 FromClause
)中的 Column
。
如果此 ForeignKey
未引用给定的 Table
,则返回 None。
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联。
第一次访问时,字典会自动生成。它也可以在某些对象的构造函数中指定,例如Table
和Column
。
attribute kwargs
从 DialectKWArgs.kwargs
属性继承 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
method references(table: Table) → bool
如果给定的Table
被此ForeignKey
引用,则返回 True。
attribute target_fullname
为此ForeignKey
返回基于字符串的“列规范”。
这通常是传递给对象构造函数的基于字符串的“tablename.colname”参数的等效值。
代码语言:javascript复制class sqlalchemy.schema.ForeignKeyConstraint
表级外键约束。
定义单列或复合外键引用约束。对于简单的、单列外键,向Column
的定义中添加一个ForeignKey
是一个简写等效于未命名的、单列ForeignKeyConstraint
。
外键配置示例在定义外键中。
成员
init(), argument_for(), column_keys, columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, elements, info, kwargs, referred_table
类签名
类sqlalchemy.schema.ForeignKeyConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)
method __init__(columns: _typing_Sequence[_DDLColumnArgument], refcolumns: _typing_Sequence[_DDLColumnArgument], name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, use_alter: bool = False, link_to_name: bool = False, match: str | None = None, table: Table | None = None, info: _InfoType | None = None, comment: str | None = None, **dialect_kw: Any) → None
构造一个支持复合的外键。
参数:
-
columns
– 本地列名称的序列。这些命名列必须在父表中定义并存在。除非link_to_name
为 True,否则名称应与每个列(默认为名称)给定的key
匹配。 -
refcolumns
– 外键列名称或 Column 对象的序列。这些列必须全部位于同一个表中。 -
name
– 可选项,键的数据库内名称。 -
onupdate
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON UPDATE 。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
ondelete
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON DELETE 。典型值包括 CASCADE、DELETE 和 RESTRICT。 -
deferrable
– 可选布尔值。如果设置,则在发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。 -
link_to_name
– 如果为 True,则column
中给定的字符串名称是引用列的渲染名称,而不是其在本地分配的key
。 -
use_alter
– 如果为 True,则不会将此约束的 DDL 作为 CREATE TABLE 定义的一部分发出。相反,在完整的表集合创建之后,通过 ALTER TABLE 语句生成它,并在删除完整的表集合之前通过 ALTER TABLE 语句将其删除。 使用ForeignKeyConstraint.use_alter
特别适用于两个或多个表在相互依赖的外键约束关系中建立的情况;但是,MetaData.create_all()
和MetaData.drop_all()
方法将自动执行此解析,因此通常不需要此标志。 另请参阅 通过 ALTER 创建/删除外键约束 -
match
– 可选字符串。如果设置,则在为此约束发出 DDL 时发出 MATCH 。典型值包括 SIMPLE、PARTIAL 和 FULL。 -
info
– 将填充到此对象的SchemaItem.info
属性中的可选数据字典。 -
comment
– 在外键约束创建时渲染一个 SQL 注释的可选字符串。 在 2.0 版中新增。 -
**dialect_kw
– 额外的关键字参数是方言特定的,并以<方言名称>_<参数名称>
的形式传递。有关文档化参数的详细信息,请参阅方言中有关各个方言的文档。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs
的 DialectKWArgs.argument_for()
方法
为此类添加一种新的特定于方言的关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是向DefaultDialect.construct_arguments
字典添加额外参数的每个参数的方法。此字典提供了各种模式级别构造函数可接受的参数名称列表。
新的方言通常应将此字典作为方言类的数据成员一次性指定。通常情况下,用于临时添加参数名称的用例是为了终端用户代码,该代码还使用自定义编译方案,该方案消耗附加参数。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,指示它参与关键字参数验证和默认系统,否则会引发ArgumentError
。如果方言不包含此集合,则可以代表该方言指定任何关键字参数。SQLAlchemy 内置的所有方言都包含此集合,但对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute column_keys
返回一个字符串键列表,表示此ForeignKeyConstraint
中的本地列。
此列表是发送到ForeignKeyConstraint
构造函数的原始字符串参数,或者如果约束已使用Column
对象初始化,则是每个元素的字符串.key
。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin.columns
属性
代表此约束的ColumnCollection
表示列的集合。
method contains_column(col: Column[Any]) → bool
继承自 ColumnCollectionConstraint.contains_column()
方法的 ColumnCollectionConstraint
如果此约束包含给定列,则返回 True。
请注意,这个对象还包含一个属性.columns
,它是一个ColumnCollection
对象的集合,其中包含Column
对象。
method copy(*, schema: str | None = None, target_table: Table | None = None, **kw: Any) → ForeignKeyConstraint
自版本 1.4 弃用:ForeignKeyConstraint.copy()
方法已弃用,并将在将来的版本中移除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
将条件 DDL 规则应用于此模式项。
这些规则的工作方式类似于ExecutableDDLElement.execute_if()
可调用对象,只是增加了一个特性,即在 DDL 编译阶段可以检查条件,例如CreateTable
构造。HasConditionalDDL.ddl_if()
当前还适用于Index
构造以及所有Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或者一个字符串名称的元组,表示多个方言类型。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
描述的相同形式构造的可调用对象。 -
state
– 任意的对象,如果存在,将传递给可调用对象。
从版本 2.0 开始新添加。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
此结构的特定方言选项的关键字参数集合。
这里的参数以其原始<dialect>_<kwarg>
格式呈现。仅包含实际传递的参数;与DialectKWArgs.dialect_options
集合不同,后者包含此方言已知的所有选项,包括默认值。
该集合也是可写的;键采用<dialect>_<kwarg>
的形式,其中值将被组装成选项列表。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
此结构的特定方言选项的关键字参数集合。
这是一个两级嵌套注册表,键入<dialect_name>
和<argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
从版本 0.9.2 开始。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
attribute elements: List[ForeignKey]
一系列ForeignKey
对象。
每个ForeignKey
代表单个引用列/被引用列对。
此集合旨在为只读。
代码语言:javascript复制attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此SchemaItem
相关联。
字典在首次访问时自动生成。它也可以在某些对象的构造函数中指定,例如Table
和Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性,属于 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
attribute referred_table
此 ForeignKeyConstraint
引用的 Table
对象。
这是一个动态计算的属性,如果约束和/或父表尚未与包含所引用表的元数据集关联,则可能不可用。
代码语言:javascript复制class sqlalchemy.schema.HasConditionalDDL
定义一个包含 HasConditionalDDL.ddl_if()
方法的类,允许对 DDL 进行条件渲染。
目前适用于约束和索引。
成员
ddl_if()
版本 2.0 中新增。
代码语言:javascript复制method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
将一个条件 DDL 规则应用到此模式项。
这些规则的工作方式与 ExecutableDDLElement.execute_if()
可调用对象类似,但增加了一个功能,即可以在 DDL 编译阶段检查条件,例如 CreateTable
。 HasConditionalDDL.ddl_if()
目前也适用于 Index
构造以及所有 Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或字符串名称的元组,表示多个方言类型。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
描述的形式构建的可调用对象。 -
state
– 如果存在,将传递给可调用对象的任意对象。
版本 2.0 中新增。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制class sqlalchemy.schema.PrimaryKeyConstraint
表级主键约束。
PrimaryKeyConstraint
对象会自动出现在任何 Table
对象上;它被分配一组与标记为 Column.primary_key
标志相对应的 Column
对象:
>>> my_table = Table('mytable', metadata,
... Column('id', Integer, primary_key=True),
... Column('version_id', Integer, primary_key=True),
... Column('data', String(50))
... )
>>> my_table.primary_key
PrimaryKeyConstraint(
Column('id', Integer(), table=<mytable>,
primary_key=True, nullable=False),
Column('version_id', Integer(), table=<mytable>,
primary_key=True, nullable=False)
)
Table
的主键也可以通过显式使用 PrimaryKeyConstraint
对象来指定;在这种用法模式下,“约束”的“名称”也可以指定,以及方言可能识别的其他选项:
my_table = Table('mytable', metadata,
Column('id', Integer),
Column('version_id', Integer),
Column('data', String(50)),
PrimaryKeyConstraint('id', 'version_id',
name='mytable_pk')
)
两种列规范样式通常不应混合使用。如果 PrimaryKeyConstraint
中存在的列与标记为 primary_key=True
的列不匹配,则会发出警告,如果两者都存在;在这种情况下,列严格来自 PrimaryKeyConstraint
声明,并且其他标记为 primary_key=True
的列将被忽略。这种行为旨在与先前的行为向后兼容。
对于需要在 PrimaryKeyConstraint
上指定特定选项的用例,但仍然希望使用 primary_key=True
标志的常规样式的情况,可以指定一个空的 PrimaryKeyConstraint
,它将从基于标志的 Table
中采用主键列集合:
my_table = Table('mytable', metadata,
Column('id', Integer, primary_key=True),
Column('version_id', Integer, primary_key=True),
Column('data', String(50)),
PrimaryKeyConstraint(name='mytable_pk',
mssql_clustered=True)
)
成员
argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
类 sqlalchemy.schema.PrimaryKeyConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为此类添加一种新的方言特定的关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种逐个参数地向 DefaultDialect.construct_arguments
字典添加额外参数的方式。此字典提供了由各种模式级构造接受的参数名称列表,代表方言。
新的方言通常应一次性指定此字典作为方言类的数据成员。临时添加参数名的用例通常是为了使用自定义编译方案的终端用户代码,该编译方案消耗额外的参数。
参数:
-
dialect_name
– 方言的名称。 方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包含一个现有的DefaultDialect.construct_arguments
集合,表示它参与关键字参数验证和默认系统,否则会引发ArgumentError
。 如果方言不包含此集合,则可以为此方言代表已经指定任何关键字参数。SQLAlchemy 中打包的所有方言都包括此集合,但对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
继承自 ColumnCollectionMixin.columns
属性的 ColumnCollectionMixin
表示此约束的列集合的 ColumnCollection
。
method contains_column(col: Column[Any]) → bool
继承自 ColumnCollectionConstraint.contains_column()
方法的 ColumnCollectionConstraint
如果此约束包含给定列,则返回 True。
请注意,此对象还包含一个名为.columns
的属性,它是Column
对象的ColumnCollection
。
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint
继承自 ColumnCollectionConstraint.copy()
方法的 ColumnCollectionConstraint
自版本 1.4 起弃用:ColumnCollectionConstraint.copy()
方法已弃用,并将在将来的版本中移除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法的 HasConditionalDDL
对此模式项应用条件 DDL 规则。
这些规则的工作方式类似于ExecutableDDLElement.execute_if()
可调用对象,额外的特性是可以在 DDL 编译阶段检查条件,例如CreateTable
这样的构造函数。HasConditionalDDL.ddl_if()
目前也适用于Index
构造以及所有Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或表示多个方言类型的字符串名称元组。 -
callable_
– 使用与ExecutableDDLElement.execute_if.callable_
中描述的相同形式构造的可调用对象。 -
state
– 如果存在,将传递给可调用对象的任意对象。
从版本 2.0 开始新增。
另请参阅
控制约束和索引的 DDL 生成 - 背景和使用示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为方言特定选项指定的关键字参数集合,用于此构造函数。
这里的参数以其原始<dialect>_<kwarg>
格式呈现。仅包括实际传递的参数;不像DialectKWArgs.dialect_options
集合,该集合包含此方言已知的所有选项,包括默认值。
该集合也是可写的;接受形式为<dialect>_<kwarg>
的键,其中值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项指定给此结构的关键字参数集合。
这是一个两级嵌套的注册表,键为<dialect_name>
和<argument_name>
。例如,postgresql_where
参数可定位为:
arg = my_object.dialect_options['postgresql']['where']
新版本中新增的功能为 0.9.2。
另请参阅
DialectKWArgs.dialect_kwargs
- 平面字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此SchemaItem
相关联。
字典在首次访问时会自动生成。它也可以在某些对象的构造函数中指定,例如Table
和Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
class sqlalchemy.schema.UniqueConstraint
表级别的唯一约束。
定义单列或复合唯一约束。对于简单的单列约束,将unique=True
添加到Column
定义中相当于未命名的单列 UniqueConstraint 的简写等效形式。
成员
init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs
类签名
类sqlalchemy.schema.UniqueConstraint
(sqlalchemy.schema.ColumnCollectionConstraint
)
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None
继承自 sqlalchemy.schema.ColumnCollectionConstraint.__init__
方法的 ColumnCollectionConstraint
参数:
-
*columns
– 列名或列对象的序列。 -
name
– 可选,此约束的数据库中的名称。 -
deferrable
– 可选布尔值。 如果设置,为此约束发出 DEFERRABLE 或 NOT DEFERRABLE。 -
initially
– 可选字符串。 如果设置,发出 INITIALLY when 为此约束发出 DDL。 -
**dialect_kw
– 其他关键字参数,包括方言特定参数,将传递给Constraint
超类。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为这个类添加一种新的方言特定关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是逐个添加额外参数到DefaultDialect.construct_arguments
字典的方法。 这个字典提供了由各种模式级构造接受的代表方言的参数名称的列表。
新的方言通常应该一次性指定这个字典作为方言类的数据成员。 临时添加参数名称的用例通常是为了使用自定义编译方案并消耗额外参数的最终用户代码。
参数:
-
dialect_name
– 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,表示它参与关键字参数验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则可以代表此方言已经指定任何关键字参数。SQLAlchemy 内置的所有方言都包括此集合,但对于第三方方言,支持可能有所不同。 -
argument_name
– 参数的名称。 -
default
– 参数的默认值。
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]
从 ColumnCollectionMixin
的 .columns
属性继承
代表此约束的一组列的 ColumnCollection
。
method contains_column(col: Column[Any]) → bool
从 ColumnCollectionConstraint
的 ColumnCollectionConstraint.contains_column()
方法继承
如果此约束包含给定列,则返回 True。
请注意,此对象还包含一个名为.columns
的属性,它是 Column
对象的 ColumnCollection
。
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint
从 ColumnCollectionConstraint
的 ColumnCollectionConstraint.copy()
方法继承
自版本 1.4 起已弃用:ColumnCollectionConstraint.copy()
方法已弃用,并将在将来的版本中删除。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
从 HasConditionalDDL
的 HasConditionalDDL.ddl_if()
方法继承
对此模式项目应用条件 DDL 规则。
这些规则的工作方式类似于ExecutableDDLElement.execute_if()
可调用对象,额外的特性是在 DDL 编译阶段可以检查条件,例如CreateTable
构造中。HasConditionalDDL.ddl_if()
目前也适用于Index
构造以及所有Constraint
构造。
参数:
-
dialect
– 方言的字符串名称,或者字符串名称的元组,表示多个方言类型。 -
callable_
– 一个可调用对象,其构造方式与ExecutableDDLElement.execute_if.callable_
中描述的形式相同。 -
state
– 任意对象,如果存在将传递给可调用对象。
新版本 2.0。
另请参阅
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为方言特定选项指定给此构造的关键字参数集合。
这里的参数以其原始的<dialect>_<kwarg>
格式呈现。仅包括实际传递的参数;不像DialectKWArgs.dialect_options
集合,该集合包含此方言已��的所有选项,包括默认值。
该集合也是可写的;键的形式为<dialect>_<kwarg>
,其中值将被组装到选项列表中。
另请参阅
DialectKWArgs.dialect_options
- 嵌套字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项指定给此构造的关键字参数集合。
这是一个两级嵌套的注册表,键为<dialect_name>
和<argument_name>
。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
新版本 0.9.2。
另请参阅
DialectKWArgs.dialect_kwargs
- 平坦的字典形式
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联起来。
字典在首次访问时会自动生成。它也可以在某些对象的构造函数中指定,例如 Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
DialectKWArgs.dialect_kwargs
的同义词。
function sqlalchemy.schema.conv(value: str, quote: bool | None = None) → Any
标记一个字符串,指示名称已经通过命名约定转换。
这是一个字符串子类,表示不应再受任何其他命名约定影响的名称。
例如 当我们使用以下命名约定创建 Constraint
时:
m = MetaData(naming_convention={
"ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
CheckConstraint('x > 5', name='x5'))
上述约束的名称将呈现为 "ck_t_x5"
。即,现有名称 x5
被用作命名约定中的 constraint_name
令牌。
在某些情况下,例如在迁移脚本中,我们可能会渲染上述 CheckConstraint
的名称已经被转换了。为了确保名称不会被双重修改,新名称使用 conv()
标记应用。我们可以明确使用如下:
m = MetaData(naming_convention={
"ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
CheckConstraint('x > 5', name=conv('ck_t_x5')))
在上面的例子中,conv()
标记表示此处的约束名称是最终的,名称将呈现为 "ck_t_x5"
而不是 "ck_t_ck_t_x5"
另请参阅
配置约束命名约定
索引
索引可以匿名创建(使用自动生成的名称 ix_<column label>
)为单列使用内联 index
关键字,在 Column
上,该关键字也修改了 unique
的用法,将唯一性应用于索引本身,而不是添加一个单独的 UNIQUE 约束。对于具有特定名称或涵盖多个列的索引,请使用 Index
结构,该结构需要一个名称。
下面我们展示了一个具有多个关联 Index
对象的 Table
。DDL 为“CREATE INDEX”在表的创建语句之后发布:
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
# an indexed column, with index "ix_mytable_col1"
Column("col1", Integer, index=True),
# a uniquely indexed column with index "ix_mytable_col2"
Column("col2", Integer, index=True, unique=True),
Column("col3", Integer),
Column("col4", Integer),
Column("col5", Integer),
Column("col6", Integer),
)
# place an index on col3, col4
Index("idx_col34", mytable.c.col3, mytable.c.col4)
# place a unique index on col5, col6
Index("myindex", mytable.c.col5, mytable.c.col6, unique=True)
mytable.create(engine)
CREATE TABLE mytable (
col1 INTEGER,
col2 INTEGER,
col3 INTEGER,
col4 INTEGER,
col5 INTEGER,
col6 INTEGER
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)
CREATE UNIQUE INDEX ix_mytable_col2 ON mytable (col2)
CREATE UNIQUE INDEX myindex ON mytable (col5, col6)
CREATE INDEX idx_col34 ON mytable (col3, col4)
注意,在上面的示例中,Index
结构是外部创建的,与其对应的表使用 Column
对象直接创建。Index
也支持在 Table
内部“内联”定义,使用字符串名称来标识列:
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
Column("col1", Integer),
Column("col2", Integer),
Column("col3", Integer),
Column("col4", Integer),
# place an index on col1, col2
Index("idx_col12", "col1", "col2"),
# place a unique index on col3, col4
Index("idx_col34", "col3", "col4", unique=True),
)
Index
对象也支持其自己的 create()
方法:
i = Index("someindex", mytable.c.col5)
i.create(engine)
CREATE INDEX someindex ON mytable (col5)
函数索引
Index
支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 ColumnElement.desc()
修改器:
from sqlalchemy import Index
Index("someindex", mytable.c.somecol.desc())
或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower()
函数创建“不区分大小写”的索引:
from sqlalchemy import func, Index
Index("someindex", func.lower(mytable.c.somecol))
```### 函数索引
`Index` 支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 `ColumnElement.desc()` 修改器:
```py
from sqlalchemy import Index
Index("someindex", mytable.c.somecol.desc())
或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower()
函数创建“不区分大小写”的索引:
from sqlalchemy import func, Index
Index("someindex", func.lower(mytable.c.somecol))
索引 API
对象名称 | 描述 |
---|---|
索引 | 一个表级索引。 |
class sqlalchemy.schema.Index
一个表级索引。
定义一个复合(一个或多个列)索引。
例如:
代码语言:javascript复制sometable = Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100))
)
Index("some_index", sometable.c.name)
对于一个简单的、单列索引,添加 Column
也支持 index=True
:
sometable = Table("sometable", metadata,
Column("name", String(50), index=True)
)
对于复合索引,可以指定多列:
代码语言:javascript复制Index("some_index", sometable.c.name, sometable.c.address)
功能性索引也得到支持,通常通过与绑定到表的Column
对象一起使用func
构造来实现:
Index("some_index", func.lower(sometable.c.name))
Index
也可以手动与Table
关联,可以通过内联声明或使用Table.append_constraint()
来实现。当使用此方法时,可以将索引列的名称指定为字符串:
Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100)),
Index("some_index", "name", "address")
)
要支持此形式中的功能性或基于表达式的索引,可以使用text()
构造:
from sqlalchemy import text
Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100)),
Index("some_index", text("lower(name)"))
)
另请参阅
索引 - 有关Index
的一般信息。
PostgreSQL 特定索引选项 - 适用于Index
构造的 PostgreSQL 特定选项。
MySQL / MariaDB 特定索引选项 - MySQL 特定选项适用于Index
构造。
集群索引支持 - MSSQL 特定选项适用于Index
构造。
成员
init(), argument_for(), create(), ddl_if(), dialect_kwargs, dialect_options, drop(), info, kwargs
类签名
类sqlalchemy.schema.Index
(sqlalchemy.sql.base.DialectKWArgs
, sqlalchemy.schema.ColumnCollectionMixin
, sqlalchemy.schema.HasConditionalDDL
, sqlalchemy.schema.SchemaItem
)
method __init__(name: str | None, *expressions: _DDLColumnArgument, unique: bool = False, quote: bool | None = None, info: _InfoType | None = None, _table: Table | None = None, _column_flag: bool = False, **dialect_kw: Any) → None
构造一个索引对象。
参数:
-
name
– 索引的名称 -
*expressions
– 要包含在索引中的列表达式。这些表达式通常是Column
的实例,但也可以是最终指向Column
的任意 SQL 表达式。 -
unique=False
– 仅限关键字参数;如果为 True,则创建一个唯一索引。 -
quote=None
– 仅限关键字参数;是否对索引的名称应用引号。工作方式与Column.quote
相同。 -
info=None
– 可选数据字典,将填充到此对象的SchemaItem.info
属性中。 -
**dialect_kw
– 上述未提及的额外关键字参数是方言特定的,并以<dialectname>_<argname>
的形式传递。有关个别方言的文档参数的详细信息,请参阅方言的文档。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为这个类添加一种新的方言特定的关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种逐个添加额外参数到DefaultDialect.construct_arguments
字典的方式。该字典提供了在方言代表构造级别构造上接受的各种参数名称的列表。
新方言通常应将此字典一次性指定为方言类的数据成员。通常,对于需要临时添加参数名的用例,是用于终端用户代码,该代码还使用了自定义的编译方案,其中包含了额外的参数。
参数:
-
dialect_name
- 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,指示它参与关键字参数的验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则已为此方言指定任何关键字参数都是可以的。SQLAlchemy 中打包的所有方言都包含此集合,但对于第三方方言,支持可能会有所不同。 -
argument_name
- 参数的名称。 -
default
- 参数的默认值。
method create(bind: _CreateDropBind, checkfirst: bool = False) → None
对于此 Index
,使用给定的 Connection
或 Engine
发出 CREATE
语句以进行连接。
参见
MetaData.create_all()
。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法 HasConditionalDDL
将条件 DDL 规则应用于此模式项。
这些规则的工作方式类似于 ExecutableDDLElement.execute_if()
可调用对象,其附加功能是可以在 DDL 编译阶段检查条件,例如 CreateTable
构造。HasConditionalDDL.ddl_if()
目前也适用于 Index
构造以及所有 Constraint
构造。
参数:
-
dialect
- 方言的字符串名称,或一组字符串名称以指示多个方言类型。 -
callable_
- 使用与ExecutableDDLElement.execute_if.callable_
中描述的相同形式构造的可调用对象。 -
state
- 如果存在,将传递给可调用对象的任意对象。
从版本 2.0 开始新增。
参见
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为方言特定选项的关键字参数集合,用于这个构造函数。
这里的参数以其原始的 <dialect>_<kwarg>
格式存在。只包括实际传递的参数;不像 DialectKWArgs.dialect_options
集合,该集合包含此方言已知的所有选项,包括默认值。
集合也是可写的;接受形式为 <dialect>_<kwarg>
的键,其值将被组装成选项列表。
另请参阅
DialectKWArgs.dialect_options
- 嵌套的字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项的关键字参数集合,用于这个构造函数。
这是一个两级嵌套的注册表,以 <dialect_name>
和 <argument_name>
为键。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
版本 0.9.2 中的新功能。
另请参阅
DialectKWArgs.dialect_kwargs
- 平坦的字典形式
method drop(bind: _CreateDropBind, checkfirst: bool = False) → None
使用给定的 Connection
或 Engine
进行连接性,为此 Index
发出 DROP
语句。
另请参阅
MetaData.drop_all()
.
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联。
第一次访问时,字典会自动生成。它也可以在某些对象的构造函数中指定,比如Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
。
DialectKWArgs.dialect_kwargs
的同义词。
,
col5 INTEGER,
col6 INTEGER
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)
CREATE UNIQUE INDEX ix_mytable_col2 ON mytable (col2)
CREATE UNIQUE INDEX myindex ON mytable (col5, col6)
CREATE INDEX idx_col34 ON mytable (col3, col4)
注意,在上面的示例中,`Index` 结构是外部创建的,与其对应的表使用 `Column` 对象直接创建。`Index` 也支持在 `Table` 内部“内联”定义,使用字符串名称来标识列:
```py
metadata_obj = MetaData()
mytable = Table(
"mytable",
metadata_obj,
Column("col1", Integer),
Column("col2", Integer),
Column("col3", Integer),
Column("col4", Integer),
# place an index on col1, col2
Index("idx_col12", "col1", "col2"),
# place a unique index on col3, col4
Index("idx_col34", "col3", "col4", unique=True),
)
Index
对象也支持其自己的 create()
方法:
i = Index("someindex", mytable.c.col5)
i.create(engine)
CREATE INDEX someindex ON mytable (col5)
函数索引
Index
支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 ColumnElement.desc()
修改器:
from sqlalchemy import Index
Index("someindex", mytable.c.somecol.desc())
或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower()
函数创建“不区分大小写”的索引:
from sqlalchemy import func, Index
Index("someindex", func.lower(mytable.c.somecol))
```### 函数索引
`Index` 支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 `ColumnElement.desc()` 修改器:
```py
from sqlalchemy import Index
Index("someindex", mytable.c.somecol.desc())
或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower()
函数创建“不区分大小写”的索引:
from sqlalchemy import func, Index
Index("someindex", func.lower(mytable.c.somecol))
索引 API
对象名称 | 描述 |
---|---|
索引 | 一个表级索引。 |
class sqlalchemy.schema.Index
一个表级索引。
定义一个复合(一个或多个列)索引。
例如:
代码语言:javascript复制sometable = Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100))
)
Index("some_index", sometable.c.name)
对于一个简单的、单列索引,添加 Column
也支持 index=True
:
sometable = Table("sometable", metadata,
Column("name", String(50), index=True)
)
对于复合索引,可以指定多列:
代码语言:javascript复制Index("some_index", sometable.c.name, sometable.c.address)
功能性索引也得到支持,通常通过与绑定到表的Column
对象一起使用func
构造来实现:
Index("some_index", func.lower(sometable.c.name))
Index
也可以手动与Table
关联,可以通过内联声明或使用Table.append_constraint()
来实现。当使用此方法时,可以将索引列的名称指定为字符串:
Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100)),
Index("some_index", "name", "address")
)
要支持此形式中的功能性或基于表达式的索引,可以使用text()
构造:
from sqlalchemy import text
Table("sometable", metadata,
Column("name", String(50)),
Column("address", String(100)),
Index("some_index", text("lower(name)"))
)
另请参阅
索引 - 有关Index
的一般信息。
PostgreSQL 特定索引选项 - 适用于Index
构造的 PostgreSQL 特定选项。
MySQL / MariaDB 特定索引选项 - MySQL 特定选项适用于Index
构造。
集群索引支持 - MSSQL 特定选项适用于Index
构造。
成员
init(), argument_for(), create(), ddl_if(), dialect_kwargs, dialect_options, drop(), info, kwargs
类签名
类sqlalchemy.schema.Index
(sqlalchemy.sql.base.DialectKWArgs
, sqlalchemy.schema.ColumnCollectionMixin
, sqlalchemy.schema.HasConditionalDDL
, sqlalchemy.schema.SchemaItem
)
method __init__(name: str | None, *expressions: _DDLColumnArgument, unique: bool = False, quote: bool | None = None, info: _InfoType | None = None, _table: Table | None = None, _column_flag: bool = False, **dialect_kw: Any) → None
构造一个索引对象。
参数:
-
name
– 索引的名称 -
*expressions
– 要包含在索引中的列表达式。这些表达式通常是Column
的实例,但也可以是最终指向Column
的任意 SQL 表达式。 -
unique=False
– 仅限关键字参数;如果为 True,则创建一个唯一索引。 -
quote=None
– 仅限关键字参数;是否对索引的名称应用引号。工作方式与Column.quote
相同。 -
info=None
– 可选数据字典,将填充到此对象的SchemaItem.info
属性中。 -
**dialect_kw
– 上述未提及的额外关键字参数是方言特定的,并以<dialectname>_<argname>
的形式传递。有关个别方言的文档参数的详细信息,请参阅方言的文档。
classmethod argument_for(dialect_name, argument_name, default)
继承自 DialectKWArgs.argument_for()
方法的 DialectKWArgs
为这个类添加一种新的方言特定的关键字参数。
例如:
代码语言:javascript复制Index.argument_for("mydialect", "length", None)
some_index = Index('a', 'b', mydialect_length=5)
DialectKWArgs.argument_for()
方法是一种逐个添加额外参数到DefaultDialect.construct_arguments
字典的方式。该字典提供了在方言代表构造级别构造上接受的各种参数名称的列表。
新方言通常应将此字典一次性指定为方言类的数据成员。通常,对于需要临时添加参数名的用例,是用于终端用户代码,该代码还使用了自定义的编译方案,其中包含了额外的参数。
参数:
-
dialect_name
- 方言的名称。方言必须是可定位的,否则会引发NoSuchModuleError
。方言还必须包括一个现有的DefaultDialect.construct_arguments
集合,指示它参与关键字参数的验证和默认系统,否则会引发ArgumentError
。如果方言不包括此集合,则已为此方言指定任何关键字参数都是可以的。SQLAlchemy 中打包的所有方言都包含此集合,但对于第三方方言,支持可能会有所不同。 -
argument_name
- 参数的名称。 -
default
- 参数的默认值。
method create(bind: _CreateDropBind, checkfirst: bool = False) → None
对于此 Index
,使用给定的 Connection
或 Engine
发出 CREATE
语句以进行连接。
参见
MetaData.create_all()
。
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self
继承自 HasConditionalDDL.ddl_if()
方法 HasConditionalDDL
将条件 DDL 规则应用于此模式项。
这些规则的工作方式类似于 ExecutableDDLElement.execute_if()
可调用对象,其附加功能是可以在 DDL 编译阶段检查条件,例如 CreateTable
构造。HasConditionalDDL.ddl_if()
目前也适用于 Index
构造以及所有 Constraint
构造。
参数:
-
dialect
- 方言的字符串名称,或一组字符串名称以指示多个方言类型。 -
callable_
- 使用与ExecutableDDLElement.execute_if.callable_
中描述的相同形式构造的可调用对象。 -
state
- 如果存在,将传递给可调用对象的任意对象。
从版本 2.0 开始新增。
参见
控制约束和索引的 DDL 生成 - 背景和用法示例
代码语言:javascript复制attribute dialect_kwargs
继承自 DialectKWArgs.dialect_kwargs
属性的 DialectKWArgs
作为方言特定选项的关键字参数集合,用于这个构造函数。
这里的参数以其原始的 <dialect>_<kwarg>
格式存在。只包括实际传递的参数;不像 DialectKWArgs.dialect_options
集合,该集合包含此方言已知的所有选项,包括默认值。
集合也是可写的;接受形式为 <dialect>_<kwarg>
的键,其值将被组装成选项列表。
另请参阅
DialectKWArgs.dialect_options
- 嵌套的字典形式
attribute dialect_options
继承自 DialectKWArgs.dialect_options
属性的 DialectKWArgs
作为方言特定选项的关键字参数集合,用于这个构造函数。
这是一个两级嵌套的注册表,以 <dialect_name>
和 <argument_name>
为键。例如,postgresql_where
参数可以定位为:
arg = my_object.dialect_options['postgresql']['where']
版本 0.9.2 中的新功能。
另请参阅
DialectKWArgs.dialect_kwargs
- 平坦的字典形式
method drop(bind: _CreateDropBind, checkfirst: bool = False) → None
使用给定的 Connection
或 Engine
进行连接性,为此 Index
发出 DROP
语句。
另请参阅
MetaData.drop_all()
.
attribute info
继承自 SchemaItem.info
属性的 SchemaItem
与对象关联的信息字典,允许将用户定义的数据与此 SchemaItem
关联。
第一次访问时,字典会自动生成。它也可以在某些对象的构造函数中指定,比如Table
和 Column
。
attribute kwargs
继承自 DialectKWArgs.kwargs
属性的 DialectKWArgs
。
DialectKWArgs.dialect_kwargs
的同义词。