⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
PostgreSQL Compatibility

DuckDB的SQL方言紧密遵循PostgreSQL方言的惯例。 本页列出了与此不同的少数例外情况。

浮点运算

DuckDB 和 PostgreSQL 在处理除以零的浮点运算时有所不同。DuckDB 遵循 IEEE 浮点运算标准 (IEEE 754) 来处理除以零和涉及无穷大值的操作。PostgreSQL 在除以零时会返回错误,但在处理无穷大值时与 IEEE 754 保持一致。为了展示这些差异,请运行以下 SQL 查询:

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;
表达式 PostgreSQL DuckDB IEEE 754
1.0 / 0.0 错误 无穷大 无穷大
0.0 / 0.0 错误 NaN NaN
-1.0 / 0.0 错误 -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

整数除法

在对整数进行除法计算时,PostgreSQL 执行整数除法,而 DuckDB 执行浮点数除法:

SELECT 1 / 2 AS x;

PostgreSQL 返回:

x
0

DuckDB 返回:

x
0.5

要在DuckDB中执行整数除法,请使用//运算符:

SELECT 1 // 2 AS x;
x
0

UNION 布尔值和整数值的联合

以下查询在 PostgreSQL 中失败,但在 DuckDB 中成功完成:

SELECT true AS x
UNION
SELECT 2;

PostgreSQL 返回一个错误:

ERROR:  UNION types boolean and integer cannot be matched

DuckDB 执行了一个强制转换,因此,它完成了查询并返回以下内容:

x
1
2

引号标识符的大小写敏感性

PostgreSQL 是大小写不敏感的。PostgreSQL 实现大小写不敏感的方式是通过在 SQL 中将未加引号的标识符转换为小写,而加引号则保留大小写,例如,以下命令创建了一个名为 mytable 的表,但尝试查询 MyTaBLe,因为引号保留了大小写。

CREATE TABLE MyTaBLe(x INT);
SELECT * FROM "MyTaBLe";
ERROR:  relation "MyTaBLe" does not exist

PostgreSQL 不仅将带引号的标识符视为区分大小写,PostgreSQL 将所有标识符都视为区分大小写,例如,这也不起作用:

CREATE TABLE "PreservedCase"(x INT);
SELECT * FROM PreservedCase;
ERROR:  relation "preservedcase" does not exist

因此,PostgreSQL 中的大小写不敏感性仅在您从不使用不同大小写的引用标识符时才有效。

对于DuckDB来说,当与默认情况下区分大小写的其他工具(例如,Parquet、Pandas)进行接口时,这种行为是有问题的——因为所有标识符总是会被转换为小写。 因此,DuckDB通过使标识符在整个系统中完全区分大小写不敏感,但保留它们的大小写来实现大小写不敏感。

在DuckDB中,上述脚本成功完成:

CREATE TABLE MyTaBLe(x INT);
SELECT * FROM "MyTaBLe";
CREATE TABLE "PreservedCase"(x INT);
SELECT * FROM PreservedCase;
SELECT table_name FROM duckdb_tables();
表名
MyTaBLe
保留大小写

PostgreSQL 将标识符转换为小写的行为可以通过 preserve_identifier_case 选项 来访问:

SET preserve_identifier_case = false;
CREATE TABLE MyTaBLe(x INT);
SELECT table_name FROM duckdb_tables();
表名
mytable

然而,系统中标识符的不区分大小写匹配无法关闭。

使用双等号进行比较

DuckDB 支持使用 === 进行相等比较,而 Postgres 仅支持 =

SELECT 1 == 1 AS t;

DuckDB 返回:

t
true

Postgres 返回:

postgres=# SELECT 1 == 1 AS t;
ERROR:  operator does not exist: integer == integer
LINE 1: SELECT 1 == 1 AS t;

请注意,由于==的可移植性有限,不鼓励使用它。

Vacuuming tables

在PostgreSQL中,VACUUM语句用于垃圾回收表并分析表。 在DuckDB中,VACUUM语句仅用于重建统计信息。 有关回收空间的说明,请参阅“回收空间”页面

Functions

regexp_extract 函数

与PostgreSQL的regexp_substr函数不同,DuckDB的regexp_extract在没有匹配时返回空字符串而不是NULL

to_date 函数

DuckDB 不支持 to_date PostgreSQL 日期格式化函数。 请改用 strptime 函数

current_date / current_time / current_timestamp

DuckDB的current_datecurrent_time伪列返回UTC中的当前日期(作为DATE)和时间(作为TIME),而PostgreSQL返回配置的本地时区中的当前日期(作为DATE)和时间作为TIMETZ。对于配置时区中的当前时间,仍然作为常规TIME,DuckDB提供了函数current_localtime()

DuckDB 和 PostgreSQL 都将 current_timestamp 返回为 TIMESTAMPTZ。DuckDB 还提供了 current_localtimestamp(),它返回配置时区的时间为 TIMESTAMP

DuckDB 目前不提供 current_localdate();不过可以通过 current_timestamp::DATEcurrent_localtimestamp()::DATE 来计算。

Note

请参阅DuckDB关于时区的博客文章以获取更多关于时间戳、时区以及DuckDB处理方式的信息。

模式中类型名称的解析

对于CREATE TABLE 语句,DuckDB 尝试在创建表的模式中解析类型名称。例如:

CREATE SCHEMA myschema;
CREATE TYPE myschema.mytype AS ENUM ('as', 'df');
CREATE TABLE myschema.mytable (v mytype);

PostgreSQL 在最后一条语句上返回了一个错误:

ERROR:  type "mytype" does not exist
LINE 1: CREATE TABLE myschema.mytable (v mytype);

DuckDB 运行语句并成功创建表,通过以下查询确认:

DESCRIBE myschema.mytable;
column_name column_type null key default extra
v ENUM('as', 'df') NULL NULL NULL