Operator Referenz

Dieser Abschnitt beschreibt die Verwendung der Operatoren, die zum Konstruieren von SQL-Ausdrücken verfügbar sind.

Diese Methoden werden im Hinblick auf die Basisklassen Operators und ColumnOperators präsentiert. Die Methoden sind dann auf Nachkommen dieser Klassen verfügbar, einschließlich

Die Operatoren werden zuerst in den Tutorial-Abschnitten eingeführt, darunter

Vergleichsoperatoren

Grundlegende Vergleiche, die auf viele Datentypen angewendet werden, einschließlich Numerics, Strings, Daten und viele andere

IN-Vergleiche

Der SQL IN-Operator ist ein eigenes Thema in SQLAlchemy. Da der IN-Operator normalerweise gegen eine Liste fester Werte verwendet wird, nutzt die Funktion von SQLAlchemy zur Konvertierung von gebundenen Parametern eine spezielle Form der SQL-Kompilierung, die einen temporären SQL-String für die Kompilierung rendert, der in einem zweiten Schritt zu der endgültigen Liste von gebundenen Parametern geformt wird. Mit anderen Worten: „es funktioniert einfach“.

IN gegen eine Liste von Werten

IN ist typischerweise verfügbar, indem eine Liste von Werten an die Methode ColumnOperators.in_() übergeben wird.

>>> print(column("x").in_([1, 2, 3]))
x IN (__[POSTCOMPILE_x_1])

Die spezielle gebundene Form __[POSTCOMPILE wird zur Laufzeit in einzelne Parameter gerendert, wie unten dargestellt.

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

Leere IN-Ausdrücke

SQLAlchemy liefert ein mathematisch gültiges Ergebnis für einen leeren IN-Ausdruck, indem es eine Backend-spezifische Subquery rendert, die keine Zeilen zurückgibt. Wieder anders ausgedrückt: „es funktioniert einfach“.

>>> 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) [...] ()

Die „leere Menge“-Subquery oben verallgemeinert sich korrekt und wird auch im Hinblick auf den IN-Operator gerendert, der erhalten bleibt.

NICHT IN

„NOT IN“ ist über den Operator ColumnOperators.not_in() verfügbar.

>>> print(column("x").not_in([1, 2, 3]))
(x NOT IN (__[POSTCOMPILE_x_1]))

Dies ist typischerweise leichter verfügbar, indem mit dem Operator ~ negiert wird.

>>> print(~column("x").in_([1, 2, 3]))
(x NOT IN (__[POSTCOMPILE_x_1]))

Tuple IN-Ausdrücke

Der Vergleich von Tupeln mit Tupeln ist bei IN üblich, da er unter anderem den Fall abdeckt, wenn Zeilen mit einer Menge potenzieller zusammengesetzter Primärschlüsselwerte abgeglichen werden. Die Konstruktion tuple_() bildet die grundlegende Baustein für Tupelvergleiche. Der Operator Tuple.in_() empfängt dann eine Liste von Tupeln.

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

Um die gerenderten Parameter zu veranschaulichen

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

Subquery IN

Schließlich funktionieren die Operatoren ColumnOperators.in_() und ColumnOperators.not_in() mit Subqueries. Das Formular stellt sicher, dass ein Select-Konstrukt direkt übergeben wird, ohne explizite Konvertierung in eine benannte Subquery.

>>> print(column("x").in_(select(user_table.c.id)))
x IN (SELECT user_account.id FROM user_account)

Tupel funktionieren wie erwartet.

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

Identitätsvergleiche

Diese Operatoren beinhalten das Testen auf spezielle SQL-Werte wie NULL, boolesche Konstanten wie true oder false, die einige Datenbanken unterstützen.

  • ColumnOperators.is_():

    Dieser Operator liefert exakt das SQL für „x IS y“, am häufigsten gesehen als „<expr> IS NULL“. Die NULL-Konstante wird am einfachsten mit dem regulären Python-Wert None erworben.

    >>> print(column("x").is_(None))
    
    x IS NULL

    SQL NULL ist auch explizit verfügbar, falls benötigt, über die Konstruktion null().

    >>> from sqlalchemy import null
    >>> print(column("x").is_(null()))
    
    x IS NULL

    Der Operator ColumnOperators.is_() wird automatisch aufgerufen, wenn der überladene Operator ColumnOperators.__eq__(), d. h. ==, in Verbindung mit dem Wert None oder null() verwendet wird. Auf diese Weise gibt es normalerweise keinen Bedarf, ColumnOperators.is_() explizit zu verwenden, insbesondere wenn es mit einem dynamischen Wert verwendet wird.

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

    Beachten Sie, dass der Python-Operator is nicht überladen ist. Obwohl Python Hooks bereitstellt, um Operatoren wie == und != zu überladen, bietet es keine Möglichkeit, is neu zu definieren.

  • ColumnOperators.is_not():

    Ähnlich wie bei ColumnOperators.is_() erzeugt dies „IS NOT“.

    >>> print(column("x").is_not(None))
    
    x IS NOT NULL

    Ist ähnlich äquivalent zu != None.

    >>> print(column("x") != None)
    
    x IS NOT NULL
  • ColumnOperators.is_distinct_from():

    Erzeugt SQL IS DISTINCT FROM.

    >>> print(column("x").is_distinct_from("some value"))
    
    x IS DISTINCT FROM :x_1
  • ColumnOperators.isnot_distinct_from():

    Erzeugt SQL IS NOT DISTINCT FROM.

    >>> print(column("x").isnot_distinct_from("some value"))
    
    x IS NOT DISTINCT FROM :x_1

String-Vergleiche

  • ColumnOperators.like():

    >>> print(column("x").like("word"))
    
    x LIKE :x_1
  • ColumnOperators.ilike():

    Groß-/Kleinschreibung-unempfindliches LIKE verwendet die SQL-Funktion lower() auf einem generischen Backend. Auf dem PostgreSQL-Backend wird ILIKE verwendet.

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

String-Enthaltensein

String-Enthaltensein-Operatoren werden grundlegend als Kombination aus LIKE und dem String-Verkettungsoperator aufgebaut, der || auf den meisten Backends ist oder manchmal eine Funktion wie concat().

String-Abgleich

Abgleichoperatoren sind immer Backend-spezifisch und können auf verschiedenen Datenbanken unterschiedliche Verhaltensweisen und Ergebnisse liefern.

  • ColumnOperators.match():

    Dies ist ein Dialekt-spezifischer Operator, der die MATCH-Funktion der zugrunde liegenden Datenbank verwendet, falls verfügbar.

    >>> print(column("x").match("word"))
    
    x MATCH :x_1
  • ColumnOperators.regexp_match():

    Dieser Operator ist Dialekt-spezifisch. Wir können ihn beispielsweise im Hinblick auf den PostgreSQL-Dialekt veranschaulichen.

    >>> from sqlalchemy.dialects import postgresql
    >>> print(column("x").regexp_match("word").compile(dialect=postgresql.dialect()))
    
    x ~ %(x_1)s

    Oder MySQL.

    >>> from sqlalchemy.dialects import mysql
    >>> print(column("x").regexp_match("word").compile(dialect=mysql.dialect()))
    
    x REGEXP %s

String-Änderung

  • ColumnOperators.concat():

    String-Verkettung.

    >>> print(column("x").concat("some string"))
    
    x || :x_1

    Dieser Operator ist über ColumnOperators.__add__(), d. h. den Python-Operator +, verfügbar, wenn mit einem Spaltenausdruck gearbeitet wird, der von String abgeleitet ist.

    >>> print(column("x", String) + "some string")
    
    x || :x_1

    Der Operator erzeugt die entsprechende datenbankspezifische Konstruktion, wie z. B. auf MySQL die historisch verwendete SQL-Funktion concat().

    >>> print((column("x", String) + "some string").compile(dialect=mysql.dialect()))
    
    concat(x, %s)
  • ColumnOperators.regexp_replace():

    Ergänzend zu ColumnOperators.regexp() erzeugt dies ein REGEXP REPLACE-Äquivalent für Backends, die es unterstützen.

    >>> print(column("x").regexp_replace("foo", "bar").compile(dialect=postgresql.dialect()))
    
    REGEXP_REPLACE(x, %(x_1)s, %(x_2)s)
  • ColumnOperators.collate():

    Erzeugt den COLLATE SQL-Operator, der zur Ausdruckszeit spezifische Sortierungen bereitstellt.

    >>> print(
    ...     (column("x").collate("latin1_german2_ci") == "Müller").compile(
    ...         dialect=mysql.dialect()
    ...     )
    ... )
    
    (x COLLATE latin1_german2_ci) = %s

    Um COLLATE gegen einen Literalwert zu verwenden, nutzen Sie die Konstruktion 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

Arithmetische Operatoren

  • ColumnOperators.__add__(), ColumnOperators.__radd__() (Python „+“-Operator)

    >>> print(column("x") + 5)
    
    x + :x_1
    >>> print(5 + column("x"))
    :x_1 + x

    Beachten Sie, dass wenn der Datentyp des Ausdrucks String oder ähnlich ist, der Operator ColumnOperators.__add__() stattdessen String-Verkettung erzeugt.

  • ColumnOperators.__sub__(), ColumnOperators.__rsub__() (Python „-“-Operator)

    >>> print(column("x") - 5)
    
    x - :x_1
    >>> print(5 - column("x"))
    :x_1 - x
  • ColumnOperators.__mul__(), ColumnOperators.__rmul__() (Python „*“-Operator)

    >>> print(column("x") * 5)
    
    x * :x_1
    >>> print(5 * column("x"))
    :x_1 * x
  • ColumnOperators.__truediv__(), ColumnOperators.__rtruediv__() (Python „/“-Operator). Dies ist der Python truediv-Operator, der sicherstellt, dass eine Ganzzahl-echte Division stattfindet.

    >>> print(column("x") / 5)
    
    x / CAST(:x_1 AS NUMERIC)
    >>> print(5 / column("x"))
    :x_1 / CAST(x AS NUMERIC)

    Geändert in Version 2.0: Der Python-Operator / stellt nun sicher, dass eine Ganzzahl-echte Division stattfindet.

  • ColumnOperators.__floordiv__(), ColumnOperators.__rfloordiv__() (Python „//“-Operator). Dies ist der Python floordiv-Operator, der sicherstellt, dass eine Boden-Division stattfindet. Für das Standard-Backend sowie für Backends wie PostgreSQL verhält sich der SQL-Operator / für Ganzzahlwerte normalerweise auf diese Weise.

    >>> print(column("x") // 5)
    
    x / :x_1
    >>> print(5 // column("x", Integer))
    :x_1 / x

    Für Backends, die standardmäßig keine Boden-Division verwenden, oder bei Verwendung mit numerischen Werten wird die FLOOR()-Funktion verwendet, um eine Boden-Division sicherzustellen.

    >>> print(column("x") // 5.5)
    
    FLOOR(x / :x_1)
    >>> print(5 // column("x", Numeric))
    FLOOR(:x_1 / x)

    Neu in Version 2.0: Unterstützung für FLOOR-Division.

  • ColumnOperators.__mod__(), ColumnOperators.__rmod__() (Python „%“-Operator)

    >>> print(column("x") % 5)
    
    x % :x_1
    >>> print(5 % column("x"))
    :x_1 % x

Bitweise Operatoren

Bitweise Operatorfunktionen bieten einen einheitlichen Zugriff auf bitweise Operatoren über verschiedene Backends hinweg, die auf kompatible Werte wie Ganzzahlen und Bit-Strings (z. B. PostgreSQL BIT und ähnliches) angewendet werden sollen. Beachten Sie, dass dies keine allgemeinen booleschen Operatoren sind.

Neu in Version 2.0.2: Dedizierte Operatoren für bitweise Operationen hinzugefügt.

  • ColumnOperators.bitwise_not(), bitwise_not(). Verfügbar als spaltenbasierte Methode, die eine bitweise NOT-Klausel gegen ein übergeordnetes Objekt erzeugt.

    >>> print(column("x").bitwise_not())
    ~x

    Dieser Operator ist auch als spaltenausdruckbasierte Methode verfügbar, die bitweise NOT auf einen einzelnen Spaltenausdruck anwendet.

    >>> from sqlalchemy import bitwise_not
    >>> print(bitwise_not(column("x")))
    ~x
  • ColumnOperators.bitwise_and() erzeugt bitweises AND.

    >>> print(column("x").bitwise_and(5))
    x & :x_1
  • ColumnOperators.bitwise_or() erzeugt bitweises OR.

    >>> print(column("x").bitwise_or(5))
    x | :x_1
  • ColumnOperators.bitwise_xor() erzeugt bitweises XOR.

    >>> print(column("x").bitwise_xor(5))
    x ^ :x_1

    Für PostgreSQL-Dialekte wird „#“ verwendet, um bitweises XOR darzustellen; dies wird automatisch ausgegeben, wenn eines dieser Backends verwendet wird.

    >>> 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() erzeugen bitweise Shift-Operatoren.

    >>> print(column("x").bitwise_rshift(5))
    x >> :x_1
    >>> print(column("x").bitwise_lshift(5))
    x << :x_1

Verwendung von Konjunktionen und Negationen

Die gebräuchlichste Konjunktion, „AND“, wird automatisch angewendet, wenn wir die Methode Select.where() wiederholt verwenden, sowie ähnliche Methoden wie Update.where() und 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() und Delete.where() akzeptieren auch mehrere Ausdrücke mit derselben Wirkung.

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

Die Konjunktion „AND“ sowie ihr Partner „OR“ sind beide direkt über die Funktionen and_() und or_() verfügbar.

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

Eine Negation ist über die Funktion not_() verfügbar. Dies kehrt typischerweise den Operator in einem booleschen Ausdruck um.

>>> from sqlalchemy import not_
>>> print(not_(column("x") == 5))
x != :x_1

Es kann auch ein Schlüsselwort wie NOT angewendet werden, wenn dies angebracht ist.

>>> from sqlalchemy import Boolean
>>> print(not_(column("x", Boolean)))
NOT x

Konjunktionsoperatoren

Die oben genannten Konjunktionsfunktionen and_(), or_(), not_() sind auch als überladene Python-Operatoren verfügbar.

Hinweis

Die Python-Operatoren &, | und ~ haben eine hohe Priorität in der Sprache; folglich müssen für Operanden, die selbst Ausdrücke enthalten, normalerweise Klammern gesetzt werden, wie in den folgenden Beispielen gezeigt.

  • Operators.__and__() (Python „&“-Operator)

    Der binäre Python-Operator & ist überladen, um sich genauso zu verhalten wie and_() (beachten Sie die Klammern um die beiden Operanden).

    >>> print((column("x") == 5) & (column("y") == 10))
    
    x = :x_1 AND y = :y_1
  • Operators.__or__() (Python „|“-Operator)

    Der binäre Python-Operator | ist überladen, um sich genauso zu verhalten wie or_() (beachten Sie die Klammern um die beiden Operanden).

    >>> print((column("x") == 5) | (column("y") == 10))
    
    x = :x_1 OR y = :y_1
  • Operators.__invert__() (Python „~“-Operator)

    Der binäre Python-Operator ~ ist überladen, um sich genauso zu verhalten wie not_(), entweder indem der vorhandene Operator umgekehrt oder das Schlüsselwort NOT auf den gesamten Ausdruck angewendet wird.

    >>> print(~(column("x") == 5))
    
    x != :x_1
    >>> from sqlalchemy import Boolean >>> print(~column("x", Boolean))
    NOT x