Konstanten
Eine Konstante ist ein Wert der direkt in einem SQL-Statement verwendet wird und weder von einem Ausdruck, einem Parameter, einem Spaltenverweis noch einer Variablen abgeleitet wird.Dies kann eine Zeichenkette oder eine Zahl sein.
Eine Konstante ist ein Wert der direkt in einem SQL-Statement verwendet wird und weder von einem Ausdruck, einem Parameter, einem Spaltenverweis noch einer Variablen abgeleitet wird.Dies kann eine Zeichenkette oder eine Zahl sein.
Eine String-Konstante ist eine Aneinanderreihung von Zeichen, die zwischen einem Paar von Apostrophen (“einfache Anführungszeichen”) eingeschlossen werden.Die größtmögliche Länge dieser Zeichenketten ist 32.767 Bytes;die maximale Anzahl der Zeichen wird durch die verwendete Zeichenkodierung bestimmt.
Note
|
|
Es wird angenommen, dass der Zeichensatz einer Zeichenkonstanten der gleiche ist wie der Zeichensatz seines Bestimmungsspeichers.
Ab Firebird 2.5 können String-Literale in hexadezimaler Notation eingegeben werden, sogenannte “binary strings”.Jedes Paar von Hex-Ziffern definiert ein Byte in der Zeichenfolge.Auf diese Weise eingegebene Zeichenfolgen haben standardmäßig den Typ BINARY
(oder den Zeichensatz OCTETS
), es sei denn, die Introducer-Syntax wird verwendet, um eine Zeichenkette als anderen Zeichensatz zu interpretieren.
{x|X}'<hexstring>' <hexstring> ::= eine gerade Anzahl von <hexdigit> <hexdigit> ::= eines aus 0..9, A..F, a..f
select x'4E657276656E' from rdb$database
-- liefert 4E657276656E, ein 6-Byte 'Binärstring'
select _ascii x'4E657276656E' from rdb$database
-- liefert 'Nerven' (gleiche Zeichenfolge, jetzt als ASCII-Text interpretiert)
select _iso8859_1 x'53E46765' from rdb$database
-- liefert 'Säge' (4 Zeichen, 4 Bytes)
select _utf8 x'53C3A46765' from rdb$database
-- liefert 'Säge' (4 Zeichen, 5 Bytes)
Note
|
Hinweise
Die Client-Schnittstelle legt fest, wie Binärzeichenfolgen dem Benutzer angezeigt werden.Das isql-Werkzeug beispielsweise, nutzt großgeschriebene Buchstaben A-F, während FlameRobin Kleinschreibung verwendet.Andere Client-Applikationen könnten andere Konventionen bevorzugen, zum Beispiel Leerzeichen zwischen den Bytepaaren: '4E 65 72 76 65 6E'. Mit der hexadezimalen Notation kann jeder Bytewert (einschließlich 00) an beliebiger Stelle im String eingefügt werden.Allerdings, wenn Sie diesen auf etwas anderes als OCTETS erzwingen wollen, liegt es in Ihrer Verantwortung, die Bytes in einer Sequenz zu liefern, die für den Zielzeichensatz gültig ist. |
Seit Firebird 3.0 ist es möglich, ein anderes Zeichen oder Zeichenpaar als das doppelte (escaped) Apostroph zu verwenden, um einen String in Anführungszeichen in einen anderen String einzubetten, ohne dass das Anführungszeichen maskiert werden muss.Das Schlüsselwort q
oder Q
vor einem String in Anführungszeichen informiert den Parser darüber, dass bestimmte Links-Rechts-Paare oder Paare identischer Zeichen innerhalb des Strings die Begrenzer des eingebetteten String-Literals sind.
<alternative string literal> ::= { q | Q } <quote> <start char> [<char> ...] <end char> <quote>
Note
|
Regeln
Wenn Innerhalb des Strings, d. h. |
select q'{abc{def}ghi}' from rdb$database; -- Ergebnis: abc{def}ghi
select q'!That's a string!' from rdb$database; -- Ergebnis: That's a string
Gegebenenfalls kann einem Zeichenfolgenliteral ein Zeichensatzname vorangestellt werden, dem ein Unterstrich “_” vorangestellt ist.Dies ist als Introducer-Syntax bekannt.Sein Zweck besteht darin, die Engine darüber zu informieren, wie die eingehende Zeichenfolge zu interpretieren und zu speichern ist.
Beispiel
INSERT INTO People
VALUES (_ISO8859_1 'Hans-Jörg Schäfer')
Eine Zahlkonstante ist eine gültige Zahl in einer unterstützten Notation:
In SQL wird der Dezimalpunkt, für Zahlen in der Standard-Dezimal-Notation, immer durch das Punkt-Zeichen dargestellt.Tausender werden nicht getrennt.Einbeziehung von Komma, Leerzeichen usw. führt zu Fehlern.
Exponentielle Notation wird unterstützt.Zum Beispiel kann 0.0000234 auch als 2.34e-5
geschrieben werden.
Hexadezimal-Notation wird von Firebird 2.5 und höheren Versionen unterstützt — siehe unten.
Das Format des Literals bestimmt den Typ (<d>
für eine Dezimalziffer, <h>
für eine Hexadezimalziffer):
Format | Typ |
---|---|
|
|
|
|
|
Aus Gründen der Abwärtskompatibilität werden einige Werte von 19 Stellen auf |
|
|
Von Firebird 2.5 aufwärts können ganzzahlige Werte in hexadezimaler Notation eingegeben werden.Zahlen mit 1-8 Hex-Ziffern werden als Typ INTEGER
interpretiert;Zahlen mit 9-16 Hex-Ziffern als Typ BIGINT
.Zahlen mit 17-32 Hex-Ziffern als Typ INT128
.
0{x|X}<hexdigits> <hexdigits> ::= 1-32 of <hexdigit> <hexdigit> ::= one of 0..9, A..F, a..f
select 0x6FAA0D3 from rdb$database -- liefert 117088467
select 0x4F9 from rdb$database -- liefert 1273
select 0x6E44F9A8 from rdb$database -- liefert 1850014120
select 0x9E44F9A8 from rdb$database -- liefert -1639646808 (an INTEGER)
select 0x09E44F9A8 from rdb$database -- liefert 2655320488 (a BIGINT)
select 0x28ED678A4C987 from rdb$database -- liefert 720001751632263
select 0xFFFFFFFFFFFFFFFF from rdb$database -- liefert -1
Hex-Nummern im Bereich 0 .. 7FFF FFFF sind positive INTEGER
mit Dezimalwerten zwischen 0 .. 2147483647.Um eine Zahl als BIGINT
zu erzwingen, müssen Sie genügend Nullen voranstellen, um die Gesamtzahl der Hex-Ziffern auf neun oder mehr zu bringen.Das ändert den Typ, aber nicht den Wert.
Hex-Nummern zwischen 8000 0000 .. FFFF FFFF erfordern etwas Aufmerksamkeit:
Bei der Eingabe mit acht Hex-Ziffern, wie in 0x9E44F9A8, wird ein Wert als 32-Bit-INTEGER
interpretiert.Da das erste Bit (Vorzeichenbit) gesetzt ist, wird es dem negativen Dezimalbereich -2147483648 .. -1 zugeordnet.
Bei einer oder mehreren Nullen, die wie in 0x09E44F9A8 vorangestellt werden, wird ein Wert als 64-Bit-BIGINT
im Bereich 0000 0000 8000 0000 .. 0000 0000 FFFF FFFF interpretiert.Das Zeichen-Bit ist jetzt nicht gesetzt, also wird der Dezimalwert dem positiven Bereich 2147483648 .. 4294967295 zugewiesen.
So ergibt sich in diesem Bereich — und nur in diesem Bereich — anhand einer mathematisch unbedeutenden 0 ein gänzlich anderer Wert.Dies ist zu beachten.
Hex-Zahlen zwischen 1 0000 0000 .. 7FFF FFFF FFFF FFFF sind alle positiv BIGINT
.
Hex-Zahlen zwischen 8000 0000 0000 0000 .. FFFF FFFF FFFF FFFF sind alle negativ BIGINT
.
Ein SMALLINT
kann nicht in Hex geschrieben werden, streng genommen zumindest, da sogar 0x1 als INTEGER
ausgewertet wird.Wenn Sie jedoch eine positive Ganzzahl innerhalb des 16-Bit-Bereichs 0x0000 (Dezimal-Null) bis 0x7FFF (Dezimalzahl 32767) schreiben, wird sie transparent in SMALLINT
umgewandelt.
Es ist möglich einen negativen SMALLINT
in Hex zu schreiben, wobei eine 4-Byte-Hexadezimalzahl im Bereich 0xFFFF8000 (Dezimal -32768) bis 0xFFFFFFFF (Dezimal -1) verwendet wird.
Ein boolesches Literal ist eines von TRUE
, FALSE
oder UNKNOWN
.
Formal definiert der SQL-Standard Datetime-Literale als Präfix DATE
, TIME
und TIMESTAMP
gefolgt von einem String-Literal mit einem Datetime-Format.Historisch gesehen hat die Firebird-Dokumentation diese Datetime-Literale als "Shorthand Casts" bezeichnet.
In Firebird 4.0 ist die Verwendung von Datum/Uhrzeit-Mnemonik in Datetime-Literalen (z.B. DATE 'TODAY'
) nicht mehr erlaubt.
Caution
|
Das Format von Datetime-Literalen und -Strings in Firebird 4.0 ist im Vergleich zu früheren Firebird-Versionen strenger. |
<datetime_literal> ::= DATE '<date_format>' | TIME { '<time_format>' | '<time_tz_format>' } | TIMESTAMP { '<timestamp_format>' | '<timestamp_tz_format>' }
<date_format> ::= [YYYY<p>]MM<p>DD | MM<p>DD[<p>{ YYYY | YY }] | DD<p>MM[<p>{ YYYY | YY }] <time_format> ::= HH[:mm[:SS[<f>NNNN]]] <timestamp_format> ::= <date_format> [<space> <time_format>] <time_zone> ::= { + | - }HH:MM | time zone name (e.g. Europe/Berlin) <time_tz_format> ::= <time_format> [<space>] <time_zone> <timestamp_tz_format> ::= <timestamp_format> [<space>] <time_zone> <p> ::= whitespace | . | - | / <f> ::= : | .
Argument | Beschreibung |
---|---|
datetime_literal |
Datetime-Literal |
date_format |
Format des Datums |
time_format |
Format der Zeit |
timestamp_format |
Format des Zeitstempels |
time_zone |
Format der Zeitzone |
time_tz_format |
Format der Zeit mit Zeitzone |
timestamp_tz_format |
Format des Zeitstempels mit Zeitzone |
YYYY |
Vierstelliges Jahr |
YY |
Zweistelliges Jahr |
MM |
MonatEs kann 1 oder 2 Ziffern enthalten (1-12 oder 01-12).Sie können auch den aus drei Buchstaben bestehenden Kurznamen oder den vollständigen Namen eines Monats in Englisch angeben.Groß-/Kleinschreibung nicht beachten |
DD |
Tag.Dieser kann 1 oder 2 Ziffern enthalten (1-31 oder 01-31) |
HH |
Stunde.Diese kann 1 oder 2 Ziffern enthalten (0-23 oder 00-23) |
mm |
Minuten.Diese können 1 oder 2 Ziffern enthalten (0-59 oder 00-59) |
SS |
Sekunden.Diese können 1 oder 2 Ziffern enthalten (0-59 oder 00-59) |
NNNN |
Zehntausendstelsekunden.Diese können 1 bis 4 Ziffern (0-9999) enthalten. |
p |
Ein Datumstrennzeichen, eines der zulässigen Zeichen.Führende und nachgestellte Leerzeichen werden ignoriert.Die Wahl des Trennzeichens in einem Datum entscheidet, ob der Parser |
f |
Sekundenbruchteil-Trennzeichen |
Important
|
Die Verwendung der vollständigen Jahresangabe in vierstelliger Form — |
-- 1
UPDATE PEOPLE
SET AGECAT = 'SENIOR'
WHERE BIRTHDATE < DATE '1-Jan-1943';
-- 2
INSERT INTO APPOINTMENTS
(EMPLOYEE_ID, CLIENT_ID, APP_DATE, APP_TIME)
VALUES (973, 8804, DATE '1-Jan-2021' + 2, TIME '16:00');
-- 3
NEW.LASTMOD = TIMESTAMP '1-Jan-2021 16:00';
Tip
|
Obwohl die Firebird-Datetime-Syntax sehr flexibel ist, empfehlen wir zur Vermeidung von Mehrdeutigkeiten die ISO-8601-Reihenfolge (Jahr-Monat-Tag), ‘ Kurz gesagt, verwenden Sie |
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')