SQL-Operatoren
SQL-Operatoren umfassen Operatoren zum Vergleichen, Berechnen, Auswerten und Verketten von Werten.
SQL-Operatoren umfassen Operatoren zum Vergleichen, Berechnen, Auswerten und Verketten von Werten.
SQL Operatoren sind in vier Typen unterteilt.Jeder Operator-Typ hat eine Priorität, eine Rangfolge, die die Reihenfolge bestimmt, in der die Operatoren und die mit ihrer Hilfe erhaltenen Werte in einem Ausdruck ausgewertet werden.Je höher der Vorrang des Operator-Typs ist, desto früher wird er ausgewertet.Jeder Operator hat seine eigene Priorität innerhalb seines Typs, der die Reihenfolge bestimmt, in der sie in einem Ausdruck ausgewertet werden.
Operatoren der gleichen Rangfolge werden von links nach rechts ausgewertet.Um dieses Verhalten zu beeinflussen, können Gruppen mittels Klammern erstellt werden.
Operatortyp | Vorrang | Erläuterung |
---|---|---|
Verkettung |
1 |
Strings werden verkettet, bevor andere Operationen stattfinden |
Arithmetik |
2 |
Arithmetische Operationen werden durchgeführt, nachdem Strings verkettet sind, aber vor Vergleichs- und logischen Operationen |
Vergleiche |
3 |
Vergleichsoperationen erfolgen nach String-Verkettung und arithmetischen Operationen, aber vor logischen Operationen |
Logical |
4 |
Logische Operatoren werden nach allen anderen Operatortypen ausgeführt |
Der Verkettungsoperator, zwei Pipe-Zeichen, auch “Doppel-Pipe” — ‘||
’ — verkettet (verbindet) zwei Zeichenketten zu einer einzigen Zeichenkette.Zeichenketten können dabei Konstante Werte oder abgeleitet von einer Spalte oder einem Ausdruck sein.
SELECT LAST_NAME || ', ' || FIRST_NAME AS FULL_NAME
FROM EMPLOYEE
Operator | Zweck | Vorrang |
---|---|---|
|
unäres Plus |
1 |
|
unäres Minus |
1 |
|
Multiplikation |
2 |
|
Division |
2 |
|
Addition |
3 |
|
Subtraktion |
3 |
UPDATE T
SET A = 4 + 1/(B-C)*D
Note
|
Wenn Operatoren den gleichen Vorrang besitzen, werden diese von links nach rechts ausgewertet. |
Operator | Zweck | Priorität |
---|---|---|
|
Überprüft, ob der Ausdruck auf der linken Seite (nicht) |
1 |
|
Ist gleich, ist identisch mit |
2 |
|
Ist ungleich zu |
2 |
|
Ist größer als |
2 |
|
Ist kleiner als |
2 |
|
Ist größer gleich als |
2 |
|
Ist kleiner gleich als |
2 |
|
Ist nicht größer als |
2 |
|
Ist nicht kleiner als |
2 |
Diese Gruppe umfasst auch Vergleichsprädikate BETWEEN
, LIKE
, CONTAINING
, SIMILAR TO
und andere.
IF (SALARY > 1400) THEN
…
Operator | Zweck | Priorität |
---|---|---|
|
Negierung eines Suchkriteriums |
1 |
|
Kombiniert zwei oder mehr Prädikate, wobei jedes als wahr angesehen werden muss, damit der Gesamtausdruck ebenfalls als wahr aufgelöst wird |
2 |
|
Kombiniert zwei oder mehr Prädikate, wobei mindestens eines als wahr angesehen werden muss, damit der Gesamtausdruck ebenfalls als wahr aufgelöst wird |
3 |
IF (A < B OR (A > C AND A > D) AND NOT (C = D)) THEN …
NEXT VALUE FOR
DSQL, PSQL
BIGINT
— Dialect 2 und 3INTEGER
— Dialect 1
NEXT VALUE FOR Sequenzname
NEXT VALUE FOR
gibt den nächsten Wert einer Sequenz zurück.SEQUENCE
ist ein SQL-konformer Begriff für Generatoren in Firebird und dessen Vorgänger, InterBase.Der Operator NEXT VALUE FOR
entspricht der Legacy-Funktion GEN_ID (…, increment)
mit increment dem in den Metadaten der Sequenz gespeicherten Inkrement.Dies ist die empfohlene Syntax zum Abrufen des nächsten Sequenzwerts.
Note
|
Im Gegensatz zur Das Inkrement einer Sequenz kann mit der In Dialekt 1 ist der Ergebnistyp |
NEW.CUST_ID = NEXT VALUE FOR CUSTSEQ;
AT
-ZeitzonenausdruckDSQL, PSQL
<at expr> ::= <expr> AT { TIME ZONE <Zeitzonen-String> | LOCAL }
Der AT
-Ausdruck drückt einen Datum/Uhrzeit-Wert in einer anderen Zeitzone aus, während der gleiche UTC-Zeitpunkt beibehalten wird.
"AT" übersetzt einen Zeit-/Zeitstempelwert in seinen entsprechenden Wert in einer anderen Zeitzone.Wenn LOCAL
verwendet wird, wird der Wert in die Sitzungszeitzone konvertiert.
Wenn expr vom Typ WITHOUT TIME ZONE
ist, wird expr zuerst in WITH TIME ZONE
in der Sitzungszeitzone konvertiert und dann in die angegebene Zeitzone umgewandelt.
select time '12:00 GMT' at time zone '-03:00' from rdb$database;
select current_timestamp at time zone 'America/Sao_Paulo' from rdb$database;
select timestamp '2018-01-01 12:00 GMT' at local from rdb$database;
Ein bedingter Ausdruck ist einer der verschiedene Werte zurückgibt, je nach verwendeter Bedingung.Es besteht aus einem bedingten Funktionskonstrukt, wovon Firebird mehrere unterstützt.Dieser Abschnitt beschreibt nur ein bedingtes Ausdruckskonstrukt: CASE
.Alle anderen bedingten Ausdrücke sind interne Funktionen und leiten sich von CASE
ab und werden in Bedingte Funktionen beschrieben.
CASE
DSQL, PSQL
Das CASE
-Konstrukt gibt einen einzigen Wert aus einer Reihe von Werten zurück.Zwei syntaktische Varianten werden unterstützt:
Das einfache CASE
, vergleichbar zu einem CASE-Konstrukt in Pascal oder einem Switch in C
Das gesuchte CASE
, welches wie eine Reihe aus “if … else if … else if
”-Klauseln funktioniert.
CASE
… CASE <test-expr> WHEN <expr> THEN <result> [WHEN <expr> THEN <result> ...] [ELSE <defaultresult>] END …
Bei dieser Variante wird test-expr mit dem ersten expr, dem zweiten expr usw. verglichen, bis eine Übereinstimmung gefunden wird und das entsprechende Ergebnis zurückgegeben wird.Wenn keine Übereinstimmung gefunden wird, wird defaultresult aus der optionalen ELSE
-Klausel zurückgegeben.Wenn es keine Übereinstimmungen und keine ELSE
-Klausel gibt, wird NULL
zurückgegeben.
Das Matching funktioniert genauso wie der Operator “=
”.Das heißt, wenn test-expr NULL
ist, stimmt es mit keinem expr überein, nicht einmal mit einem Ausdruck, der in NULL
aufgelöst wird.
Das zurückgegebene Ergebnis muss kein Literalwert sein: Es kann ein Feld- oder Variablenname, ein zusammengesetzter Ausdruck oder ein NULL
-Literal sein.
SELECT
NAME,
AGE,
CASE UPPER(SEX)
WHEN 'M' THEN 'Male'
WHEN 'F' THEN 'Female'
ELSE 'Unknown'
END GENDER,
RELIGION
FROM PEOPLE
Eine Kurzform des einfachen CASE
-Konstrukts wird auch in der DECODE
-Funktion verwendet.
CASE
CASE
WHEN <bool_expr> THEN <result>
[WHEN <bool_expr> THEN <result> …]
[ELSE <defaultresult>]
END
Der bool_expr-Ausdruck gibt ein ternäres logisches Ergebnis zurück: TRUE
, FALSE
oder NULL
.Der erste Ausdruck, der TRUE
ermittelt, wird als Ergebnis verwendet.Gibt kein Ausdruck TRUE
zurück, kommt defaultresult aus der optionalen ELSE
-Klausel zum Einsatz.Gibt kein Ausdruck TRUE
zurück und gibt es keine ELSE
-Klausel, ist der Rückgabewert NULL
.
So wie im einfachen CASE
-Konstrukt, muss das Ergebnis nicht zwangsläufig ein Literal sein: es kann ein Feld- oder Variablenname, ein zusammengesetzter Ausdruck oder NULL
sein.
CANVOTE = CASE
WHEN AGE >= 18 THEN 'Yes'
WHEN AGE < 18 THEN 'No'
ELSE 'Unsure'
END
NULL
in AusdrückenNULL
ist in SQL kein Wert, sondern ein state, der anzeigt, dass der Wert des Elements entweder unbekannt ist oder nicht existiert.Es ist weder eine Null, noch ein Leerzeichen, noch ein “leerer String”, und es verhält sich nicht wie ein Wert.
Wenn Sie NULL
in numerischen, String- oder Datums-/Uhrzeit-Ausdrücken verwenden, ist das Ergebnis immer NULL
.Wenn Sie NULL
in logischen (booleschen) Ausdrücken verwenden, hängt das Ergebnis vom Typ der Operation und von anderen beteiligten Werten ab.Wenn Sie einen Wert mit NULL
vergleichen, ist das Ergebnis unbekannt.
Important
|
|
NULL
zurückgebenAusdrücke in dieser Liste werden immer NULL
zurückgeben:
1 + 2 + 3 + NULL
'Home ' || 'sweet ' || NULL
MyField = NULL
MyField <> NULL
NULL = NULL
not (NULL)
Wenn es Ihnen schwerfällt dies zu verstehen, beachten Sie, dass NULL
ein Status ist, der für “unknown” (unbekannt) steht.
NULL
in logischen AusdrückenEs wurde bereits gezeigt, dass not (NULL)
in NULL
aufgeht.Dieser Effekt ist etwas komplizierter für logische AND
- sowie logische OR
-Operatoren:
NULL or false → NULL NULL or true → true NULL or NULL → NULL NULL and false → false NULL and true → NULL NULL and NULL → NULL
Tip
|
Als grundlegende Faustregel gilt: Wenn die Anwendung von |
(1 = NULL) or (1 <> 1) -- Ergebnis NULL
(1 = NULL) or FALSE -- Ergebnis NULL
(1 = NULL) or (1 = 1) -- Ergebnis TRUE
(1 = NULL) or TRUE -- Ergebnis TRUE
(1 = NULL) or (1 = NULL) -- Ergebnis NULL
(1 = NULL) or UNKNOWN -- Ergebnis NULL
(1 = NULL) and (1 <> 1) -- Ergebnis FALSE
(1 = NULL) and FALSE -- Ergebnis FALSE
(1 = NULL) and (1 = 1) -- Ergebnis NULL
(1 = NULL) and TRUE -- Ergebnis NULL
(1 = NULL) and (1 = NULL) -- Ergebnis NULL
(1 = NULL) and UNKNOWN -- Ergebnis NULL
Eine Unterabfrage ist eine spezielle Form eines Ausdrucks, die innerhalb einer anderen Abfrage eingebettet wird.Unterabfragen werden in der gleichen Weise geschrieben wie reguläre SELECT
-Abfragen, werden jedoch von Klammern umschlossen.Unterabfrage-Ausdrücke können in folgender Art und Weise verwendet werden:
Um eine Ausgabespalte in der SELECT-Liste anzugeben
Um Werte zu holen oder als Kriterium für Suchprädikate (die WHERE
- und HAVING
-Klauseln)
Um ein Set zu erstellen, das die Eltern-Abfrage verwenden kann, so als wäre dies eine reguläre Tabelle oder View.Unterabfragen wie diese erscheinen in der FROM-Klausel (Derived Tables) oder in einer Common Table Expression (CTE)
Eine Unterabfrage kann korreliert sein.Eine Abfrage ist korreliert, wenn die Unterabfrage und die Hauptabfrage voneinander abhängig sind.Um jeden Datensatz in der Unterabfrage zu verarbeiten, muss ein Datensatz in der Hauptabfrage abgerufen werden;d.h. die Unterabfrage hängt vollständig von der Hauptabfrage ab.
SELECT *
FROM Customers C
WHERE EXISTS
(SELECT *
FROM Orders O
WHERE C.cnum = O.cnum
AND O.adate = DATE '10.03.1990');
Werden Unterabfragen verwendet um Werte einer Ausgabespalte aus einer SELECT-Liste zu holen, muss die Unterabfrage ein skalares Ergebnis zurückliefern.
Unterabfragen, die in Suchprädikaten verwendet werden, mit Ausnahme von existenziellen und quantifizierten Prädikaten, müssen ein skalares Ergebnis zurückgeben;Das heißt, nicht mehr als eine Spalte von nicht mehr als einer passenden Zeile oder Aggregation.Sollte mehr zurückgegeben werden, wird es zu einem Laufzeitfehler kommen (“Multiple rows in a singleton select…”).
Note
|
Obwohl es einen echten Fehler berichtet, kann die Nachricht etwas irreführend sein.Ein “singleton SELECT” ist eine Abfrage, die nicht mehr als eine Zeile zurückgeben kann.Jedoch sind “singleton” und “skalar” nicht gleichzusetzen: nicht alle singleton SELECTs müssen zwangsläufig skalar sein;und Einspalten-SELECTs können mehrere Zeilen für existenzielle und quantifizierte Prädikate zurückgeben. |
Eine Unterabfrage als Ausgabespalte in einer SELECT
-Liste:
SELECT
e.first_name,
e.last_name,
(SELECT
sh.new_salary
FROM
salary_history sh
WHERE
sh.emp_no = e.emp_no
ORDER BY sh.change_date DESC ROWS 1) AS last_salary
FROM
employee e
Eine Unterabfrage in der WHERE
-Klausel, um das höchste Gehalt eines Mitarbeiters zu ermitteln und hierauf zu filtern:
SELECT
e.first_name,
e.last_name,
e.salary
FROM employee e
WHERE
e.salary = (
SELECT MAX(ie.salary)
FROM employee ie
)
Ein Prädikat ist ein einfacher Ausdruck, der eine Behauptung aufstellt, wir nennen sie P
.Wenn P
zu TRUE (wahr) aufgelöst wird, ist die Behauptung erfolgreich.Wird sie zu FALSE (unwahr, falsch) oder NULL (UNKNOWN) aufgelöst, ist die Behauptung falsch.Hier gibt es einen Fallstrick: Nehmen wir an, das Prädikat P
gibt FALSE zurück.In diesem Falle gilt, dass NOT(P)
TRUE zurückgeben wird.Andererseits gilt, falls P
NULL (unknown) zurückgibt, dann gibt NOT(P)
ebenfalls NULL zurück.
In SQL können Prädikate in CHECK
-Einschränkungen, WHERE
- und HAVING
-Klauseln, CASE
-Ausdrücken, der IIF()
-Funktion und in der ON
-Bedingung von JOIN
-Klauseln und überall in einer normalen vorkommen Ausdruck auftreten kann.
Eine Behauptung ist ein Statement über Daten, die, wie ein Prädikat, zu TRUE, FALSE oder NULL aufgelöst werden können.Behauptungen bestehen aus einem oder mehr Prädikaten, möglicherweise mittels NOT
negiert und verbunden durch AND
- sowie OR
-Operatoren.Klammern können verwendet werden um Prädikate zu gruppieren und die Ausführungsreihenfolge festzulegen.
Ein Prädikat kann andere Prädikate einbetten.Die Ausführung ist nach außen gerichtet, das heißt, das innenliegendste Prädikat wird zuerst ausgeführt.Jede “Ebene” wird in ihrer Rangfolge ausgewertet bis der Wahrheitsgehalt der endgültigen Behauptung aufgelöst wird.
Ein Vergleichsprädikat besteht aus zwei Ausdrücken, die mit einem Vergelichsoperator verbunden sind.Es existieren traditionel sechs Vergleichsoperatoren:
=, >, <, >=, <=, <>
Für die vollständige Liste der Vergleichsoperatoren mit ihren Variantenformen siehe Vergleichsoperatoren.
Wenn eine der Seiten (links oder rechts) eines Vergleichsprädikats NULL
darin hat, wird der Wert des Prädikats UNKNOWN.
Abrufen von Informationen über Computer mit der CPU-Frequenz nicht weniger als 500 MHz und der Preis niedriger als $800:
SELECT *
FROM Pc
WHERE speed >= 500 AND price < 800;
Abrufen von Informationen über alle Punktmatrixdrucker, die weniger als $300 kosten:
SELECT *
FROM Printer
WHERE ptrtype = 'matrix' AND price < 300;
Die folgende Abfrage gibt keine Daten zurück, auch nicht wenn es Drucker ohne zugewiesenen Typ gibt, da ein Prädikat, das NULL
mit NULL
vergleicht, NULL
zurückgibt:
SELECT *
FROM Printer
WHERE ptrtype = NULL AND price < 300;
Andererseits kann ptrtype
auf NULL
getestet werden und ein Ergebnis zurückgeben: es ist nur kein _Vergleichstest:
SELECT *
FROM Printer
WHERE ptrtype IS NULL AND price < 300;
— Siehe auch [fblangref40-commons-isnotnull-de].
Note
|
Hinweis zu String-Vergleichen
Wenn die Felder |
Andere Vergleichsprädikate werden durch Schlüsselwörter gekennzeichnet.
BETWEEN
DSQL, PSQL, ESQL
<value> [NOT] BETWEEN <value_1> AND <value_2>
Das Prädikat BETWEEN
testet, ob ein Wert in einen angegebenen Bereich von zwei Werten fällt.(NOT BETWEEN
testet, ob der Wert nicht in diesen Bereich fällt.)
Die Operanden für das Prädikat BETWEEN
sind zwei Argumente kompatibler Datentypen.Im Gegensatz zu einigen anderen DBMS ist das Prädikat BETWEEN
in Firebird nicht symmetrisch — wenn der niedrigere Wert nicht das erste Argument ist, gibt das Prädikat BETWEEN
immer FALSE zurück.Die Suche ist inklusiv (die von beiden Argumenten repräsentierten Werte werden in die Suche eingeschlossen).Mit anderen Worten, das Prädikat BETWEEN
könnte umgeschrieben werden:
<value> >= <value_1> AND <value> <= <value_2>
Wenn BETWEEN
in den Suchbedingungen von DML-Abfragen verwendet wird, kann der Firebird-Optimierer einen Index für die durchsuchte Spalte verwenden, falls dieser verfügbar ist.
SELECT *
FROM EMPLOYEE
WHERE HIRE_DATE BETWEEN date '1992-01-01' AND CURRENT_DATE
LIKE
DSQL, PSQL, ESQL
<match_value> [NOT] LIKE <pattern> [ESCAPE <escape character>] <match_value> ::= character-type expression <pattern> ::= search pattern <escape character> ::= escape character
Das Prädikat LIKE
vergleicht den zeichenartigen Ausdruck mit dem im zweiten Ausdruck definierten Muster.Die Groß-/Kleinschreibung oder Akzent-Sensitivität für den Vergleich wird durch die verwendete Kollatierung bestimmt.Bei Bedarf kann für jeden Operanden eine Kollatierung angegeben werden.
Zwei Wildcard-Zeichen sind für die Suche verfügbar:
Das Prozentzeichen (%
) berücksichtigt alle Sequenzen von null oder mehr Zeichen im getesteten Wert
Das Unterstrichzeichen (_
) berücksichtigt jedes beliebige Einzelzeichen im getesteten Wert
Wenn der getestete Wert dem Muster entspricht, unter Berücksichtigung von Wildcard-Zeichen ist das Prädikat TRUE.
ESCAPE
-Zeichen-OptionWenn der Such-String eines der Wildcard-Zeichen beinhaltet, kann die ESCAPE
-Klausel verwendet werden, um ein Escape-Zeichen zu definieren.Das Escape-Zeichen muss im Suchstring vor dem Symbol ‘%
’ oder ‘_
’ stehen, um anzuzeigen, dass das Symbol als Literalzeichen interpretiert werden soll.
LIKE
Finde die Nummern der Abteilung, deren Namen mit dem Wort “Software” starten:
SELECT DEPT_NO
FROM DEPT
WHERE DEPT_NAME LIKE 'Software%';
Es ist möglich einen Index für das Feld DEPT_NAME zu verwenden, sofern dieser existiert.
Note
|
Über
LIKE und den OptimizerEigentlich verwendet das Somit gilt — wenn Sie nach einem Wortanfang suchen, sollten Sie das Prädikat |
Suchen Sie nach Mitarbeitern, deren Namen aus 5 Buchstaben bestehen, mit den Buchstaben “Sm” beginnen und mit “th” enden. Das Prädikat gilt für Namen wie “Smith” und “Smyth”.
SELECT
first_name
FROM
employee
WHERE first_name LIKE 'Sm_th'
Suche nach allen Mandanten, deren Adresse den String “Rostov” enthält:
SELECT *
FROM CUSTOMER
WHERE ADDRESS LIKE '%Rostov%'
Note
|
Benötigen Sie eine Suche, die Groß- und Kleinschreibung innerhalb einer Zeichenkette ignoriert ( |
Suchen Sie nach Tabellen, die den Unterstrich im Namen enthalten.Als Escape-Zeichen wird das Zeichen ‘#
’ verwendet:
SELECT
RDB$RELATION_NAME
FROM RDB$RELATIONS
WHERE RDB$RELATION_NAME LIKE '%#_%' ESCAPE '#'
STARTING WITH
DSQL, PSQL, ESQL
<value> [NOT] STARTING WITH <value>
Das Prädikat STARTING WITH
sucht nach einer Zeichenkette oder einem zeichenkettenähnlichen Datentyp, die mit den Zeichen des Argumentes value beginnt.Die Suche unterscheidet zwischen Groß- und Kleinschreibung.
Wenn STARTING WITH
als Suchkriterium in DML-Abfragen verwendet wird, nutzt der Firebird-Optimizer einen Index auf der Suchspalte, sofern vorhanden.
Suche nach Mitarbeitern deren Namen mit “Jo” beginnen:
SELECT LAST_NAME, FIRST_NAME
FROM EMPLOYEE
WHERE LAST_NAME STARTING WITH 'Jo'
CONTAINING
DSQL, PSQL, ESQL
<value> [NOT] CONTAINING <value>
Das Prädikat CONTAINING
sucht nach einem String oder einem stringähnlichen Typ und sucht nach der Zeichenfolge, die seinem Argument entspricht.Es kann für eine alphanumerische (stringartige) Suche nach Zahlen und Datumsangaben verwendet werden.Bei einer CONTAINING
-Suche wird die Groß-/Kleinschreibung nicht beachtet.Wenn jedoch eine akzentsensitive Sortierung verwendet wird, erfolgt die Suche akzentsensitiver.
Suche nach Projekten, deren Namen die Teilzeichenfolge “Map” enthalten:
SELECT *
FROM PROJECT
WHERE PROJ_NAME CONTAINING 'Map';
Zwei Zeilen mit den Namen “AutoMap” und “MapBrowser port” werden zurückgegeben.
Suche nach Änderungen in den Gehältern, die die Zahl 84 im Datum enthalten (in diesem Falle heißt dies, Änderungen im Jahr 1984):
SELECT *
FROM SALARY_HISTORY
WHERE CHANGE_DATE CONTAINING 84;
SIMILAR TO
DSQL, PSQL
string-expression [NOT] SIMILAR TO <pattern> [ESCAPE <escape-char>] <pattern> ::= an SQL regular expression <escape-char> ::= a single character
SIMILAR TO
findet eine Zeichenkette anhand eines Regulären Ausdruck-Musters in SQL (engl. SQL Regular Expression Pattern).Anders als in einigen anderen Sprachen muss das Muster mit der gesamten Zeichenkette übereinstimmen, um erfolgreich zu sein — die Übereinstimmung eines Teilstrings reicht nicht aus.Ist ein Operand NULL
, ist auch das Ergebnis NULL
.Andernfalls ist das Ergebnis TRUE
oder FALSE
.
Um mit einem Sonderzeichen in regulären Ausdrücken abzugleichen, muss dieses Zeichen mit Escapezeichen versehen werden.Es gibt kein Standard-Escape-Zeichen;Stattdessen gibt der Benutzer bei Bedarf eine an:
'Peer (Poire)' similar to 'P[^ ]+ \(P[^ ]+\)' escape '\' -- true
'Pera [Pear]' similar to 'P[^ ]+ #[P[^ ]+#]' escape '#' -- true
'Päron-äppledryck' similar to 'P%$-ä%' escape '$' -- true
'Pärondryck' similar to 'P%--ä%' escape '-' -- false
Die letzte Zeile demonstriert, dass das Escape-Zeichen auch sich selbst escapen kann, wenn notwendig.
Die folgende Syntax definiert das SQL-Standardausdruckformat.Es ist eine komplette und korrekte Top-down-Definition.Es ist auch sehr formell, ziemlich lang und vermutlich perfekt geeignet, jeden zu entmutigen, der nicht schon Erfahrungen mit Regulären Ausdrücken (oder mit sehr formalen, eher langen Top-down-Definitionen) gesammelt hat.Fühlen Sie sich frei, dies zu überspringen und den nächsten Abschnitt, Aufbau Regulärer Ausdrücke, zu lesen, der einen Bottom-up-Ansatz verfolgt und sich an den Rest von uns richtet.
<regular expression> ::= <regular term> ['|' <regular term> ...] <regular term> ::= <regular factor> ... <regular factor> ::= <regular primary> [<quantifier>] <quantifier> ::= ? | * | + | '{' <m> [,[<n>]] '}' <m>, <n> ::= unsigned int, mit <m> <= <n> wenn beide vorhanden <regular primary> ::= <character> | <character class> | % | (<regular expression>) <character> ::= <escaped character> | <non-escaped character> <escaped character> ::= <escape-char> <special character> | <escape-char> <escape-char> <special character> ::= eines der Zeichen []()|^-+*%\?{} <non-escaped character> ::= ein Zeichen, das nicht ein <special character> ist und nicht gleich <escape-char> (wenn definiert)_ <character class> ::= '' | '[' <member> ... ']' | '[^' <non-member> ... ']' | '[' <member> ... '^' <non-member> ... ']' <member>, <non-member> ::= <character> | <range> | <predefined class> <range> ::= <character>-<character> <predefined class> ::= '[:' <predefined class name> ':]' <predefined class name> ::= ALPHA | UPPER | LOWER | DIGIT | ALNUM | SPACE | WHITESPACE
Dieser Abschnitt behandelt die Elemente und Regeln zum Aufbau Regulärer Ausdrücke in SQL.
Innerhalb Regulärer Ausdrücke repräsentieren die meisten Zeichen sich selbst.Die einzige Ausnahme bilden die folgenden Zeichen:
[ ] ( ) | ^ - + * % _ ? { }
... und das Escape-Zeichen, sofern definiert.
Ein Regulärer Ausdruck, der keine Sonderzeichen oder Escape-Zeichen beinhaltet, findet nur Strings, die identisch zu sich selbst sind (abhängig von der verwendeten Collation).Das heißt, es agiert wie der ‘=
’-Operator:
'Apple' similar to 'Apple' -- true
'Apples' similar to 'Apple' -- false
'Apple' similar to 'Apples' -- false
'APPLE' similar to 'Apple' -- abhängig von der Collation
Die bekannten SQL-Wildcards ‘_
’ und ‘%
’ finden beliebige Einzelzeichen und Strings beliebiger Länge:
'Birne' similar to 'B_rne' -- true
'Birne' similar to 'B_ne' -- false
'Birne' similar to 'B%ne' -- true
'Birne' similar to 'Bir%ne%' -- true
'Birne' similar to 'Birr%ne' -- false
Beachten Sie, wie ‘%
’ auch den leeren String berücksichtigt.
Ein Bündel von Zeichen, die in Klammern eingeschlossen sind, definiert eine Zeichenklasse.Ein Zeichen in der Zeichenfolge entspricht einer Klasse im Muster, wenn das Zeichen Mitglied der Klasse ist:
'Citroen' similar to 'Cit[arju]oen' -- true
'Citroen' similar to 'Ci[tr]oen' -- false
'Citroen' similar to 'Ci[tr][tr]oen' -- true
Wie aus der zweiten Zeile ersichtlich ist, entspricht die Klasse nur einem einzigen Zeichen, nicht einer Sequenz.
Innerhalb einer Klassendefinition definieren zwei Zeichen, die durch einen Bindestrich verbunden sind, einen Bereich.Ein Bereich umfasst die beiden Endpunkte und alle Zeichen, die zwischen ihnen in der aktiven Sortierung liegen.Bereiche können überall in der Klassendefinition ohne spezielle Begrenzer platziert werden, um sie von den anderen Elementen zu trennen.
'Datte' similar to 'Dat[q-u]e' -- true
'Datte' similar to 'Dat[abq-uy]e' -- true
'Datte' similar to 'Dat[bcg-km-pwz]e' -- false
Die folgenden vordefinierten Zeichenklassen können auch in einer Klassendefinition verwendet werden:
[:ALPHA:]
Lateinische Buchstaben a..z und A..Z.Mit einer akzentunempfindlichen Sortierung stimmt diese Klasse auch mit akzentuierten Formen dieser Zeichen überein.
[:DIGIT:]
Dezimalziffern 0..9.
[:ALNUM:]
Gesamtheit aus [:ALPHA:]
und [:DIGIT:]
.
[:UPPER:]
Großgeschriebene Form der lateinischen Buchstaben A..Z.Findet auch kleingeschriebene Strings mit groß- und kleinschreibunempfindlicher Collation sowie akzentunempfindlicher Collation.
[:LOWER:]
Kleingeschriebene Form der lateinischen Buchstaben A..Z.Findet auch großgeschriebene Strings mit groß- und kleinschreibunempfindlicher Collation sowie akzentunempfindlicher Collation.
[:SPACE:]
Findet das Leerzeichen (ASCII 32).
[:WHITESPACE:]
Findet horizontalen Tabulator (ASCII 9), Zeilenvorschub (ASCII 10), vertikalen Tabulator (ASCII 11), Seitenvorschub (ASCII 12), Wagenrücklauf (ASCII 13) und Leerzeichen (ASCII 32).
Das Einbinden einer vordefinierten Klasse hat den gleichen Effekt wie das Einbinden all seiner Mitglieder.Vordefinierte Klassen sind nur in Klassendefinitionen erlaubt.Wenn Sie gegen eine vordefinierte Klasse prüfen und gegen nichts sonst, platzieren Sie ein zusätzliches Paar von Klammern um sie herum.
'Erdbeere' similar to 'Erd[[:ALNUM:]]eere' -- true
'Erdbeere' similar to 'Erd[[:DIGIT:]]eere' -- false
'Erdbeere' similar to 'Erd[a[:SPACE:]b]eere' -- true
'Erdbeere' similar to [[:ALPHA:]] -- false
'E' similar to [[:ALPHA:]] -- true
Wenn eine Klassendefinition mit einem Caret-Zeichen beginnt, wird alles, was folgt, aus der Klasse ausgeschlossen.Alle anderen Zeichen stimmen überein:
'Framboise' similar to 'Fra[^ck-p]boise' -- false
'Framboise' similar to 'Fr[^a][^a]boise' -- false
'Framboise' similar to 'Fra[^[:DIGIT:]]boise' -- true
If the caret is not placed at the start of the sequence, the class contains everything before the caret, except for the elements that also occur after the caret:
'Grapefruit' similar to 'Grap[a-m^f-i]fruit' -- true
'Grapefruit' similar to 'Grap[abc^xyz]fruit' -- false
'Grapefruit' similar to 'Grap[abc^de]fruit' -- false
'Grapefruit' similar to 'Grap[abe^de]fruit' -- false
'3' similar to '[[:DIGIT:]^4-8]' -- true
'6' similar to '[[:DIGIT:]^4-8]' -- false
Zuletzt sei noch erwähnt, dass die Wildcard-Zeichen ‘_
’ eine eigene Zeichenklasse sind, die einem beliebigen einzelnen Zeichen entspricht.
Ein Fragezeichen, direkt von einem weiteren Zeichen oder Klasse gefolgt, gibt an, dass das folgende Element gar nicht oder einmalig vorkommen darf:
'Hallon' similar to 'Hal?on' -- false
'Hallon' similar to 'Hal?lon' -- true
'Hallon' similar to 'Halll?on' -- true
'Hallon' similar to 'Hallll?on' -- false
'Hallon' similar to 'Halx?lon' -- true
'Hallon' similar to 'H[a-c]?llon[x-z]?' -- true
Ein Sternchen (‘*
’) unmittelbar nach einem Zeichen oder einer Klasse zeigt an, dass das vorangehende Element 0-mal oder öfter vorkommen kann, damit es übereinstimmt:
'Icaque' similar to 'Ica*que' -- true
'Icaque' similar to 'Icar*que' -- true
'Icaque' similar to 'I[a-c]*que' -- true
'Icaque' similar to '_*' -- true
'Icaque' similar to '[[:ALPHA:]]*' -- true
'Icaque' similar to 'Ica[xyz]*e' -- false
Ein Pluszeichen (‘+
’) unmittelbar nach einem Zeichen oder einer Klasse gibt an, dass das vorangehende Element mindestens einmal vorkommen muss, damit es übereinstimmt:
'Jujube' similar to 'Ju_+' -- true
'Jujube' similar to 'Ju+jube' -- true
'Jujube' similar to 'Jujuber+' -- false
'Jujube' similar to 'J[jux]+be' -- true
'Jujube' sililar to 'J[[:DIGIT:]]+ujube' -- false
Wenn auf ein Zeichen oder eine Klasse eine Zahl in geschweiften Klammern folgt (‘{
’ und ‘}
’), muss sie genau so oft wiederholt werden, damit sie übereinstimmt:
'Kiwi' similar to 'Ki{2}wi' -- false
'Kiwi' similar to 'K[ipw]{2}i' -- true
'Kiwi' similar to 'K[ipw]{2}' -- false
'Kiwi' similar to 'K[ipw]{3}' -- true
Wenn der Zahl ein Komma folgt (‘,
’), muss das Element mindestens so oft wiederholt werden, damit es übereinstimmt:
'Limone' similar to 'Li{2,}mone' -- false
'Limone' similar to 'Li{1,}mone' -- true
'Limone' similar to 'Li[nezom]{2,}' -- true
Wenn die geschweiften Klammern zwei durch ein Komma getrennte Zahlen enthalten, wobei die zweite Zahl nicht kleiner als die erste ist, muss das Element mindestens die erste Zahl und höchstens die zweite Zahl wiederholt werden, um zu entsprechen:
'Mandarijn' similar to 'M[a-p]{2,5}rijn' -- true
'Mandarijn' similar to 'M[a-p]{2,3}rijn' -- false
'Mandarijn' similar to 'M[a-p]{2,3}arijn' -- true
Die Bezeichner ‘?
’, ‘*
’ und ‘+
’ sind Kurzschreibweisen für {0,1}
, {0,}
und {1,}
.
Reguläre Ausdrücke können Oder-verknüpft werden mittels ‘|
’-Operator.Eine Gesamtübereinstimmung tritt auf, wenn die Argumentzeichenkette mit mindestens einem Term übereinstimmt.
'Nektarin' similar to 'Nek|tarin' -- false
'Nektarin' similar to 'Nektarin|Persika' -- true
'Nektarin' similar to 'M_+|N_+|P_+' -- true
Ein oder mehrere Teile der regulären Ausdrücke können in Unterausdrücke gruppiert werden (auch Untermuster genannt), indem diese in runde Klammern eingeschlossen werden.Ein Unterausdruck ist ein eigener regulärer Ausdruck.Dieser kann alle erlaubten Elemente eines regulären Ausdrucks enthalten, und auch eigene Bezeichner.
'Orange' similar to 'O(ra|ri|ro)nge' -- true
'Orange' similar to 'O(r[a-e])+nge' -- true
'Orange' similar to 'O(ra){2,4}nge' -- false
'Orange' similar to 'O(r(an|in)g|rong)?e' -- true
IS [NOT] DISTINCT FROM
DSQL, PSQL
<operand1> IS [NOT] DISTINCT FROM <operand2>
Zwei Operanden werden als DISTINCT angesehen, wenn sie unterschiedliche Werte besitzen oder wenn einer NULL
ist und der andere nicht-NULL
.Sie werden als NOT DISTINCT angesehen, wenn sie den gleichen Wert besitzen oder beide Operanden NULL
sind.
IS [NOT] DISTINCT FROM
liefert immer TRUE oder FALSE und niemals UNKNOWN (NULL) (unbekannter Wert).Die Operatoren ‘=
’ und ‘<>
’ geben umgekehrt UNKNOWN (NULL) zurück, wenn einer oder beide Operanden NULL sind.
Operandenwerte |
Ergebnis verschiedener Prädikate |
|||
---|---|---|---|---|
|
|
|
|
|
Gleiche Werte |
|
|
|
|
Verschiedene Werte |
|
|
|
|
Beide |
|
|
|
|
Einer |
|
|
|
|
SELECT ID, NAME, TEACHER
FROM COURSES
WHERE START_DAY IS NOT DISTINCT FROM END_DAY;
-- PSQL-Fragment
IF (NEW.JOB IS DISTINCT FROM OLD.JOB)
THEN POST_EVENT 'JOB_CHANGED';
IS [NOT]
DSQL, PSQL
<value> IS [NOT] { TRUE | FALSE | UNKNOWN }
Das IS
-Prädikat mit booleschen Literalwerten prüft, ob der Ausdruck auf der linken Seite mit dem booleschen Wert auf der rechten Seite übereinstimmt.Der Ausdruck auf der linken Seite muss vom Typ BOOLEAN
sein, sonst kommt es zu einer Ausnahme.
Das IS [NOT] UNKNOWN
entspricht IS [NOT] NULL
.
Note
|
Die rechte Seite des Prädikats akzeptiert nur die Literale |
-- FALSE-Wert prüfen
SELECT * FROM TBOOL WHERE BVAL IS FALSE;
ID BVAL
============= =======
2 <false>
-- UNKNOWN-Wert prüfen
SELECT * FROM TBOOL WHERE BVAL IS UNKNOWN;
ID BVAL
============= =======
3 <null>
IS [NOT] NULL
DSQL, PSQL, ESQL
<value> IS [NOT] NULL
Da NULL
kein Wert ist, sind diese Operatoren keine Vergleichsoperatoren.Das Prädikat IS [NOT] NULL
prüft die Behauptung, dass der Ausdruck auf der linken Seite einen Wert (IS NOT NULL) oder keinen Wert hat (IS NULL).
Suche nach Verkäufen, die kein Versanddatum besitzen:
SELECT * FROM SALES
WHERE SHIP_DATE IS NULL;
Note
|
Hinweis bezüglich des IS-Prädikates
Bis einschließlich Firebird 2.5, hat das Prädikat |
Diese Gruppe von Prädikaten umfasst diejenigen, die Unterabfragen verwenden, um Werte für alle Arten von Zusicherungen in Suchbedingungen zu übermitteln.Existenzielle Prädikate werden so genannt, weil sie verschiedene Methoden verwenden, um auf existence oder non-existence einer Bedingung zu testen, und TRUE
zurückgeben, wenn die Existenz oder Nichtexistenz bestätigt wird oder FALSE
andernfalls.
EXISTS
DSQL, PSQL, ESQL
[NOT] EXISTS (<select_stmt>)
Das Prädikat EXISTS
verwendet als Argument einen Unterabfrageausdruck.Es gibt TRUE
zurück, wenn das Ergebnis der Unterabfrage mindestens eine Zeile enthalten würde; andernfalls gibt es FALSE
zurück.
NOT EXISTS
gibt FALSE
zurück, wenn das Ergebnis der Unterabfrage mindestens eine Zeile enthalten würde; andernfalls gibt es TRUE
zurück.
Note
|
Die Unterabfrage kann mehrere Spalten enthalten, oder |
Finde die Mitarbeiter, die Projekte haben.
SELECT *
FROM employee
WHERE EXISTS(SELECT *
FROM employee_project ep
WHERE ep.emp_no = employee.emp_no)
Finde die Mitarbeiter, die keine Projekte haben.
SELECT *
FROM employee
WHERE NOT EXISTS(SELECT *
FROM employee_project ep
WHERE ep.emp_no = employee.emp_no)
IN
DSQL, PSQL, ESQL
<value> [NOT] IN (<select_stmt> | <value_list>) <value_list> ::= <value_1> [, <value_2> …]
Das Prädikat IN
prüft, ob der Wert des Ausdrucks auf der linken Seite im Wertesatz der rechten Seite vorkommt.Der Wertesatz darf nicht mehr als 1500 Elemente enthalten.Das IN
-Prädikat kann mit folgender äquivalenter Form ersetzt werden:
(<value> = <value_1> [OR <value> = <value_2> …]) <value> = { ANY | SOME } (<select_stmt>)
Wenn das Prädikat IN
als Suchbedingung in DML-Abfragen verwendet wird, kann der Firebird-Optimizer einen Index auf die Suchspalte nutzen, sofern einer vorhanden ist.
In seiner zweiten Form prüft das Prädikat IN
, ob der linke Ausdruckswert im Ergebnis der Unterabfrage vorhanden ist (oder nicht vorhanden, wenn NOT IN
verwendet wird).
Die Unterabfrage darf nur eine Spalte abfragen, andernfalls wird es zum Fehler “count of column list and variable list do not match” kommen.
Abfragen, die das Prädikat IN
mit einer Unterabfrage verwenden, können durch eine ähnliche Abfrage mittels des EXISTS
-Prädikates ersetzt werden.Zum Beispiel folgende Abfrage:
SELECT
model, speed, hd
FROM PC
WHERE
model IN (SELECT model
FROM product
WHERE maker = 'A');
kann ersetzt werden mittels EXISTS-Prädikat:
SELECT
model, speed, hd
FROM PC
WHERE
EXISTS (SELECT *
FROM product
WHERE maker = 'A'
AND product.model = PC.model);
Jedoch gilt zu beachten, dass eine Abfrage mittels NOT IN
und einer Unterabfrage nicht immer das gleiche Ergebnis zurückliefert wie sein Gegenpart mit NOT EXISTS
.Dies liegt daran, dass EXISTS
immer TRUE oder FALSE zurückgibt, wohingegen IN
NULL
in diesen beiden Fällen zurückliefert:
wenn der geprüfte Wert NULL
ist und die IN ()
-Liste nicht leer ist
wenn der geprüfte Wert keinen Treffer in der IN ()
-Liste enthält und mindestens ein Element NULL
ist.
Nur in diesen beiden Fällen wird IN ()
NULL
zurückgeben, während das EXISTS
-Prädikat FALSE
zurückgibt ('keine passende Zeile gefunden', engl. 'no matching row found').In einer Suche oder, zum Beispiel in einem IF (…)
-Statement, bedeuten beide Ergebnisse einen “Fehler” und es macht damit keinen Unterschied.
Aber für die gleichen Daten gibt NOT IN ()
NULL
zurück, während NOT EXISTS
TRUE
zurückgibt, was das Gegenteilige Ergebnis ist.
Schauen wir uns das folgendes Beispiel an:
-- Suche nach Bürgern die nicht am gleichen Tag wie eine
-- berühmte New Yorker Persönlichkeit geboren wurden
SELECT P1.name AS NAME
FROM Personnel P1
WHERE P1.birthday NOT IN (SELECT C1.birthday
FROM Celebrities C1
WHERE C1.birthcity = 'New York');
Nehmen wir nun an, dass die Liste der New Yorker Berühmtheiten nicht leer ist und mindestens einen NULL-Geburtstag aufweist.Dann gilt für alle Bürger, die nicht am gleichen Tag mit einer Berühmtheit Geburtstag haben, dass NOT IN
NULL
zurückgibt, da dies genau das ist was IN
tut.Die Suchbedingung wurde nicht erfüllt und die Bürger werden nicht im Ergebnis des SELECT
berücksichtigt, da die Aussage falsch ist.
Bürger, die am gleichen Tag wie eine Berühmtheit Geburtstag feiern, wird NOT IN
korrekterweise FALSE
zurückgeben, womit diese ebenfalls aussortiert werden, und damit keine Zeile zurückgegeben wird.
Wird die Form NOT EXISTS
verwendet:
-- Suche nach Bürgern, die nicht am gleichen Tag wie eine
-- berühmte New Yorker Persönlichkeit geboren wurden
SELECT P1.name AS NAME
FROM Personnel P1
WHERE NOT EXISTS (SELECT *
FROM Celebrities C1
WHERE C1.birthcity = 'New York'
AND C1.birthday = P1.birthday);
nicht-Übereinstimmungen werden im NOT EXISTS
-Ergebnis TRUE
erhalten und ihre Datensätze landen im Rückgabesatz.
Tip
|
Wenn bei der Suche nach einer Nichtübereinstimmung die Möglichkeit besteht, dass |
Finde Mitarbeiter mit den Namen “Pete”, “Ann” und “Roger”:
SELECT *
FROM EMPLOYEE
WHERE FIRST_NAME IN ('Pete', 'Ann', 'Roger');
Finde alle Computer, die deren Hersteller mit dem Buchstaben “A” beginnt:
SELECT
model, speed, hd
FROM PC
WHERE
model IN (SELECT model
FROM product
WHERE maker STARTING WITH 'A');
SINGULAR
DSQL, PSQL, ESQL
[NOT] SINGULAR (<select_stmt>)
Das Prädikat SINGULAR
nimmt eine Unterabfrage als Argument und wertet sie als TRUE, wenn die Unterabfrage genau eine Ergebniszeile zurückgibt; andernfalls wird das Prädikat als FALSE ausgewertet.Die Unterabfrage kann mehrere Ausgabespalten auflisten, da die Zeilen sowieso nicht zurückgegeben werden.Sie werden nur auf (singuläre) Existenz geprüft.Der Kürze halber wird normalerweise ‘SELECT *
’ angegeben.Das Prädikat SINGULAR
kann nur zwei Werte zurückgeben: TRUE
oder FALSE
.
Finden Sie die Mitarbeiter, die nur ein Projekt haben.
SELECT *
FROM employee
WHERE SINGULAR(SELECT *
FROM employee_project ep
WHERE ep.emp_no = employee.emp_no)
Ein Quantifizierer ist ein logischer Operator, der die Anzahl der Objekte festlegt, für die diese Behauptung wahr ist.Es ist keine numerische Größe, sondern eine logische, die die Behauptung mit dem vollen Satz möglicher Objekte verbindet.Solche Prädikate basieren auf logischen universellen und existentiellen Quantifizierern, die in der formalen Logik erkannt werden.
In Unterabfrageausdrücken ermöglichen quantifizierte Prädikate den Vergleich einzelner Werte mit den Ergebnissen von Unterabfragen;sie haben die folgende gemeinsame Form:
<value expression> <comparison operator> <quantifier> <subquery>
ALL
DSQL, PSQL, ESQL
<value> <op> ALL (<select_stmt>)
Wenn der ALL
-Quantifizierer verwendet wird, ist das Prädikat TRUE, wenn jeder Wert, der von der Unterabfrage zurückgegeben wird, die Bedingung des Prädikates in der Hauptabfrage erfüllt ist.
Zeige nur jene Kunden an, deren Bewertungen höher sind als die Bewertung jedes Kunden in Paris.
SELECT c1.*
FROM Customers c1
WHERE c1.rating > ALL
(SELECT c2.rating
FROM Customers c2
WHERE c2.city = 'Paris')
Important
|
Wenn die Unterabfrage einen leeren Satz zurückgibt, ist das Prädikat TRUE für jeden linken Wert, unabhängig vom Operator.Dies mag widersprüchlich erscheinen, denn jeder linke Wert wird gegenüber dem rechten betrachtet als: kleiner als, größer als, gleich sowie ungleich. Dennoch passt dies perfekt in die formale Logik: Wenn der Satz leer ist, ist das Prädikat 0 mal wahr, d.h. für jede Zeile im Satz. |
ANY
and SOME
DSQL, PSQL, ESQL
<value> <op> {ANY | SOME} (<select_stmt>)
Die Quantifizierer ANY
und SOME
sind in ihrem Verhalten identisch.Offensichtlich sind beide im SQL-Standard vorhanden, so dass sie austauschbar verwendet werden können, um die Lesbarkeit der Operatoren zu verbessern.Wird der ANY
- oder SOME
-Quantifizierer verwendet, ist das Prädikat TRUE, wenn einer der zurückgegebenen Werte der Unterabfrage die Suchbedingung der Hauptabfrage erfüllt.Gibt die Unterabfrage keine Zeile zurück, wird das Prädikat automtisch als FALSE angesehen.
Zeige nur die Kunden, deren Bewertungen höher sind als die eines oder mehrerer Kunden in Rom.
SELECT *
FROM Customers
WHERE rating > ANY
(SELECT rating
FROM Customers
WHERE city = 'Rome')