Note
请参阅DuckDB关于时区的博客文章以获取更多关于时间戳、时区以及DuckDB处理方式的信息。
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;
请注意,由于==
的可移植性有限,不鼓励使用它。
在PostgreSQL中,VACUUM
语句用于垃圾回收表并分析表。
在DuckDB中,VACUUM
语句仅用于重建统计信息。
有关回收空间的说明,请参阅“回收空间”页面。
regexp_extract
函数
与PostgreSQL的regexp_substr
函数不同,DuckDB的regexp_extract
在没有匹配时返回空字符串而不是NULL
。
to_date
函数
DuckDB 不支持 to_date
PostgreSQL 日期格式化函数。
请改用 strptime
函数。
DuckDB的current_date
和current_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::DATE
或 current_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 |