Zum Inhalt springen

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:

  • UINT8 entspricht UTINYINT, weil es eine 8-Bit-Ganzzahl ohne Vorzeichen ist
  • INT8 entspricht BIGINT, 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).