⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
PostgreSQL 兼容性

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 错误 无穷大 (Infinity) 无穷大 (Infinity)
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 返回 0,而 DuckDB 返回 0.5

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

SELECT 1 // 2 AS 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

相等性检查中的隐式转换

DuckDB 在相等性检查中执行隐式类型转换,例如将字符串转换为数值或布尔值。因此,在某些情况下,PostgreSQL 会抛出错误,而 DuckDB 可以成功计算出结果:

表达式 PostgreSQL DuckDB
'1.1' = 1 错误 true
'1.1' = 1.1 true true
1 = 1.1 false false
true = 'true' true true
true = 1 错误 true
'true' = 1 错误 错误

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

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

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

PostgreSQL 不仅将引号标识符视为大小写敏感,它将所有标识符都视为大小写敏感。例如,以下操作也无法工作:

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

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

对于 DuckDB,这种行为在与默认大小写敏感的其他工具(如 Parquet, Pandas)进行交互时会产生问题——因为所有标识符都会被强制转换为小写。因此,DuckDB 通过使系统内部的标识符保持完全大小写不敏感,同时 保留其原始大小写 来实现大小写不敏感。

在 DuckDB 中,上述脚本可以成功执行:

CREATE TABLE MyTaBLe (x INTEGER);
SELECT * FROM "MyTaBLe";
CREATE TABLE "PreservedCase" (x INTEGER);
SELECT * FROM PreservedCase;
SELECT tbl FROM duckdb_tables();
tbl
MyTaBLe
PreservedCase

PostgreSQL 将标识符转换为小写的行为可以通过 preserve_identifier_case 选项 来实现。

SET preserve_identifier_case = false;
CREATE TABLE MyTaBLe (x INTEGER);
SELECT tbl FROM duckdb_tables();
tbl
mytable

但是,系统中针对标识符的大小写不敏感匹配无法关闭。

使用双等号进行比较

DuckDB 同时支持 === 进行相等性比较,而 PostgreSQL 仅支持 =

SELECT 1 == 1 AS t;

DuckDB 返回 true,而 PostgreSQL 返回:

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

请注意,由于可移植性有限,不建议使用 ==

清理 (Vacuuming) 表

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

字符串

从 1.3.0 版本开始,DuckDB 会对嵌套数据结构中序列化的字符串中的 ' 等字符进行转义。PostgreSQL 不会这样做。

例如,运行:

SELECT ARRAY[''''];

PostgreSQL 返回:

{'}

DuckDB 返回:

['\'']

函数

regexp_extract 函数

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

to_date 函数

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

date_part 函数

date_part 函数提取的大多数部分都作为整数返回。由于 DuckDB 中没有无穷大的整数值,因此对于无穷大的时间戳,会返回 NULL

Schema 中类型名称的解析

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

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') 是 (YES) NULL NULL NULL

利用函数依赖进行 GROUP BY

PostgreSQL 可以利用函数依赖,例如在以下查询中的 i -> j

CREATE TABLE tbl (i INTEGER, j INTEGER, PRIMARY KEY (i));
SELECT j
FROM tbl
GROUP BY i;

PostgreSQL 运行该查询。

DuckDB 失败。

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.

要解决此问题,请添加其他属性或使用 GROUP BY ALL 子句

正则表达式匹配运算符的行为

PostgreSQL 支持 POSIX 正则表达式匹配运算符 ~(大小写敏感的部分正则匹配)和 ~*(大小写不敏感的部分正则匹配),以及它们的否定变体 !~!~*

在 DuckDB 中,~ 等同于 regexp_full_match!~ 等同于 NOT regexp_full_match。运算符 ~*!~* 不受支持。

下表显示了 PostgreSQL 和 DuckDB 中这些函数之间的对应关系几乎不存在。请避免在 DuckDB 中使用 POSIX 正则表达式匹配运算符。

表达式 PostgreSQL DuckDB
'aaa' ~ '(a|b)' true false
'AAA' ~* '(a|b)' true 错误
'aaa' !~ '(a|b)' false true
'AAA' !~* '(a|b)' false 错误
© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南