PostgreSQL-Kompatibilität
Der SQL-Dialekt von DuckDB folgt eng den Konventionen des PostgreSQL-Dialekts. Die wenigen Ausnahmen sind auf dieser Seite aufgeführt.
Gleitkommaarithmetik
DuckDB und PostgreSQL behandeln Gleitkommaarithmetik bei Division durch Null unterschiedlich. DuckDB entspricht dem IEEE-Standard für Gleitkommaarithmetik (IEEE 754) sowohl bei Division durch Null als auch bei Operationen mit Unendlichkeitswerten. PostgreSQL gibt bei Division durch Null einen Fehler zurück, richtet sich bei Unendlichkeitswerten aber nach IEEE 754. Um die Unterschiede zu zeigen, führen Sie die folgenden SQL-Abfragen aus:
SELECT 1.0 / 0.0 AS x;SELECT 0.0 / 0.0 AS x;SELECT -1.0 / 0.0 AS x;SELECT 'Infinity'::FLOAT / 'Infinity'::FLOAT AS x;SELECT 1.0 / 'Infinity'::FLOAT AS x;SELECT 'Infinity'::FLOAT - 'Infinity'::FLOAT AS x;SELECT 'Infinity'::FLOAT - 1.0 AS x;| Expression | PostgreSQL | DuckDB | IEEE 754 |
|---|---|---|---|
| 1.0 / 0.0 | error | Infinity | Infinity |
| 0.0 / 0.0 | error | NaN | NaN |
| -1.0 / 0.0 | error | -Infinity | -Infinity |
| ‘Infinity’ / ‘Infinity’ | NaN | NaN | NaN |
| 1.0 / ‘Infinity’ | 0.0 | 0.0 | 0.0 |
| ‘Infinity’ - ‘Infinity’ | NaN | NaN | NaN |
| ‘Infinity’ - 1.0 | Infinity | Infinity | Infinity |
Division von Ganzzahlen
Bei der Division von Ganzzahlen führt PostgreSQL eine Ganzzahldivision durch, DuckDB dagegen eine Gleitkommadivision:
SELECT 1 / 2 AS x;PostgreSQL liefert 0, DuckDB liefert 0.5.
Um in DuckDB eine Ganzzahldivision durchzuführen, verwenden Sie den Operator //:
SELECT 1 // 2 AS x;Das liefert 0.
UNION von booleschen und ganzzahligen Werten
Die folgende Abfrage schlägt in PostgreSQL fehl, wird in DuckDB jedoch erfolgreich ausgeführt:
SELECT true AS xUNIONSELECT 2;PostgreSQL gibt einen Fehler zurück:
ERROR: UNION types boolean and integer cannot be matchedDuckDB führt eine erzwungene Typumwandlung durch, führt die Abfrage daher aus und liefert Folgendes:
| x |
|---|
| 1 |
| 2 |
Implizite Typumwandlung bei Gleichheitsprüfungen
DuckDB führt bei Gleichheitsprüfungen implizite Typumwandlungen durch, z. B. das Umwandeln von Zeichenketten in numerische und boolesche Werte. Daher gibt es mehrere Fälle, in denen PostgreSQL einen Fehler wirft, DuckDB das Ergebnis aber erfolgreich berechnet:
| Expression | PostgreSQL | DuckDB |
|---|---|---|
| ‘1.1’ = 1 | error | true |
| ‘1.1’ = 1.1 | true | true |
| 1 = 1.1 | false | false |
| true = ‘true’ | true | true |
| true = 1 | error | true |
| ‘true’ = 1 | error | error |
Groß-/Kleinschreibung bei quotierten Bezeichnern
PostgreSQL ist unabhängig von der Groß-/Kleinschreibung. PostgreSQL erreicht das, indem unquotierte Bezeichner in SQL in Kleinbuchstaben umgewandelt werden, während Quotierung die Schreibweise erhält. Der folgende Befehl erzeugt beispielsweise eine Tabelle namens mytable, versucht aber, MyTaBLe abzufragen, weil Anführungszeichen die Schreibweise erhalten.
CREATE TABLE MyTaBLe (x INTEGER);SELECT * FROM "MyTaBLe";ERROR: relation "MyTaBLe" does not existPostgreSQL behandelt nicht nur quotierte Bezeichner als abhängig von der Groß-/Kleinschreibung; es behandelt alle Bezeichner so, z. B. funktioniert auch Folgendes nicht:
CREATE TABLE "PreservedCase" (x INTEGER);SELECT * FROM PreservedCase;ERROR: relation "preservedcase" does not existDaher funktioniert die Unabhängigkeit von der Groß-/Kleinschreibung in PostgreSQL nur, wenn Sie nie quotierte Bezeichner mit unterschiedlicher Schreibweise verwenden.
Für DuckDB war dieses Verhalten problematisch beim Zusammenspiel mit anderen Werkzeugen (z. B. Parquet, Pandas), die standardmäßig abhängig von der Groß-/Kleinschreibung sind – weil alle Bezeichner ständig in Kleinbuchstaben umgewandelt würden. Daher erreicht DuckDB Unabhängigkeit von der Groß-/Kleinschreibung, indem Bezeichner im gesamten System vollständig unabhängig von der Groß-/Kleinschreibung sind, ihre Schreibweise aber erhalten bleibt.
In DuckDB werden die Skripte oben erfolgreich ausgeführt:
CREATE TABLE MyTaBLe (x INTEGER);SELECT * FROM "MyTaBLe";CREATE TABLE "PreservedCase" (x INTEGER);SELECT * FROM PreservedCase;SELECT tbl FROM duckdb_tables();| tbl |
|---|
| MyTaBLe |
| PreservedCase |
Das PostgreSQL-Verhalten, Bezeichner in Kleinbuchstaben umzuwandeln, ist über die Option preserve_identifier_case verfügbar:
SET preserve_identifier_case = false;CREATE TABLE MyTaBLe (x INTEGER);SELECT tbl FROM duckdb_tables();| tbl |
|---|
| mytable |
Die unabhängige Zuordnung von Bezeichnern im System lässt sich jedoch nicht abschalten.
Doppeltes Gleichheitszeichen für Vergleiche
DuckDB unterstützt sowohl = als auch == für Gleichheitsvergleiche, PostgreSQL nur =.
SELECT 1 == 1 AS t;DuckDB liefert true, PostgreSQL liefert:
postgres=# SELECT 1 == 1 AS t;ERROR: operator does not exist: integer == integerLINE 1: SELECT 1 == 1 AS t;Beachten Sie, dass die Verwendung von == wegen der eingeschränkten Portabilität nicht empfohlen wird.
Vacuum von Tabellen
In PostgreSQL führt die Anweisung VACUUM eine Speicherbereinigung von Tabellen durch und analysiert sie.
In DuckDB dient die Anweisung VACUUM nur dazu, Statistiken neu aufzubauen.
Hinweise zur Freigabe von Speicherplatz finden Sie auf der Seite „Speicherplatz freigeben“.
Zeichenketten
Seit Version 1.3.0 maskiert DuckDB Zeichen wie ' in Zeichenketten, die in verschachtelten Datenstrukturen serialisiert werden.
PostgreSQL tut das nicht.
Als Beispiel führen Sie aus:
SELECT ARRAY[''''];PostgreSQL liefert:
{'}DuckDB liefert:
['\'']Funktionen
Funktion regexp_extract
Im Gegensatz zu PostgreSQLs Funktion regexp_substr liefert DuckDBs regexp_extract leere Zeichenketten statt NULLs, wenn es keine Übereinstimmung gibt.
Funktion to_date
DuckDB unterstützt die PostgreSQL-Datumsformatierungsfunktion to_date nicht.
Verwenden Sie stattdessen die Funktion strptime.
Funktion date_part
Die meisten von der Funktion date_part extrahierten Bestandteile werden als Ganzzahlen zurückgegeben. Da es in DuckDB keine unendlichen Ganzzahlwerte gibt, werden für unendliche Zeitstempel NULLs zurückgegeben.
Auflösung von Typnamen im Schema
Bei CREATE TABLE-Anweisungen versucht DuckDB, Typnamen in dem Schema aufzulösen, in dem eine Tabelle angelegt wird. Zum Beispiel:
CREATE SCHEMA myschema;CREATE TYPE myschema.mytype AS ENUM ('as', 'df');CREATE TABLE myschema.mytable (v mytype);PostgreSQL gibt bei der letzten Anweisung einen Fehler zurück:
ERROR: type "mytype" does not existLINE 1: CREATE TABLE myschema.mytable (v mytype);DuckDB führt die Anweisung aus und legt die Tabelle erfolgreich an, bestätigt durch die folgende Abfrage:
DESCRIBE myschema.mytable;| column_name | column_type | null | key | default | extra |
|---|---|---|---|---|---|
| v | ENUM(‘as’, ‘df’) | YES | NULL | NULL | NULL |
Nutzung funktionaler Abhängigkeiten für GROUP BY
PostgreSQL kann funktionale Abhängigkeiten ausnutzen, etwa i -> j in der folgenden Abfrage:
CREATE TABLE tbl (i INTEGER, j INTEGER, PRIMARY KEY (i));SELECT jFROM tblGROUP BY i;PostgreSQL führt die Abfrage aus.
DuckDB scheitert:
Binder Error:column "j" must appear in the GROUP BY clause or must be part of an aggregate function.Either add it to the GROUP BY list, or use "ANY_VALUE(j)" if the exact value of "j" is not important.Als Workaround fügen Sie die anderen Attribute hinzu oder verwenden Sie die Klausel GROUP BY ALL.
Verhalten der Operatoren für reguläre Ausdrücke
PostgreSQL unterstützt die POSIX-Operatoren für reguläre Ausdrücke ~ (teilweise, groß-/kleinschreibungsabhängig) und ~* (teilweise, unabhängig von der Groß-/Kleinschreibung) sowie ihre negierten Varianten !~ bzw. !~*.
In DuckDB ist ~ gleichwertig mit regexp_full_match und !~ gleichwertig mit NOT regexp_full_match.
Die Operatoren ~* und !~* werden nicht unterstützt.
Die folgende Tabelle zeigt, dass die Entsprechung zwischen diesen Funktionen in PostgreSQL und DuckDB fast nicht vorhanden ist. Vermeiden Sie die POSIX-Operatoren für reguläre Ausdrücke in DuckDB.
| Expression | PostgreSQL | DuckDB |
|---|---|---|
| `‘aaa’ ~ ’(a | b)’` | true |
| `‘AAA’ ~* ’(a | b)’` | true |
| `‘aaa’ !~ ’(a | b)’` | false |
| `‘AAA’ !~* ’(a | b)’` | false |