SQL-Besonderheiten
Wie alle Programmiersprachen und Bibliotheken hat DuckDB seine Eigenheiten und Inkonsistenzen.
Manche sind Überbleibsel der Evolution unseres gefiederten Freundes; andere sind unvermeidlich, weil wir uns am SQL-Standard und insbesondere am Dialekt von PostgreSQL orientieren (siehe die Seite „PostgreSQL-Kompatibilität“ für Ausnahmen).
Der Rest mag schlicht auf unterschiedliche Vorlieben zurückgehen, oder wir sind uns einig, was getan werden sollte, sind aber noch nicht dazu gekommen.
Diese Besonderheiten anzuerkennen ist das Beste, was wir tun können – deshalb haben wir unten eine Liste von Beispielen zusammengestellt.
Aggregation leerer Gruppen
Bei leeren Gruppen liefern die Aggregatfunktionen sum, list und string_agg jeweils NULL statt 0, [] bzw. ''. Das schreibt der SQL-Standard vor und wird von allen uns bekannten SQL-Implementierungen befolgt. Dieses Verhalten wird von der Listenaggregatfunktion list_sum übernommen, nicht aber von der DuckDB-eigenen Funktion list_dot_product, die bei leeren Listen 0 zurückgibt.
0- vs. 1-basierte Indizierung
Um dem Standard-SQL zu entsprechen, wird fast überall 1-basierte Indizierung verwendet, z. B. bei Array- und Zeichenkettenindizierung sowie -slicing und bei Fensterfunktionen (row_number, rank, dense_rank). Wie in PostgreSQL verwenden JSON-Funktionen jedoch eine 0-basierte Indizierung.
Typen
UINT8 vs. INT8
UINT8 und INT8 sind Aliase für Ganzzahltypen unterschiedlicher Breite:
UINT8entsprichtUTINYINT, weil es eine 8-Bit-Ganzzahl ohne Vorzeichen istINT8entsprichtBIGINT, weil es eine 8-Byte-Ganzzahl mit Vorzeichen ist
Erklärung: Das n im numerischen Typ INTn und UINTn bezeichnet die Breite der Zahl in Bytes oder Bits.
INT1, INT2, INT4 entsprechen der Anzahl der Bytes, während INT16, INT32 und INT64 der Anzahl der Bits entsprechen.
Dasselbe gilt für UINT-Werte.
Allerdings ist der Wert n = 8 sowohl für die Anzahl der Bits als auch der Bytes gültig.
Bei Werten ohne Vorzeichen entspricht UINT8 UTINYINT (8 Bits).
Bei Werten mit Vorzeichen entspricht INT8 BIGINT (8 Bytes).
Ausdrücke
Ergebnisse, die überraschen können
| Expression | Result | Note |
|---|---|---|
-2^2 |
4.0 |
PostgreSQL-Kompatibilität bedeutet, dass das unäre Minus Vorrang vor dem Potenzoperator hat. Verwenden Sie zusätzliche Klammern, z. B. -(2^2), oder die Funktion pow, z. B. -pow(2, 2), um Fehler zu vermeiden. |
't' = true |
true |
Kompatibel mit PostgreSQL. |
1 = '1' |
true |
Kompatibel mit PostgreSQL. |
1 = ' 1' |
true |
Kompatibel mit PostgreSQL. |
1 = '01' |
true |
Kompatibel mit PostgreSQL. |
1 = ' 01 ' |
true |
Kompatibel mit PostgreSQL. |
1 = true |
true |
Nicht kompatibel mit PostgreSQL. |
1 = '1.1' |
true |
Nicht kompatibel mit PostgreSQL. |
1 IN (0, NULL) |
NULL |
Sinnvoll, wenn Sie die NULLs in Ein- und Ausgabe als UNKNOWN betrachten. |
1 in [0, NULL] |
false |
|
concat('abc', NULL) |
abc |
Kompatibel mit PostgreSQL. list_concat verhält sich ähnlich. |
| `‘abc’ | NULL` |
NaN-Werte
'NaN'::FLOAT = 'NaN'::FLOAT und 'NaN'::FLOAT > 3 verletzen IEEE-754, bedeuten aber, dass Gleitkommatypen eine totale Ordnung haben, wie alle anderen Datentypen (achten Sie auf die Folgen für greatest / least).
Funktion age
age(x) ist current_date - x statt current_timestamp - x. Eine weitere von PostgreSQL geerbte Besonderheit.
Extraktionsfunktionen
list_extract / map_extract liefern NULL bei nicht vorhandenen Schlüsseln. struct_extract wirft einen Fehler, weil Schlüssel von Structs wie Spalten sind.
Klauseln
Automatische Spaltendeduplizierung in SELECT
Spaltennamen werden dedupliziert, wobei das erste Vorkommen die anderen überschattet:
CREATE TABLE tbl AS SELECT 1 AS a;SELECT a FROM (SELECT *, 2 AS a FROM tbl);| a |
|---|
| 1 |
Unabhängigkeit von der Groß-/Kleinschreibung beim SELECT von Spalten
Wegen der Unabhängigkeit von der Groß-/Kleinschreibung ist SELECT a FROM 'file.parquet' nicht möglich, wenn in file.parquet eine Spalte namens A vor der gewünschten Spalte a erscheint.
USING SAMPLE
Die Klausel USING SAMPLE steht syntaktisch nach den Klauseln WHERE und GROUP BY (wie die Klausel LIMIT), wird semantisch aber vor beiden angewendet (anders als die Klausel LIMIT).