操作员参考

优质
小牛编辑
135浏览
2023-12-01

本节详细介绍可用于构造SQL表达式的运算符的用法。

这些方法是根据 OperatorsColumnOperators 基类。这些类的后代可以使用这些方法,包括:

在教程部分中首先介绍了运算符,包括:

比较运算符

适用于许多数据类型(包括数字、字符串、日期等)的基本比较:

在比较中

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 ,布尔常量,例如 truefalse 一些数据库支持:

  • ColumnOperators.is_()

    此运算符将为“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__() 重载运算符,即。 == ,与 Nonenull() 价值观。这样,通常不需要使用 ColumnOperators.is_() 显式地,当与动态值一起使用时:

    >>> a = None
    >>> print(column('x') == a)
    x IS NULL

    注意 Python is 操作员是 不超载 . 即使Python为重载操作符提供了钩子,比如 ==!= 是的 not 提供任何重新定义的方法 is .

  • ColumnOperators.is_not()

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

字符串比较

管柱密封

字符串包含运算符基本上是由LIKE和字符串连接运算符组合而成的,即 || 在大多数后端或有时像 concat()

字符串匹配

匹配运算符始终特定于后端,并且可能在不同的数据库上提供不同的行为和结果:

  • ColumnOperators.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__() ,也就是 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)
  • 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

算术运算符

使用连词和否定词

如果我们重复使用 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