本节详细介绍可用于构造SQL表达式的运算符的用法。
这些方法是根据 Operators
和 ColumnOperators
基类。这些类的后代可以使用这些方法,包括:
Column
物体
ColumnElement
对象,它们是所有核心SQL表达式语言列级表达式的根
InstrumentedAttribute
对象是映射的属性。
在教程部分中首先介绍了运算符,包括:
SQLAlchemy 1.4/2.0教程 - unified tutorial in 2.0 style
对象关系教程(1.x API) - ORM tutorial in 1.x style
SQL表达式语言教程(1.x API) - Core tutorial in 1.x style
适用于许多数据类型(包括数字、字符串、日期等)的基本比较:
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
>>> print(column('x').between(5, 10))
x BETWEEN :x_1 AND :x_2
sqlin操作符在SQLAlchemy中是一个独立的主题。由于IN运算符通常用于固定值列表,SQLAlchemy的绑定参数强制特性使用了一种特殊的SQL编译形式,该编译将呈现一个临时SQL字符串,以便在第二步中形成绑定参数的最终列表。换言之,“它就是有效的”。
通常,通过将值列表传递给 ColumnOperators.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)
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运算符呈现。
“不在”可通过 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]))
元组与元组的比较在中很常见,因为在将行与一组潜在的复合主键值进行匹配时,其他用例都适用于这种情况。这个 tuple_()
construct为元组比较提供了基本的构建块。这个 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',)]
最后, 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
一些数据库支持:
此运算符将为“x IS y”提供精确的SQL,通常被视为“<expr>IS NULL”。这个 NULL
使用常规Python最容易获得常量 None
::
>>> print(column('x').is_(None))
x IS NULL
如果需要,也可以使用 null()
结构:
>>> from sqlalchemy import null
>>> print(column('x').is_(null()))
x IS NULL
这个 ColumnOperators.is_()
使用运算符时自动调用 ColumnOperators.__eq__()
重载运算符,即。 ==
,与 None
或 null()
价值观。这样,通常不需要使用 ColumnOperators.is_()
显式地,当与动态值一起使用时:
>>> a = None
>>> print(column('x') == a)
x IS NULL
注意 Python is
操作员是 不超载 . 即使Python为重载操作符提供了钩子,比如 ==
和 !=
是的 not 提供任何重新定义的方法 is
.
类似 ColumnOperators.is_()
,产生“不是”:
>>> print(column('x').is_not(None))
x IS NOT NULL
类似于 != None
::
>>> print(column('x') != None)
x IS NOT NULL
ColumnOperators.is_distinct_from()
:
生成的SQL不同于:
>>> print(column('x').is_distinct_from('some value'))
x IS DISTINCT FROM :x_1
ColumnOperators.isnot_distinct_from()
:
生成的SQL与以下对象不同:
>>> print(column('x').isnot_distinct_from('some value'))
x IS NOT DISTINCT FROM :x_1
>>> print(column('x').like('word'))
x LIKE :x_1
不区分大小写的LIKE使用SQL lower()
函数在通用后端上。在PostgreSQL后端,它将使用 ILIKE
::
>>> print(column('x').ilike('word'))
lower(x) LIKE lower(:x_1)
>>> print(column('x').notlike('word'))
x NOT LIKE :x_1
>>> print(column('x').notilike('word'))
lower(x) NOT LIKE lower(:x_1)
字符串包含运算符基本上是由LIKE和字符串连接运算符组合而成的,即 ||
在大多数后端或有时像 concat()
:
ColumnOperators.startswith()
::
The string containment operators
>>> print(column('x').startswith('word'))
x LIKE :x_1 || '%'
>>> print(column('x').endswith('word'))
x LIKE '%' || :x_1
>>> print(column('x').contains('word'))
x LIKE '%' || :x_1 || '%'
匹配运算符始终特定于后端,并且可能在不同的数据库上提供不同的行为和结果:
这是一个特定于方言的运算符,它使用底层数据库的匹配功能(如果可用):
>>> 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
字符串连接::
>>> print(column('x').concat("some string"))
x || :x_1
此操作员可通过 ColumnOperators.__add__()
,也就是 Python +
运算符,当使用派生自 String
::
>>> 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)
生成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__()
操作员却生成 string concatenation .
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.__div__()
, ColumnOperators.__rdiv__()
(Python“/”运算符)::
>>> print(column('x') / 5)
x / :x_1
>>> print(5 / column('x'))
:x_1 / x
ColumnOperators.__mod__()
, ColumnOperators.__rmod__()
(Python“%`”运算符)::
>>> print(column('x') % 5)
x % :x_1
>>> print(5 % column('x'))
:x_1 % x
如果我们重复使用 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“&”运算符):
Python二进制文件 &
运算符的行为与 and_()
(注意两个操作数周围的括号)::
>>> print((column('x') == 5) & (column('y') == 10))
x = :x_1 AND y = :y_1
Operators.__or__()
(Python“|`
”运算符):
Python二进制文件 |
运算符的行为与 or_()
(注意两个操作数周围的括号)::
>>> print((column('x') == 5) | (column('y') == 10))
x = :x_1 OR y = :y_1
Operators.__invert__()
(Python“~”运算符):
Python二进制文件 ~
运算符的行为与 not_()
,或者反转现有运算符,或者应用 NOT
整个表达式的关键字::
>>> print(~(column('x') == 5))
x != :x_1
>>> from sqlalchemy import Boolean
>>> print(~column('x', Boolean))
NOT x
TODO
flambé! the dragon and The Alchemist image designs created and generously donated by Rotem Yaari.
Created using Sphinx 4.2.0.