运算符参考
本节详细介绍了用于构建 SQL 表达式的运算符的用法。
这些方法按照 Operators
和 ColumnOperators
基类的方式呈现。然后这些方法可用于这些类的后代,包括:
Column
对象ColumnElement
对象更一般地,这些对象是所有 Core SQL 表达式语言列级表达式的根InstrumentedAttribute
对象,这些对象是 ORM 级别的映射属性。
运算符首先在教程部分中介绍,包括:
- SQLAlchemy 统一教程 - 以 2.0 风格 呈现的统一教程
- 对象关系教程 - ORM 教程以 1.x 风格 呈现
- SQL 表达式语言教程 - 以 1.x 风格 呈现的核心教程
比较运算符
基本比较,适用于许多数据类型,包括数值、字符串、日期等:
ColumnOperators.__eq__()
(Python “==
” 运算符):
>>> print(column("x") == 5) x = :x_1
ColumnOperators.__ne__()
(Python “!=
” 运算符):
>>> print(column("x") != 5) x != :x_1
ColumnOperators.__gt__()
(Python “>
” 运算符):
>>> print(column("x") > 5) x > :x_1
ColumnOperators.__lt__()
(Python “<
” 运算符):
>>> print(column("x") < 5) x < :x_1
ColumnOperators.__ge__()
(Python “>=
” 运算符):
>>> print(column("x") >= 5) x >= :x_1
ColumnOperators.__le__()
(Python “<=
” 运算符):
>>> print(column("x") <= 5) x <= :x_1
ColumnOperators.between()
:
>>> print(column("x").between(5, 10)) x BETWEEN :x_1 AND :x_2
IN 比较
SQL IN 运算符是 SQLAlchemy 中的一个主题。 由于 IN 运算符通常针对一组固定值使用,因此 SQLAlchemy 的绑定参数 coercion 功能利用了特殊形式的 SQL 编译,将中间 SQL 字符串渲染为最终绑定参数列表,然后在第二步形成。 换句话说,“它只是工作”。
针对一组值的 IN
通常通过将值列表传递给 ColumnOperators.in_()
方法来实现 IN:
>>> print(column("x").in_([1, 2, 3])) x IN (__[POSTCOMPILE_x_1])
特殊的绑定形式__[POSTCOMPILE
在执行时被渲染为单独的参数,如下所示:
>>> stmt = select(User.id).where(User.id.in_([1, 2, 3])) >>> result = conn.execute(stmt) SELECT user_account.id FROM user_account WHERE user_account.id IN (?, ?, ?) [...] (1, 2, 3)
空 IN 表达式
SQLAlchemy 通过渲染一个返回零行的特定于后端的子查询来为空 IN 表达式产生数学上有效的结果。 再换句话说,“它只是工作”:
>>> stmt = select(User.id).where(User.id.in_([])) >>> result = conn.execute(stmt) SELECT user_account.id FROM user_account WHERE user_account.id IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1) [...] ()
上面的“空集”子查询正确地进行了概括,并且还以保持不变的 IN 运算符形式呈现。
NOT IN
“NOT IN”可通过ColumnOperators.not_in()
运算符获得:
>>> print(column("x").not_in([1, 2, 3])) (x NOT IN (__[POSTCOMPILE_x_1]))
通常,通过~
运算符否定更容易实现:
>>> print(~column("x").in_([1, 2, 3])) (x NOT IN (__[POSTCOMPILE_x_1]))
元组 IN 表达式
使用 IN 与元组进行元组比较是常见的,因为在其他用例中,它可以适应将行匹配到一组潜在的复合主键值的情况。 tuple_()
构造提供了元组比较的基本构建块。 Tuple.in_()
运算符然后接收元组列表:
>>> from sqlalchemy import tuple_ >>> tup = tuple_(column("x", Integer), column("y", Integer)) >>> expr = tup.in_([(1, 2), (3, 4)]) >>> print(expr) (x, y) IN (__[POSTCOMPILE_param_1])
为了说明渲染的参数:
>>> tup = tuple_(User.id, Address.id) >>> stmt = select(User.name).join(Address).where(tup.in_([(1, 1), (2, 2)])) >>> conn.execute(stmt).all() SELECT user_account.name FROM user_account JOIN address ON user_account.id = address.user_id WHERE (user_account.id, address.id) IN (VALUES (?, ?), (?, ?)) [...] (1, 1, 2, 2) [('spongebob',), ('sandy',)]
子查询 IN
最后,ColumnOperators.in_()
和 ColumnOperators.not_in()
运算符与子查询一起使用。 这种形式提供了直接传递 Select
构造的方法,无需任何显式转换为命名子查询:
>>> print(column("x").in_(select(user_table.c.id))) x IN (SELECT user_account.id FROM user_account)
元组按预期工作:
>>> print( ... tuple_(column("x"), column("y")).in_( ... select(user_table.c.id, address_table.c.id).join(address_table) ... ) ... ) (x, y) IN (SELECT user_account.id, address.id FROM user_account JOIN address ON user_account.id = address.user_id)
身份比较
这些运算符涉及测试特殊的 SQL 值,如NULL
,一些数据库支持的布尔常量,如true
或false
:
ColumnOperators.is_()
:
此运算符将为“x IS y”提供确切的 SQL,最常见的是“ IS NULL”。 使用常规 PythonNone
最容易获得NULL
常量:
>>> print(column("x").is_(None)) x IS NULL
- 如果需要,SQL NULL 也可以显式使用
null()
构造:
>>> from sqlalchemy import null >>> print(column("x").is_(null())) x IS NULL
- 当使用
ColumnOperators.__eq__()
重载运算符,即==
,与None
或null()
值一起使用时,ColumnOperators.is_()
运算符会自动调用。因此,通常不需要显式使用ColumnOperators.is_()
,特别是在与动态值一起使用时:
>>> a = None >>> print(column("x") == a) x IS NULL
- 注意,Python 的
is
运算符没有被重载。尽管 Python 提供了重载运算符如==
和!=
的钩子,但它没有提供任何重新定义is
的方法。 ColumnOperators.is_not()
:
类似于ColumnOperators.is_()
,生成“IS NOT”:
>>> print(column("x").is_not(None)) x IS NOT NULL
- 等同于
!= None
:
>>> print(column("x") != None) x IS NOT NULL
ColumnOperators.is_distinct_from()
:
生成 SQL IS DISTINCT FROM:
>>> print(column("x").is_distinct_from("some value")) x IS DISTINCT FROM :x_1
ColumnOperators.isnot_distinct_from()
:
生成 SQL IS NOT DISTINCT FROM:
>>> print(column("x").isnot_distinct_from("some value")) x IS NOT DISTINCT FROM :x_1
字符串比较:
ColumnOperators.like()
:
>>> print(column("x").like("word")) x LIKE :x_1
ColumnOperators.ilike()
:
大小写不敏感的 LIKE 使用通用后端上的 SQLlower()
函数。在 PostgreSQL 后端上,它将使用ILIKE
:
>>> print(column("x").ilike("word")) lower(x) LIKE lower(:x_1)
ColumnOperators.notlike()
:
>>> print(column("x").notlike("word")) x NOT LIKE :x_1
ColumnOperators.notilike()
:
>>> print(column("x").notilike("word")) lower(x) NOT LIKE lower(:x_1)
字符串包含:
字符串包含运算符基本上是由 LIKE 和字符串连接运算符组合而成,大多数后端使用||
,有时候也会使用像concat()
这样的函数:
ColumnOperators.startswith()
:
>>> print(column("x").startswith("word")) x LIKE :x_1 || '%'
ColumnOperators.endswith()
:
>>> print(column("x").endswith("word")) x LIKE '%' || :x_1
ColumnOperators.contains()
:
>>> print(column("x").contains("word")) x LIKE '%' || :x_1 || '%'
字符串匹配
匹配运算符始终是特定于后端的,并且在不同数据库上可能提供不同的行为和结果:
ColumnOperators.match()
:
这是一种方言特定的运算符,如果底层数据库支持 MATCH 功能,则使用它:
>>> print(column("x").match("word")) x MATCH :x_1
ColumnOperators.regexp_match()
:
此运算符是方言特定的。我们可以用 PostgreSQL 方言举例说明:
>>> from sqlalchemy.dialects import postgresql >>> print(column("x").regexp_match("word").compile(dialect=postgresql.dialect())) x ~ %(x_1)s
- 或 MySQL:
>>> from sqlalchemy.dialects import mysql >>> print(column("x").regexp_match("word").compile(dialect=mysql.dialect())) x REGEXP %s
字符串改动
ColumnOperators.concat()
:
字符串连接:
>>> print(column("x").concat("some string")) x || :x_1
- 此运算符通过
ColumnOperators.__add__()
可用,即,当使用从String
派生的列表达式时,Python+
运算符:
>>> print(column("x", String) + "some string") x || :x_1
- 此运算符将产生适当的特定于数据库的构造,例如在 MySQL 上,它历来是
concat()
SQL 函数:
>>> print((column("x", String) + "some string").compile(dialect=mysql.dialect())) concat(x, %s)
ColumnOperators.regexp_replace()
:
与ColumnOperators.regexp()
互补,这产生了支持它的后端的 REGEXP REPLACE 等效项:
>>> print(column("x").regexp_replace("foo", "bar").compile(dialect=postgresql.dialect())) REGEXP_REPLACE(x, %(x_1)s, %(x_2)s)
ColumnOperators.collate()
:
产生 COLLATE SQL 运算符,为表达式提供特定的排序规则:
>>> print( ... (column("x").collate("latin1_german2_ci") == "Müller").compile( ... dialect=mysql.dialect() ... ) ... ) (x COLLATE latin1_german2_ci) = %s
- 要对字面值使用 COLLATE,使用
literal()
构造:
>>> from sqlalchemy import literal >>> print( ... (literal("Müller").collate("latin1_german2_ci") == column("x")).compile( ... dialect=mysql.dialect() ... ) ... ) (%s COLLATE latin1_german2_ci) = x
算术运算符
ColumnOperators.__add__()
,ColumnOperators.__radd__()
(Python “+
” 运算符):
>>> print(column("x") + 5) x + :x_1 >>> print(5 + column("x")) :x_1 + x
- 请注意,当表达式的数据类型是
String
或类似类型时,ColumnOperators.__add__()
运算符会产生 字符串连接: ColumnOperators.__sub__()
,ColumnOperators.__rsub__()
(Python “-
” 运算符):
>>> print(column("x") - 5) x - :x_1 >>> print(5 - column("x")) :x_1 - x
ColumnOperators.__mul__()
,ColumnOperators.__rmul__()
(Python “*
” 运算符):
>>> print(column("x") * 5) x * :x_1 >>> print(5 * column("x")) :x_1 * x
ColumnOperators.__truediv__()
,ColumnOperators.__rtruediv__()
(Python “/
” 运算符)。这是 Python 的truediv
运算符,它将确保进行整数真除法:
>>> print(column("x") / 5) x / CAST(:x_1 AS NUMERIC) >>> print(5 / column("x")) :x_1 / CAST(x AS NUMERIC)
- 从版本 2.0 起更改:Python 的
/
运算符现在确保进行整数真除法。 ColumnOperators.__floordiv__()
,ColumnOperators.__rfloordiv__()
(Python “//
” 运算符)。这是 Python 的floordiv
运算符,它将确保进行地板除法。对于默认后端以及诸如 PostgreSQL 之类的后端,SQL/
运算符通常以这种方式处理整数值:
>>> print(column("x") // 5) x / :x_1 >>> print(5 // column("x", Integer)) :x_1 / x
- 对于默认不使用地板除法的后端,或者当与数字值一起使用时,使用 FLOOR() 函数以确保地板除法:
>>> print(column("x") // 5.5) FLOOR(x / :x_1) >>> print(5 // column("x", Numeric)) FLOOR(:x_1 / x)
- 版本 2.0 中新增:支持地板除法
ColumnOperators.__mod__()
,ColumnOperators.__rmod__()
(Python “%
” 运算符):
>>> print(column("x") % 5) x % :x_1 >>> print(5 % column("x")) :x_1 % x
位运算符
位运算符函数提供了对不同后端的位运算符的统一访问,这些后端预期在兼容值(例如整数和位字符串,如 PostgreSQL BIT
等)上进行操作。请注意,这些不是通用布尔运算符。
版本 2.0.2 中新增:添加了专用于位运算的运算符。
ColumnOperators.bitwise_not()
,bitwise_not()
。作为一个列级方法可用,针对父对象产生按位 NOT 子句:
>>> print(column("x").bitwise_not()) ~x
- 这个操作符也作为列表达式级方法可用,将按位 NOT 应用于单个列表达式:
>>> from sqlalchemy import bitwise_not >>> print(bitwise_not(column("x"))) ~x
ColumnOperators.bitwise_and()
产生按位与:
>>> print(column("x").bitwise_and(5)) x & :x_1
ColumnOperators.bitwise_or()
产生按位或:
>>> print(column("x").bitwise_or(5)) x | :x_1
ColumnOperators.bitwise_xor()
产生按位异或:
>>> print(column("x").bitwise_xor(5)) x ^ :x_1
- 对于 PostgreSQL 方言,“#” 被用来表示按位异或;当使用这些后端之一时,它会自动发出:
>>> from sqlalchemy.dialects import postgresql >>> print(column("x").bitwise_xor(5).compile(dialect=postgresql.dialect())) x # %(x_1)s
ColumnOperators.bitwise_rshift()
,ColumnOperators.bitwise_lshift()
产生按位移动操作符:
>>> print(column("x").bitwise_rshift(5)) x >> :x_1 >>> print(column("x").bitwise_lshift(5)) x << :x_1
使用连接词和否定词
最常见的连接词 “AND”,如果我们重复使用 Select.where()
方法,以及类似的方法如 Update.where()
和 Delete.where()
,则会自动应用:
>>> print( ... select(address_table.c.email_address) ... .where(user_table.c.name == "squidward") ... .where(address_table.c.user_id == user_table.c.id) ... ) SELECT address.email_address FROM address, user_account WHERE user_account.name = :name_1 AND address.user_id = user_account.id
Select.where()
,Update.where()
和 Delete.where()
也接受具有相同效果的多个表达式:
>>> print( ... select(address_table.c.email_address).where( ... user_table.c.name == "squidward", ... address_table.c.user_id == user_table.c.id, ... ) ... ) SELECT address.email_address FROM address, user_account WHERE user_account.name = :name_1 AND address.user_id = user_account.id
“AND” 连接词以及其伴侣 “OR”,都可以直接使用 and_()
和 or_()
函数获得:
>>> from sqlalchemy import and_, or_ >>> print( ... select(address_table.c.email_address).where( ... and_( ... or_(user_table.c.name == "squidward", user_table.c.name == "sandy"), ... address_table.c.user_id == user_table.c.id, ... ) ... ) ... ) SELECT address.email_address FROM address, user_account WHERE (user_account.name = :name_1 OR user_account.name = :name_2) AND address.user_id = user_account.id
使用 not_()
函数可得到否定。这通常会反转布尔表达式中的操作符:
>>> from sqlalchemy import not_ >>> print(not_(column("x") == 5)) x != :x_1
当适用时,也可以应用关键词如 NOT
:
>>> from sqlalchemy import Boolean >>> print(not_(column("x", Boolean))) NOT x
逻辑与运算符
上述逻辑连接函数and_()
, or_()
, not_()
也可以作为 Python 运算符进行重载:
注意
Python 中的&
、|
和~
运算符在语言中具有高优先级;因此,通常必须为包含表达式的操作数应用括号,如下面的示例所示。
Operators.__and__()
(Python “&
” operator):
Python 二进制&
运算符被重载,以与and_()
相同(请注意两个操作数周围的括号):
>>> print((column("x") == 5) & (column("y") == 10)) x = :x_1 AND y = :y_1
Operators.__or__()
(Python “|
” operator):
Python 二进制|
运算符被重载,以与or_()
相同(请注意两个操作数周围的括号):
>>> print((column("x") == 5) | (column("y") == 10)) x = :x_1 OR y = :y_1
Operators.__invert__()
(Python “~
” operator):
Python 二进制~
运算符被重载,以与not_()
相同,可以反转现有运算符,或将NOT
关键字应用于整个表达式:
>>> print(~(column("x") == 5)) x != :x_1 >>> from sqlalchemy import Boolean >>> print(~column("x", Boolean)) NOT x
比较运算符
基本比较适用于许多数据类型,包括数字、字符串、日期等:
ColumnOperators.__eq__()
(Python “==
” operator):
>>> print(column("x") == 5) x = :x_1
ColumnOperators.__ne__()
(Python “!=
” operator):
>>> print(column("x") != 5) x != :x_1
ColumnOperators.__gt__()
(Python “>
” operator):
>>> print(column("x") > 5) x > :x_1
ColumnOperators.__lt__()
(Python “<
” operator):
>>> print(column("x") < 5) x < :x_1
ColumnOperators.__ge__()
(Python “>=
” operator):
>>> print(column("x") >= 5) x >= :x_1
ColumnOperators.__le__()
(Python “<=
” operator):
>>> print(column("x") <= 5) x <= :x_1
ColumnOperators.between()
:
>>> print(column("x").between(5, 10)) x BETWEEN :x_1 AND :x_2
IN 比较
SQL 的 IN 操作符在 SQLAlchemy 中是一个单独的主题。由于 IN 操作符通常针对一组固定值使用,SQLAlchemy 的绑定参数强制转换特性利用一种特殊形式的 SQL 编译,在第二步形成最终的绑定参数列表。换句话说,“它就是这样工作”。
针对值列表的 IN
通过将值列表传递给 ColumnOperators.in_()
方法,通常可以使用 IN:
>>> print(column("x").in_([1, 2, 3])) x IN (__[POSTCOMPILE_x_1])
特殊的绑定形式 __[POSTCOMPILE
在执行时被渲染为单独的参数,如下所示:
>>> stmt = select(User.id).where(User.id.in_([1, 2, 3])) >>> result = conn.execute(stmt) SELECT user_account.id FROM user_account WHERE user_account.id IN (?, ?, ?) [...] (1, 2, 3)
空的 IN 表达式
SQLAlchemy 通过渲染一个特定于后端的子查询返回没有行的有效数学结果,从而为空的 IN 表达式生成一个中间值。换句话说,“它就是这样工作”:
>>> stmt = select(User.id).where(User.id.in_([])) >>> result = conn.execute(stmt) SELECT user_account.id FROM user_account WHERE user_account.id IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1) [...] ()
上述的“空集合”子查询正确地泛化,并且也是以 IN 操作符的形式呈现的,该操作符保持不变。
NOT IN
“NOT IN” 可通过 ColumnOperators.not_in()
运算符使用:
>>> print(column("x").not_in([1, 2, 3])) (x NOT IN (__[POSTCOMPILE_x_1]))
通常通过使用 ~
运算符进行否定更容易:
>>> print(~column("x").in_([1, 2, 3])) (x NOT IN (__[POSTCOMPILE_x_1]))
元组 IN 表达式
使用 IN 与元组比较是常见的,除了其他用例外,它适应了将行匹配到一组潜在的复合主键值的情况。tuple_()
构造提供了元组比较的基本构建块。然后 Tuple.in_()
运算符接收一个元组列表:
>>> from sqlalchemy import tuple_ >>> tup = tuple_(column("x", Integer), column("y", Integer)) >>> expr = tup.in_([(1, 2), (3, 4)]) >>> print(expr) (x, y) IN (__[POSTCOMPILE_param_1])
为了说明渲染的参数:
>>> tup = tuple_(User.id, Address.id) >>> stmt = select(User.name).join(Address).where(tup.in_([(1, 1), (2, 2)])) >>> conn.execute(stmt).all() SELECT user_account.name FROM user_account JOIN address ON user_account.id = address.user_id WHERE (user_account.id, address.id) IN (VALUES (?, ?), (?, ?)) [...] (1, 1, 2, 2) [('spongebob',), ('sandy',)]
子查询 IN
最后,ColumnOperators.in_()
和 ColumnOperators.not_in()
运算符与子查询一起使用。该形式允许直接传递 Select
构造,无需明确转换为命名子查询:
>>> print(column("x").in_(select(user_table.c.id))) x IN (SELECT user_account.id FROM user_account)
元组按预期工作:
>>> print( ... tuple_(column("x"), column("y")).in_( ... select(user_table.c.id, address_table.c.id).join(address_table) ... ) ... ) (x, y) IN (SELECT user_account.id, address.id FROM user_account JOIN address ON user_account.id = address.user_id)
针对值列表的 IN
通过将值列表传递给 ColumnOperators.in_()
方法,通常可以使用 IN:
>>> print(column("x").in_([1, 2, 3])) x IN (__[POSTCOMPILE_x_1])
特殊的绑定形式 __[POSTCOMPILE
在执行时被渲染为单独的参数,如下所示:
>>> stmt = select(User.id).where(User.id.in_([1, 2, 3])) >>> result = conn.execute(stmt) SELECT user_account.id FROM user_account WHERE user_account.id IN (?, ?, ?) [...] (1, 2, 3)
空的 IN 表达式
SQLAlchemy 通过渲染一个特定于后端的子查询来为空 IN 表达式生成一个数学上有效的结果,该子查询不返回任何行。换句话说,“它只是有效地工作”:
>>> stmt = select(User.id).where(User.id.in_([])) >>> result = conn.execute(stmt) SELECT user_account.id FROM user_account WHERE user_account.id IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1) [...] ()
上述“空集”子查询正确地进行了泛化,并且也以 IN 操作符的形式呈现在原位。
NOT IN
“NOT IN” 可通过ColumnOperators.not_in()
操作符获得:
>>> print(column("x").not_in([1, 2, 3])) (x NOT IN (__[POSTCOMPILE_x_1]))
通常通过使用~
操作符进行否定更容易获得:
>>> print(~column("x").in_([1, 2, 3])) (x NOT IN (__[POSTCOMPILE_x_1]))
元组 IN 表达式
使用 IN 进行元组与元组的比较很常见,因为除了其他用例外,还适用于将匹配行与一组潜在的复合主键值进行匹配的情况。tuple_()
构造提供了元组比较的基本构建块。然后Tuple.in_()
操作符接收一个元组列表:
>>> from sqlalchemy import tuple_ >>> tup = tuple_(column("x", Integer), column("y", Integer)) >>> expr = tup.in_([(1, 2), (3, 4)]) >>> print(expr) (x, y) IN (__[POSTCOMPILE_param_1])
渲染参数的示例:
>>> tup = tuple_(User.id, Address.id) >>> stmt = select(User.name).join(Address).where(tup.in_([(1, 1), (2, 2)])) >>> conn.execute(stmt).all() SELECT user_account.name FROM user_account JOIN address ON user_account.id = address.user_id WHERE (user_account.id, address.id) IN (VALUES (?, ?), (?, ?)) [...] (1, 1, 2, 2) [('spongebob',), ('sandy',)]
子查询 IN
最后,ColumnOperators.in_()
和 ColumnOperators.not_in()
操作符与子查询一起使用。该形式提供了直接传入Select
构造的方式,无需明确转换为命名子查询:
>>> print(column("x").in_(select(user_table.c.id))) x IN (SELECT user_account.id FROM user_account)
元组按预期工作:
>>> print( ... tuple_(column("x"), column("y")).in_( ... select(user_table.c.id, address_table.c.id).join(address_table) ... ) ... ) (x, y) IN (SELECT user_account.id, address.id FROM user_account JOIN address ON user_account.id = address.user_id)
身份比较
这些操作符涉及测试特殊的 SQL 值,如NULL
,一些数据库支持的布尔常量,如true
或false
:
ColumnOperators.is_()
:
该操作符将提供“x IS y”的确切 SQL,通常表示为“ IS NULL”。使用常规的 PythonNone
最容易获得NULL
常量:
>>> print(column("x").is_(None)) x IS NULL
- 如果需要,SQL NULL 也可以明确使用
null()
构造获得:
>>> from sqlalchemy import null >>> print(column("x").is_(null())) x IS NULL
- 当使用
ColumnOperators.__eq__()
重载的操作符,即==
,与None
或null()
值一起使用时,ColumnOperators.is_()
操作符会自动调用。因此,通常不需要显式使用ColumnOperators.is_()
,特别是在与动态值一起使用时:
>>> a = None >>> print(column("x") == a) x IS NULL
- 请注意,Python 的
is
运算符未被重载。即使 Python 提供了像==
和!=
这样的运算符重载钩子,它也没有提供任何重新定义is
的方法。 ColumnOperators.is_not()
:
类似于ColumnOperators.is_()
,生成“IS NOT”:
>>> print(column("x").is_not(None)) x IS NOT NULL
- 同样等价于
!= None
:
>>> print(column("x") != None) x IS NOT NULL
ColumnOperators.is_distinct_from()
:
生成 SQL IS DISTINCT FROM:
>>> print(column("x").is_distinct_from("some value")) x IS DISTINCT FROM :x_1
ColumnOperators.isnot_distinct_from()
:
生成 SQL IS NOT DISTINCT FROM:
>>> print(column("x").isnot_distinct_from("some value")) x IS NOT DISTINCT FROM :x_1
字符串比较
ColumnOperators.like()
:
>>> print(column("x").like("word")) x LIKE :x_1
ColumnOperators.ilike()
:
不区分大小写的 LIKE 在通用后端上使用 SQLlower()
函数。在 PostgreSQL 后端上,它将使用ILIKE
:
>>> print(column("x").ilike("word")) lower(x) LIKE lower(:x_1)
ColumnOperators.notlike()
:
>>> print(column("x").notlike("word")) x NOT LIKE :x_1
ColumnOperators.notilike()
:
>>> print(column("x").notilike("word")) lower(x) NOT LIKE lower(:x_1)
字符串包含
字符串包含运算符基本上是由 LIKE 和字符串连接运算符构建的,后端上为 ||
或者有时是像 concat()
这样的函数:
ColumnOperators.startswith()
:
>>> print(column("x").startswith("word")) x LIKE :x_1 || '%'
ColumnOperators.endswith()
:
>>> print(column("x").endswith("word")) x LIKE '%' || :x_1
ColumnOperators.contains()
:
>>> print(column("x").contains("word")) x LIKE '%' || :x_1 || '%'
字符串匹配
匹配运算符始终是特定于后端的,可能在不同的数据库上提供不同的行为和结果:
ColumnOperators.match()
:
这是一个特定于方言的运算符,如果底层数据库支持 MATCH 特性,则使用它:
>>> print(column("x").match("word")) x MATCH :x_1
ColumnOperators.regexp_match()
:
此运算符是方言特定的。我们可以用 PostgreSQL 方言举例说明:
>>> from sqlalchemy.dialects import postgresql >>> print(column("x").regexp_match("word").compile(dialect=postgresql.dialect())) x ~ %(x_1)s
- 或者 MySQL:
>>> from sqlalchemy.dialects import mysql >>> print(column("x").regexp_match("word").compile(dialect=mysql.dialect())) x REGEXP %s
字符串修改
ColumnOperators.concat()
:
字符串连接:
>>> print(column("x").concat("some string")) x || :x_1
- 当使用从
String
派生的列表达式时,此运算符可通过ColumnOperators.__add__()
提供,即 Python 的+
运算符:
>>> print(column("x", String) + "some string") x || :x_1
- 该运算符将产生适当的数据库特定结构,例如在 MySQL 上,它历史上一直是
concat()
SQL 函数:
>>> print((column("x", String) + "some string").compile(dialect=mysql.dialect())) concat(x, %s)
ColumnOperators.regexp_replace()
:
与ColumnOperators.regexp()
互补,对于支持的后端,会产生等效的 REGEXP REPLACE:
>>> print(column("x").regexp_replace("foo", "bar").compile(dialect=postgresql.dialect())) REGEXP_REPLACE(x, %(x_1)s, %(x_2)s)
ColumnOperators.collate()
:
生成 COLLATE SQL 运算符,可在表达式时间为特定排序提供支持:
>>> print( ... (column("x").collate("latin1_german2_ci") == "Müller").compile( ... dialect=mysql.dialect() ... ) ... ) (x COLLATE latin1_german2_ci) = %s
- 若要针对字面值使用 COLLATE,请使用
literal()
构造:
>>> from sqlalchemy import literal >>> print( ... (literal("Müller").collate("latin1_german2_ci") == column("x")).compile( ... dialect=mysql.dialect() ... ) ... ) (%s COLLATE latin1_german2_ci) = x
算术运算符
ColumnOperators.__add__()
,ColumnOperators.__radd__()
(Python “+
” 运算符):
>>> print(column("x") + 5) x + :x_1 >>> print(5 + column("x")) :x_1 + x
- 请注意,当表达式的数据类型是
String
或类似时,ColumnOperators.__add__()
运算符会产生字符串连接而不是 字符串连接: ColumnOperators.__sub__()
,ColumnOperators.__rsub__()
(Python “-
” 运算符):
>>> print(column("x") - 5) x - :x_1 >>> print(5 - column("x")) :x_1 - x
ColumnOperators.__mul__()
,ColumnOperators.__rmul__()
(Python “*
” 运算符):
>>> print(column("x") * 5) x * :x_1 >>> print(5 * column("x")) :x_1 * x
ColumnOperators.__truediv__()
,ColumnOperators.__rtruediv__()
(Python “/
” 运算符)。这是 Python 的truediv
运算符,它确保进行整数真除法:
>>> print(column("x") / 5) x / CAST(:x_1 AS NUMERIC) >>> print(5 / column("x")) :x_1 / CAST(x AS NUMERIC)
- 在 2.0 版本中更改:Python
/
运算符现在确保进行整数真除法 ColumnOperators.__floordiv__()
,ColumnOperators.__rfloordiv__()
(Python “//
” 运算符)。这是 Python 的floordiv
运算符,它确保进行 floor division。对于默认后端以及诸如 PostgreSQL 这样的后端,SQL/
运算符通常以这种方式对整数值进行操作:
>>> print(column("x") // 5) x / :x_1 >>> print(5 // column("x", Integer)) :x_1 / x
- 对于默认不使用 floor division 的后端,或者与数值一起使用时,使用 FLOOR() 函数来确保进行 floor division:
>>> print(column("x") // 5.5) FLOOR(x / :x_1) >>> print(5 // column("x", Numeric)) FLOOR(:x_1 / x)
- 2.0 版本中的新功能:支持 FLOOR division
ColumnOperators.__mod__()
,ColumnOperators.__rmod__()
(Python “%
” 运算符):
>>> print(column("x") % 5) x % :x_1 >>> print(5 % column("x")) :x_1 % x
按位运算符
按位运算符函数提供了对不同后端的位运算符的统一访问,这些后端预计将对兼容的值(例如整数和位字符串,例如 PostgreSQL BIT
和类似的)进行操作。请注意,这些不是通用布尔运算符。
2.0.2 版本中的新功能:添加了专用位运算符。
ColumnOperators.bitwise_not()
,bitwise_not()
。作为列级方法可用,对父对象生成按位 NOT 子句:
>>> print(column("x").bitwise_not()) ~x
- 这个运算符也作为列表达式级别的方法可用,对单个列表达式应用按位 NOT:
>>> from sqlalchemy import bitwise_not >>> print(bitwise_not(column("x"))) ~x
ColumnOperators.bitwise_and()
产生按位与:
>>> print(column("x").bitwise_and(5)) x & :x_1
ColumnOperators.bitwise_or()
产生按位 OR:
>>> print(column("x").bitwise_or(5)) x | :x_1
ColumnOperators.bitwise_xor()
产生按位异或操作符:
>>> print(column("x").bitwise_xor(5)) x ^ :x_1
- 对于 PostgreSQL 方言,“#” 用于表示按位异或;在使用其中一个后端时会自动发出:
>>> from sqlalchemy.dialects import postgresql >>> print(column("x").bitwise_xor(5).compile(dialect=postgresql.dialect())) x # %(x_1)s
ColumnOperators.bitwise_rshift()
,ColumnOperators.bitwise_lshift()
产生按位移动操作符:
>>> print(column("x").bitwise_rshift(5)) x >> :x_1 >>> print(column("x").bitwise_lshift(5)) x << :x_1
使用连接词和否定
如果我们反复使用 Select.where()
方法,以及类似的方法如 Update.where()
和 Delete.where()
,最常见的连接词“AND”会自动应用:
>>> print( ... select(address_table.c.email_address) ... .where(user_table.c.name == "squidward") ... .where(address_table.c.user_id == user_table.c.id) ... ) SELECT address.email_address FROM address, user_account WHERE user_account.name = :name_1 AND address.user_id = user_account.id
Select.where()
、Update.where()
和 Delete.where()
也接受具有相同效果的多个表达式:
>>> print( ... select(address_table.c.email_address).where( ... user_table.c.name == "squidward", ... address_table.c.user_id == user_table.c.id, ... ) ... ) SELECT address.email_address FROM address, user_account WHERE user_account.name = :name_1 AND address.user_id = user_account.id
“AND” 连接词以及其伴侣“OR”可以直接使用 and_()
和 or_()
函数:
>>> from sqlalchemy import and_, or_ >>> print( ... select(address_table.c.email_address).where( ... and_( ... or_(user_table.c.name == "squidward", user_table.c.name == "sandy"), ... address_table.c.user_id == user_table.c.id, ... ) ... ) ... ) SELECT address.email_address FROM address, user_account WHERE (user_account.name = :name_1 OR user_account.name = :name_2) AND address.user_id = user_account.id
使用 not_()
函数可进行否定。这通常会反转布尔表达式中的运算符:
>>> from sqlalchemy import not_ >>> print(not_(column("x") == 5)) x != :x_1
在适当时还可以应��关键字,如 NOT
:
>>> from sqlalchemy import Boolean >>> print(not_(column("x", Boolean))) NOT x
连接操作符
上述连接函数 and_()
、or_()
、not_()
也可作为 Python 中的重载运算符使用:
注意
Python 中的 &
、|
和 ~
操作符在语言中具有高优先级;因此,通常需要为包含表达式的操作数应用括号,如下面的示例所示。
Operators.__and__()
(Python “&
” 操作符):
Python 的二进制&
运算符被重载,以与and_()
(注意两个操作数周围的括号)行为相同:
>>> print((column("x") == 5) & (column("y") == 10)) x = :x_1 AND y = :y_1
Operators.__or__()
(Python “|
” operator):
Python 的二进制|
运算符被重载,以与or_()
(注意两个操作数周围的括号)行为相同:
>>> print((column("x") == 5) | (column("y") == 10)) x = :x_1 OR y = :y_1
Operators.__invert__()
(Python “~
” operator):
Python 的二进制~
运算符被重载,以与not_()
行为相同,可以反转现有运算符,或将NOT
关键字应用于整个表达式:
>>> print(~(column("x") == 5)) x != :x_1 >>> from sqlalchemy import Boolean >>> print(~column("x", Boolean)) NOT x
SELECT 及相关构造
术语“可选择的”指代任何代表数据库行的对象。在 SQLAlchemy 中,这些对象都是 Selectable
的子类,其中最突出的是 Select
,它表示一个 SQL SELECT 语句。Selectable
的一个子集是 FromClause
,它表示可以在 Select
语句的 FROM 子句中的对象。FromClause
的一个区别性特征是 FromClause.c
属性,它是 FROM 子句中包含的所有列的命名空间(这些元素本身是 ColumnElement
的子类)。
可选择的基本构造
最高级的“FROM 子句”和“SELECT”构造器。
对象名称 | 描述 |
except_(*selects) | 返回多个可选项的 EXCEPT 。 |
except_all(*selects) | 返回多个可选项的 EXCEPT ALL 。 |
exists([__argument]) | 构造一个新的 Exists 构造。 |
intersect(*selects) | 返回多个可选项的 INTERSECT 。 |
intersect_all(*selects) | 返回多个可选项的 INTERSECT ALL 。 |
select(*entities, **__kw) | 构造一个新的 Select 。 |
table(name, *columns, **kw) | 生成一个新的 TableClause 。 |
union(*selects) | 返回多个可选项的 UNION 。 |
union_all(*selects) | 返回多个可选项的 UNION ALL 。 |
values(*columns, [name, literal_binds]) | 构造一个 Values 构造。 |
function sqlalchemy.sql.expression.except_(*selects: _SelectStatementForCompoundArgument) → CompoundSelect
返回多个可选项的 EXCEPT
。
返回的对象是一个CompoundSelect
的实例。
参数:
*selects – 一个Select
实例的列表。
function sqlalchemy.sql.expression.except_all(*selects: _SelectStatementForCompoundArgument) → CompoundSelect
返回多个可选择的EXCEPT ALL
。
返回的对象是一个CompoundSelect
的实例。
参数:
*selects – 一个Select
实例的列表。
function sqlalchemy.sql.expression.exists(__argument: _ColumnsClauseArgument[Any] | SelectBase | ScalarSelect[Any] | None = None) → Exists
构建一个新的Exists
构造。
exists()
可以单独调用以生成一个Exists
构造,该构造将接受简单的 WHERE 条件:
exists_criteria = exists().where(table1.c.col1 == table2.c.col2)
然而,为了在构建 SELECT 时具有更大的灵活性,可以将现有的Select
构造转换为Exists
,最方便的方法是利用SelectBase.exists()
方法:
exists_criteria = ( select(table2.c.col2). where(table1.c.col1 == table2.c.col2). exists() )
EXISTS 条件然后在封闭的 SELECT 中使用:
stmt = select(table1.c.col1).where(exists_criteria)
上述语句将如下形式:
SELECT col1 FROM table1 WHERE EXISTS (SELECT table2.col2 FROM table2 WHERE table2.col2 = table1.col1)
另请参阅
EXISTS 子查询 - 在 2.0 风格教程中。
SelectBase.exists()
- 将SELECT
转换为EXISTS
子句的方法。
function sqlalchemy.sql.expression.intersect(*selects: _SelectStatementForCompoundArgument) → CompoundSelect
返回多个可选择的INTERSECT
。
返回的对象是一个CompoundSelect
的实例。
参数:
*selects – 一个Select
实例的列表。
function sqlalchemy.sql.expression.intersect_all(*selects: _SelectStatementForCompoundArgument) → CompoundSelect
返回多个可选择的INTERSECT ALL
。
返回的对象是一个CompoundSelect
的实例。
参数:
*selects – 一个Select
实例的列表。
function sqlalchemy.sql.expression.select(*entities: _ColumnsClauseArgument[Any], **__kw: Any) → Select[Any]
构建一个新的Select
。
新版本 1.4 中:- select()
函数现在可以按位置接受列参数。顶层的select()
函数将根据传入的参数自动使用 1.x 或 2.x 风格的 API;使用来自sqlalchemy.future
模块的select()
将强制使用仅使用 2.x 风格的构造函数。
类似的功能也可通过任何FromClause
上的FromClause.select()
方法获得。
另请参阅
使用 SELECT 语句 - 在 SQLAlchemy 统一教程中
参数:
*entities –
要从中选择的实体。对于核心用法,这通常是一系列将形成结果语句的列子句的ColumnElement
和/或FromClause
对象。对于那些是FromClause
的实例的对象(通常是Table
或Alias
对象),FromClause.c
集合被提取出来形成ColumnElement
对象的集合。
此参数还将接受TextClause
构造,以及 ORM 映射的类。
function sqlalchemy.sql.expression.table(name: str, *columns: ColumnClause[Any], **kw: Any) → TableClause
创建一个新的TableClause
。
返回的对象是TableClause
的一个实例,它表示架构级别的Table
对象的“句法”部分。它可用于构建轻量级的表构造。
参数:
name
– 表的名称。columns
– 一个column()
构造的集合。schema
–
此表的架构名称。
新版本 1.3.18 中:table()
现在可以接受一个schema
参数。
function sqlalchemy.sql.expression.union(*selects: _SelectStatementForCompoundArgument) → CompoundSelect
返回多个可选择的UNION
。
返回的对象是CompoundSelect
的一个实例。
所有FromClause
子类上都有一个类似的union()
方法。
参数:
*selects
– 一个Select
实例列表。**kwargs
– 可用的关键字参数与select()
的相同。
function sqlalchemy.sql.expression.union_all(*selects: _SelectStatementForCompoundArgument) → CompoundSelect
返回多个可选择的UNION ALL
。
返回的对象是CompoundSelect
的一个实例。
所有FromClause
子类上都有一个类似的union_all()
方法。
参数:
*selects – 一个Select
实例列表。
function sqlalchemy.sql.expression.values(*columns: ColumnClause[Any], name: str | None = None, literal_binds: bool = False) → Values
构建一个Values
构造。
列表达式和Values
的实际数据在两个独立的步骤中给出。构造函数通常接收列表达式,通常作为column()
构造,并且数据通过Values.data()
方法传递为一个列表,可以多次调用以添加更多数据,例如:
from sqlalchemy import column from sqlalchemy import values value_expr = values( column('id', Integer), column('name', String), name="my_values" ).data( [(1, 'name1'), (2, 'name2'), (3, 'name3')] )
参数:
*columns
– 列表达式,通常使用column()
对象组成。name
– 此 VALUES 构造的名称。如果省略,VALUES 构造将在 SQL 表达式中无名。不同的后端可能对此有不同的要求。literal_binds
– 默认为 False。是否在 SQL 输出中内联呈现数据值,而不是使用绑定参数。## 可选择修饰符构造函数
此处列出的函数通常作为FromClause
和Selectable
元素的方法更常见,例如,alias()
函数通常通过FromClause.alias()
方法调用。
对象名称 | 描述 |
alias(selectable[, name, flat]) | 返回给定FromClause 的命名别名。 |
cte(selectable[, name, recursive]) | 返回一个新的 CTE ,或者公共表达式实例。 |
join(left, right[, onclause, isouter, …]) | 生成一个给定两个FromClause 表达式的Join 对象。 |
lateral(selectable[, name]) | 返回一个Lateral 对象。 |
outerjoin(left, right[, onclause, full]) | 返回一个 OUTER JOIN 子句元素。 |
tablesample(selectable, sampling[, name, seed]) | 返回一个TableSample 对象。 |
function sqlalchemy.sql.expression.alias(selectable: FromClause, name: str | None = None, flat: bool = False) → NamedFromClause
返回给定FromClause
的命名别名。
对于Table
和Join
对象,返回类型为Alias
对象。其他类型的NamedFromClause
对象可能会针对其他类型的FromClause
对象返回。
命名别名表示任何在 SQL 中分配了替代名称的FromClause
,通常在生成时使用 AS
子句,例如 SELECT * FROM table AS aliasname
。
等效功能可通过FromClause.alias()
方法在所有FromClause
对象上使用。
参数:
selectable
– 任何FromClause
子类,例如表格,选择语句等。name
– 要分配为别名的字符串名称。如果为None
,则将在编译时确定性地生成一个名称。确定性意味着该名称保证与同一语句中使用的其他构造唯一,并且对于同一语句对象的每次连续编译也将是相同的名称。flat
– 如果给定的可选对象是Join
的实例,则将传递给Join.alias()
- 有关详细信息,请参阅Join.alias()
。
function sqlalchemy.sql.expression.cte(selectable: HasCTE, name: str | None = None, recursive: bool = False) → CTE
返回一个新的 CTE
或公共表达式实例。
请参阅 HasCTE.cte()
了解 CTE 用法的详细信息。
function sqlalchemy.sql.expression.join(left: _FromClauseArgument, right: _FromClauseArgument, onclause: _OnClauseArgument | None = None, isouter: bool = False, full: bool = False) → Join
给定两个 FromClause
表达式,生成一个 Join
对象。
例如:
j = join(user_table, address_table, user_table.c.id == address_table.c.user_id) stmt = select(user_table).select_from(j)
将会生成类似的 SQL:
SELECT user.id, user.name FROM user JOIN address ON user.id = address.user_id
类似的功能可在任何 FromClause
对象(例如 Table
)上使用 FromClause.join()
方法。
参数:
left
– 连接的左侧。right
– 连接的右侧;这是任何FromClause
对象,例如Table
对象,也可以是 ORM 映射的类等可选对象。onclause
– 表示连接的 ON 子句的 SQL 表达式。如果保留为None
,FromClause.join()
将尝试根据外键关系连接两个表。isouter
– 如果为 True,则渲染一个 LEFT OUTER JOIN,而不是 JOIN。full
– 如果为 True,则渲染一个 FULL OUTER JOIN,而不是 JOIN。
另请参见
FromClause.join()
- 方法形式,基于给定的左侧。
Join
- 生成的对象类型。
function sqlalchemy.sql.expression.lateral(selectable: SelectBase | _FromClauseArgument, name: str | None = None) → LateralFromClause
返回一个 Lateral
对象。
Lateral
是表示具有 LATERAL 关键字的子查询的 Alias
子类。
LATERAL 子查询的特殊行为是,它出现在封闭 SELECT 的 FROM 子句中,但可以与该 SELECT 的其他 FROM 子句相关联。这是一种特殊情况的子查询,仅受一小部分后端支持,目前支持较新版本的 PostgreSQL。
另请参见
LATERAL 关联 - 使用概述。
function sqlalchemy.sql.expression.outerjoin(left: _FromClauseArgument, right: _FromClauseArgument, onclause: _OnClauseArgument | None = None, full: bool = False) → Join
返回一个 OUTER JOIN
子句元素。
返回的对象是 Join
的实例。
类似的功能也可通过任何 FromClause
上的 FromClause.outerjoin()
方法获得。
参数:
left
– 连接的左侧。right
– 连接的右侧。onclause
– 可选的ON
子句条件,否则会从左侧和右侧之间建立的外键关系中派生。
要将连接链在一起,请使用结果 Join
对象上的 FromClause.join()
或 FromClause.outerjoin()
方法。
function sqlalchemy.sql.expression.tablesample(selectable: _FromClauseArgument, sampling: float | Function[Any], name: str | None = None, seed: roles.ExpressionElementRole[Any] | None = None) → TableSample
返回一个 TableSample
对象。
TableSample
是一个 Alias
子类,表示应用了 TABLESAMPLE 子句的表。 tablesample()
也可从 FromClause
类中通过 FromClause.tablesample()
方法获得。
TABLESAMPLE 子句允许从表中随机选择近似百分比的行。它支持多种采样方法,最常见的是 BERNOULLI 和 SYSTEM。
例如:
from sqlalchemy import func selectable = people.tablesample( func.bernoulli(1), name='alias', seed=func.random()) stmt = select(selectable.c.people_id)
假设 people
有一个列 people_id
,上述语句将呈现为:
SELECT alias.people_id FROM people AS alias TABLESAMPLE bernoulli(:bernoulli_1) REPEATABLE (random())
参数:
sampling
– 一个介于 0 和 100 之间的float
百分比或Function
。name
– 可选别名名称seed
– 任意实值 SQL 表达式。当指定时,还会呈现 REPEATABLE 子句。
可选择的类文档
这里的类是使用 可选择的基础构造函数 和 可选择的修饰符构造函数 列出的构造函数生成的。
对象名称 | 描述 |
别名 | 表示表或可选择的别名(AS)。 |
AliasedReturnsRows | 对表、子查询和其他可选择的别名的基类。 |
CompoundSelect | 形成 UNION , UNION ALL , 和其他基于 SELECT 的集合操作的基础。 |
CTE | 表示公共表达式。 |
Executable | 将ClauseElement 标记为支持执行。 |
Exists | 表示一个EXISTS 子句。 |
FromClause | 表示可在SELECT 语句的FROM 子句中使用的元素。 |
GenerativeSelect | SELECT 语句的基类,可以添加额外的元素。 |
HasCTE | 声明一个类包含 CTE 支持的 Mixin。 |
HasPrefixes | |
HasSuffixes | |
Join | 表示两个FromClause 元素之间的JOIN 构造。 |
Lateral | 表示一个 LATERAL 子查询。 |
ReturnsRows | Core 构造的基类,具有某种可以表示行的列的概念。 |
ScalarSelect | 表示一个标量子查询。 |
ScalarValues | 表示可用作语句中 COLUMN 元素的标量VALUES 构造。 |
Select | 表示一个SELECT 语句。 |
Selectable | 将类标记为可选择。 |
SelectBase | SELECT 语句的基类。 |
Subquery | 表示一个 SELECT 的子查询。 |
TableClause | 表示最小的“表”构造。 |
TableSample | 表示一个 TABLESAMPLE 子句。 |
TableValuedAlias | 对“表值”SQL 函数的别名。 |
TextualSelect | 在TextClause 构造内部包装一个SelectBase 接口。 |
Values | 表示可用作语句中 FROM 元素的VALUES 构造。 |
class sqlalchemy.sql.expression.Alias
表示一个表或可选择的别名(AS)。
表示别名,通常使用AS
关键字(或在某些数据库上不使用关键字,如 Oracle)应用于 SQL 语句中的任何表或子选择。
此对象是从alias()
模块级函数以及所有FromClause
子类上可用的FromClause.alias()
方法构造的。
另请参阅
FromClause.alias()
成员
inherit_cache
类签名
类sqlalchemy.sql.expression.Alias
(sqlalchemy.sql.roles.DMLTableRole
,sqlalchemy.sql.expression.FromClauseAlias
)
attribute inherit_cache: bool | None = True
指示此HasCacheKey
实例是否应使用其直接超类使用的缓存键生成方案。
此属性默认为None
,表示构造尚未考虑是否应该参与缓存;这在功能上等同于将值设置为False
,除了还会发出警告。
如果与此类本地属性而不是其超类相关的属性不会更改对象对应的 SQL,则可以将此标志设置为True
。
另请参阅
启用自定义构造的缓存支持 - 设置第三方或用户定义的 SQL 构造的HasCacheKey.inherit_cache
属性的通用指南。
class sqlalchemy.sql.expression.AliasedReturnsRows
别名对表、子查询和其他可选择项的基类。
成员
description, is_derived_from(), original
类签名
类sqlalchemy.sql.expression.AliasedReturnsRows
(sqlalchemy.sql.expression.NoInit
,sqlalchemy.sql.expression.NamedFromClause
)
attribute description
method is_derived_from(fromclause: FromClause | None) → bool
如果此FromClause
是从给定的FromClause
“派生”的话,则返回True
。
一个例子是表的别名是从该表派生的。
attribute original
适用于引用 Alias.original 的方言的遗留。
class sqlalchemy.sql.expression.CompoundSelect
形成UNION
,UNION ALL
和其他基于 SELECT 的集合操作的基础。
另请参阅
union()
union_all()
intersect()
intersect_all()
except()
except_all()
成员
add_cte(), alias(), as_scalar(), c, corresponding_column(), cte(), execution_options(), exists(), exported_columns, fetch(), get_execution_options(), get_label_style(), group_by(), is_derived_from(), label(), lateral(), limit(), offset(), options(), order_by(), replace_selectable(), scalar_subquery(), select(), selected_columns, self_group(), set_label_style(), slice(), subquery(), with_for_update()
类签名
类sqlalchemy.sql.expression.CompoundSelect
(sqlalchemy.sql.expression.HasCompileState
, sqlalchemy.sql.expression.GenerativeSelect
, sqlalchemy.sql.expression.ExecutableReturnsRows
)
method add_cte(*ctes: CTE, nest_here: bool = False) → Self
继承自 HasCTE.add_cte()
方法的 HasCTE
向此语句添加一个或多个CTE
构造。
此方法将给定的CTE
构造与父语句关联,以便它们将无条件地在最终语句的 WITH 子句中呈现,即使在语句或任何子选择中没有其他地方引用它们。
当设置为 True 时,可选的HasCTE.add_cte.nest_here
参数将使每个给定的CTE
在与此语句直接一起呈现的 WITH 子句中呈现,而不是将其移动到最终呈现语句的顶部,即使此语句作为较大语句中的子查询呈现。
此方法有两个一般用途。一个是嵌入一些用途的 CTE 语句,而不被明确引用,例如将 DML 语句(如 INSERT 或 UPDATE)作为 CTE 内联到可能间接从其结果中获取的主语句中的用例。另一个是提供对应该保持直接呈现的特定一系列 CTE 构造的放置的控制,这些构造可能嵌套在较大语句中。
例如:
from sqlalchemy import table, column, select t = table('t', column('c1'), column('c2')) ins = t.insert().values({"c1": "x", "c2": "y"}).cte() stmt = select(t).add_cte(ins)
将呈现为:
WITH anon_1 AS (INSERT INTO t (c1, c2) VALUES (:param_1, :param_2)) SELECT t.c1, t.c2 FROM t
在上面的示例中,“anon_1” CTE 在 SELECT 语句中未被引用,但仍完成运行 INSERT 语句的任务。
类似地,在与 DML 相关的上下文中,使用 PostgreSQL Insert
构造生成“upsert”:
from sqlalchemy import table, column from sqlalchemy.dialects.postgresql import insert t = table("t", column("c1"), column("c2")) delete_statement_cte = ( t.delete().where(t.c.c1 < 1).cte("deletions") ) insert_stmt = insert(t).values({"c1": 1, "c2": 2}) update_statement = insert_stmt.on_conflict_do_update( index_elements=[t.c.c1], set_={ "c1": insert_stmt.excluded.c1, "c2": insert_stmt.excluded.c2, }, ).add_cte(delete_statement_cte) print(update_statement)
上述语句呈现为:
WITH deletions AS (DELETE FROM t WHERE t.c1 < %(c1_1)s) INSERT INTO t (c1, c2) VALUES (%(c1)s, %(c2)s) ON CONFLICT (c1) DO UPDATE SET c1 = excluded.c1, c2 = excluded.c2
从版本 1.4.21 开始新增。
参数:
*ctes
–
零个或多个CTE
构造。
从版本 2.0 开始更改:接受多个 CTE 实例nest_here
–
如果为 True,则给定的 CTE 或 CTEs 将被呈现为当它们被添加到此HasCTE
时指定HasCTE.cte.nesting
标志为True
。假设给定的 CTEs 在外部封闭语句中也没有被引用,当给出此标志时,给定的 CTEs 应在此语句级别呈现。
从版本 2.0 开始新增。
另请参阅HasCTE.cte.nesting
method alias(name: str | None = None, flat: bool = False) → Subquery
继承自 SelectBase.alias()
方法的 SelectBase
返回针对此 SelectBase
的命名子查询。
对于 SelectBase
(而不是 FromClause
),这将返回一个行为大部分与用于 FromClause
的 Alias
对象相同的 Subquery
对象。
自版本 1.4 起更改:SelectBase.alias()
方法现在是 SelectBase.subquery()
方法的同义词。
method as_scalar() → ScalarSelect[Any]
继承自 SelectBase.as_scalar()
方法的 SelectBase
自版本 1.4 起弃用:SelectBase.as_scalar()
方法已被弃用,并将在将来的版本中移除。请参考 SelectBase.scalar_subquery()
。
attribute c
继承自 SelectBase.c
属性的 SelectBase
自版本 1.4 起弃用:SelectBase.c
和 SelectBase.columns
属性已被弃用,并将在将来的版本中移除;这些属性隐式创建一个子查询,应该明确指定。请先调用 SelectBase.subquery()
来创建一个子查询,然后再包含此属性。要访问此 SELECT 对象所选择的列,请使用 SelectBase.selected_columns
属性。
method corresponding_column(column: KeyedColumnElement[Any], require_embedded: bool = False) → KeyedColumnElement[Any] | None
继承自 Selectable.corresponding_column()
方法的 Selectable
给定一个ColumnElement
,从这个Selectable
的Selectable.exported_columns
集合中返回对应于原始ColumnElement
的导出ColumnElement
对象,通过一个共同的祖先列。
参数:
column
– 要匹配的目标ColumnElement
。require_embedded
– 只返回给定ColumnElement
的相应列,如果给定的ColumnElement
实际上存在于此Selectable
的子元素之内。通常,如果列仅与此Selectable
的导出列之一共享一个共同的祖先,则列将匹配。
另请参阅
Selectable.exported_columns
- 用于操作的ColumnCollection
。
ColumnCollection.corresponding_column()
- 实现方法。
method cte(name: str | None = None, recursive: bool = False, nesting: bool = False) → CTE
继承自 HasCTE
的 HasCTE.cte()
*方法。
返回一个新的CTE
或通用表达式实例。
公共表达式是 SQL 标准,其中 SELECT 语句可以利用与主要语句一起指定的辅助语句,使用一个称为“WITH”的子句。还可以采用有关 UNION 的特殊语义,以允许“递归”查询,其中 SELECT 语句可以利用先前已选择的行集。
CTEs 也可以应用于某些数据库上的 DML 构造 UPDATE、INSERT 和 DELETE,既作为与 RETURNING 结合使用时 CTE 行的源,也作为 CTE 行的使用者。
SQLAlchemy 检测到 CTE
对象,这些对象与 Alias
对象类似,被视为要传递到语句的 FROM 子句以及语句顶部的 WITH 子句的特殊元素。
对于特殊前缀,如 PostgreSQL 的 “MATERIALIZED” 和 “NOT MATERIALIZED”,可以使用 CTE.prefix_with()
方法来建立这些。
1.3.13 版本更改:增加了对前缀的支持。特别是 - MATERIALIZED 和 NOT MATERIALIZED。
参数:
name
– 给公共表达式的名称。类似于FromClause.alias()
,名称可以保留为None
,在这种情况下,将在查询编译时使用匿名符号。recursive
– 如果为True
,将呈现WITH RECURSIVE
。递归公共表达式旨在与 UNION ALL 结合使用,以从已选择的行中派生行。nesting
–
如果为True
,将在引用它的语句中本地呈现 CTE。对于更复杂的情况,还可以使用HasCTE.add_cte()
方法,使用HasCTE.add_cte.nest_here
参数更精确地控制特定 CTE 的精确放置。
1.4.24 版本新增。
另请参阅HasCTE.add_cte()
以下示例包括两个来自 PostgreSQL 文档的示例 www.postgresql.org/docs/current/static/queries-with.html
,以及其他示例。
示例 1,非递归:
from sqlalchemy import (Table, Column, String, Integer, MetaData, select, func) metadata = MetaData() orders = Table('orders', metadata, Column('region', String), Column('amount', Integer), Column('product', String), Column('quantity', Integer) ) regional_sales = select( orders.c.region, func.sum(orders.c.amount).label('total_sales') ).group_by(orders.c.region).cte("regional_sales") top_regions = select(regional_sales.c.region).\ where( regional_sales.c.total_sales > select( func.sum(regional_sales.c.total_sales) / 10 ) ).cte("top_regions") statement = select( orders.c.region, orders.c.product, func.sum(orders.c.quantity).label("product_units"), func.sum(orders.c.amount).label("product_sales") ).where(orders.c.region.in_( select(top_regions.c.region) )).group_by(orders.c.region, orders.c.product) result = conn.execute(statement).fetchall()
示例 2,WITH RECURSIVE:
from sqlalchemy import (Table, Column, String, Integer, MetaData, select, func) metadata = MetaData() parts = Table('parts', metadata, Column('part', String), Column('sub_part', String), Column('quantity', Integer), ) included_parts = select(\ parts.c.sub_part, parts.c.part, parts.c.quantity\ ).\ where(parts.c.part=='our part').\ cte(recursive=True) incl_alias = included_parts.alias() parts_alias = parts.alias() included_parts = included_parts.union_all( select( parts_alias.c.sub_part, parts_alias.c.part, parts_alias.c.quantity ).\ where(parts_alias.c.part==incl_alias.c.sub_part) ) statement = select( included_parts.c.sub_part, func.sum(included_parts.c.quantity). label('total_quantity') ).\ group_by(included_parts.c.sub_part) result = conn.execute(statement).fetchall()
示例 3,使用 UPDATE 和 INSERT 进行 upsert 的 CTE:
from datetime import date from sqlalchemy import (MetaData, Table, Column, Integer, Date, select, literal, and_, exists) metadata = MetaData() visitors = Table('visitors', metadata, Column('product_id', Integer, primary_key=True), Column('date', Date, primary_key=True), Column('count', Integer), ) # add 5 visitors for the product_id == 1 product_id = 1 day = date.today() count = 5 update_cte = ( visitors.update() .where(and_(visitors.c.product_id == product_id, visitors.c.date == day)) .values(count=visitors.c.count + count) .returning(literal(1)) .cte('update_cte') ) upsert = visitors.insert().from_select( [visitors.c.product_id, visitors.c.date, visitors.c.count], select(literal(product_id), literal(day), literal(count)) .where(~exists(update_cte.select())) ) connection.execute(upsert)
示例 4,嵌套 CTE(SQLAlchemy 1.4.24 及以上版本):
value_a = select( literal("root").label("n") ).cte("value_a") # A nested CTE with the same name as the root one value_a_nested = select( literal("nesting").label("n") ).cte("value_a", nesting=True) # Nesting CTEs takes ascendency locally # over the CTEs at a higher level value_b = select(value_a_nested.c.n).cte("value_b") value_ab = select(value_a.c.n.label("a"), value_b.c.n.label("b"))
上述查询将第二个 CTE 嵌套在第一个内部,如下所示带有内联参数:
WITH value_a AS (SELECT 'root' AS n), value_b AS (WITH value_a AS (SELECT 'nesting' AS n) SELECT value_a.n AS n FROM value_a) SELECT value_a.n AS a, value_b.n AS b FROM value_a, value_b
可以使用 HasCTE.add_cte()
方法来设置相同的 CTE(SQLAlchemy 2.0 及以上版本):
value_a = select( literal("root").label("n") ).cte("value_a") # A nested CTE with the same name as the root one value_a_nested = select( literal("nesting").label("n") ).cte("value_a") # Nesting CTEs takes ascendency locally # over the CTEs at a higher level value_b = ( select(value_a_nested.c.n). add_cte(value_a_nested, nest_here=True). cte("value_b") ) value_ab = select(value_a.c.n.label("a"), value_b.c.n.label("b"))
示例 5,非线性 CTE(SQLAlchemy 1.4.28 及以上版本):
edge = Table( "edge", metadata, Column("id", Integer, primary_key=True), Column("left", Integer), Column("right", Integer), ) root_node = select(literal(1).label("node")).cte( "nodes", recursive=True ) left_edge = select(edge.c.left).join( root_node, edge.c.right == root_node.c.node ) right_edge = select(edge.c.right).join( root_node, edge.c.left == root_node.c.node ) subgraph_cte = root_node.union(left_edge, right_edge) subgraph = select(subgraph_cte)
上述查询将在递归 CTE 中呈现 2 个 UNION:
WITH RECURSIVE nodes(node) AS ( SELECT 1 AS node UNION SELECT edge."left" AS "left" FROM edge JOIN nodes ON edge."right" = nodes.node UNION SELECT edge."right" AS "right" FROM edge JOIN nodes ON edge."left" = nodes.node ) SELECT nodes.node FROM nodes
另请参阅
Query.cte()
- HasCTE.cte()
的 ORM 版本。
method execution_options(**kw: Any) → Self
继承自 Executable.execution_options()
方法的 Executable
为语句设置在执行期间生效的非 SQL 选项。
可以在许多范围内设置执行选项,包括每个语句、每个连接或每次执行,使用诸如Connection.execution_options()
之类的方法和接受选项字典的参数,如Connection.execute.execution_options
和Session.execute.execution_options
。
执行选项的主要特征,与其他类型的选项(如 ORM 加载器选项)相反,是执行选项永远不会影响查询的编译 SQL,只会影响 SQL 语句本身的调用方式或结果的获取方式。也就是说,执行选项不是 SQL 编译所考虑的内容,也不被视为语句的缓存状态的一部分。
Executable.execution_options()
方法是生成的,就像应用于Engine
和Query
对象的方法一样,这意味着当调用该方法时,会返回对象的副本,将给定的参数应用于该新副本,但原始对象保持不变:
statement = select(table.c.x, table.c.y) new_statement = statement.execution_options(my_option=True)
这种行为的一个例外是Connection
对象,其中Connection.execution_options()
方法明确地不是生成的。
可传递给 Executable.execution_options()
和其他相关方法和参数字典的选项类型包括由 SQLAlchemy Core 或 ORM 明确消耗的参数,以及未由 SQLAlchemy 定义的任意关键字参数,这意味着可以使用这些方法和/或参数字典来处理与自定义代码交互的用户定义参数,该自定义代码可以使用诸如 Executable.get_execution_options()
和 Connection.get_execution_options()
的方法访问这些参数,或者在选择的事件钩子中使用专用的 execution_options
事件参数,如 ConnectionEvents.before_execute.execution_options
或 ORMExecuteState.execution_options
。例如:
from sqlalchemy import event @event.listens_for(some_engine, "before_execute") def _process_opt(conn, statement, multiparams, params, execution_options): "run a SQL function before invoking a statement" if execution_options.get("do_special_thing", False): conn.exec_driver_sql("run_special_function()")
在 SQLAlchemy 明确识别的选项范围内,大多数适用于特定类对象而不适用于其他类对象。最常见的执行选项包括:
Connection.execution_options.isolation_level
- 通过Engine
为连接或一类连接设置隔离级别。此选项仅由Connection
或Engine
接受。Connection.execution_options.stream_results
- 指示应使用服务器端游标获取结果;此选项由Connection
接受,在Connection.execute()
的execution_options
参数上,以及在 SQL 语句对象上的Executable.execution_options()
上,以及像Session.execute()
这样的 ORM 构造函数。Connection.execution_options.compiled_cache
- 指示一个将用作Connection
或Engine
的 SQL 编译缓存 的字典,以及像Session.execute()
这样的 ORM 方法。可以传递None
来禁用语句的缓存。此选项不被Executable.execution_options()
接受,因为在语句对象中携带编译缓存是不可取的。Connection.execution_options.schema_translate_map
- 模式翻译映射 功能使用的模式名称的映射,由Connection
、Engine
、Executable
接受,以及像Session.execute()
这样的 ORM 构造函数。
另请参阅
Connection.execution_options()
Connection.execute.execution_options
Session.execute.execution_options
ORM 执行选项 - 所有 ORM 特定执行选项的文档
method exists() → Exists
继承自 SelectBase.exists()
方法的 SelectBase
返回此可选择性的 Exists
表示,可用作列表达式。
返回的对象是 Exists
的一个实例。
另请参阅
exists()
EXISTS 子查询 - 在 2.0 风格 教程中。
版本 1.4 中的新功能。
attribute exported_columns
继承自 SelectBase.exported_columns
属性的 SelectBase
一个 ColumnCollection
代表此 Selectable
的“导出”列,不包括 TextClause
结构。
一个 SelectBase
对象的“导出”列与 SelectBase.selected_columns
集合是同义词。
版本 1.4 中的新功能。
另请参阅
Select.exported_columns
Selectable.exported_columns
FromClause.exported_columns
method fetch(count: _LimitOffsetType, with_ties: bool = False, percent: bool = False) → Self
继承自 GenerativeSelect.fetch()
方法的 GenerativeSelect
返回一个应用了给定 FETCH FIRST 标准的新可选择性。
这是一个数字值,通常在结果选择中呈现为FETCH {FIRST | NEXT} [ count ] {ROW | ROWS} {ONLY | WITH TIES}
表达式。此功能目前已在 Oracle、PostgreSQL、MSSQL 上实现。
使用 GenerativeSelect.offset()
来指定偏移量。
注意
GenerativeSelect.fetch()
方法将替换应用了 GenerativeSelect.limit()
的任何子句。
自版本 1.4 起新增。
SqlAlchemy 2.0 中文文档(三十五)(2)https://developer.aliyun.com/article/1562892