DuckDB 2.0 中更简洁的变量语法
2026-10-13 4 分钟阅读
DuckDB 团队
TL;DR: DuckDB 2.0 让你用 $name 引用读取会话变量,而不是调用 getvariable,并且预处理语句在未提供命名参数时可以回退到会话变量。本文展示新语法如何工作,以及这两个特性如何配合。
DuckDB 长期以来通过 SET VARIABLE 语句支持会话变量。你设置一次值,然后在需要的地方读回它,这把一个魔法常量保留在一个地方,而不是分散在脚本各处。到目前为止,读取一个变量意味着调用 getvariable,而这个调用比它背后的想法更冗长。
DuckDB 2.0 增加了一个简写。你可以用 $name 引用读取会话变量,而预处理语句在省略命名参数时可以回退到会话变量。本文走一遍这个特性的两半,并展示它们如何一起工作。
用 $name 读取变量
像你一直做的那样设置变量。
sql
SET VARIABLE x = 5;
在 DuckDB 2.0 之前,你用 getvariable 读回它。
sql
SELECT getvariable('x') AS x;
在 DuckDB 2.0 中,$x 正是那个调用的简写。
sql
SELECT $x AS x;
x
5
对于一个已设置的变量,两种形式可以互换。$name 引用解析为该名称会话变量的当前值,所以当 x 设为 5 时,$x 和 getvariable('x') 返回相同结果。
sql
SET VARIABLE animal = 'duck';
SELECT $animal = getvariable('animal') AS same;
same
true
如果你引用一个未设置的变量,DuckDB 会报错而不是返回 NULL。用 RESET VARIABLE 移除变量后也是如此。
sql
RESET VARIABLE animal;
SELECT $animal;
Invalid Input Error:
Values were not provided for the following parameters: animal
错误提到参数,是因为 $name 引用和命名预处理语句参数在底层是同一个构造:一个未设置的变量让参数没有值。这种重叠正是让这个特性第二半得以工作的原因。
会话变量作为预处理语句默认值
一个预处理语句声明你在执行它时提供的参数。DuckDB 用同样的 $name 语法命名参数。
sql
SET VARIABLE x = 5;
PREPARE double_value AS SELECT $x * 2 AS result;
在执行时提供参数,它就被直接使用。
sql
EXECUTE double_value(x := 1);
result
2
省略参数,DuckDB 2.0 就回退到同名的会话变量。这里 x 仍然是 5,所以语句计算 5 * 2。
sql
EXECUTE double_value;
result
10
回退值本身可以来自另一个变量。因为 $y 在被传入之前就解析了,这执行 10 * 2。
sql
SET VARIABLE y = 10;
EXECUTE double_value(x := $y);
result
20
当一个语句有多个参数时,两个来源自然结合。你提供的每个参数覆盖匹配的变量,你省略的每个参数回退到它。
sql
SET VARIABLE multiplier = 10;
SET VARIABLE x = 42;
PREPARE compute AS SELECT $multiplier * $x AS result;
没有参数时,两个参数都来自变量,得到 10 * 42。
sql
EXECUTE compute;
result
420
覆盖一个参数,另一个仍然回退。EXECUTE compute(multiplier := 3) 计算 3 * 42,而 EXECUTE compute(x := 1) 计算 10 * 1。
| 语句 | 结果 |
|---|---|
EXECUTE compute(multiplier := 3) |
126 |
EXECUTE compute(x := 1) |
10 |
EXECUTE compute(multiplier := 2, x := 5) |
10 |
命名参数和位置参数
回退只适用于命名参数。位置参数,写作 $1、$2 等等,按位置匹配,从不从会话变量填充,即使恰好有一个名为 1 的变量。
如果位置参数没有提供,语句仍然引发缺失参数错误。当你混合两种风格时记住这一点:把你想要从变量默认的参数据命名。
总结
DuckDB 2.0 使会话变量更容易读取,也更容易与预处理语句结合:
$name是getvariable('name')的简写,引用未设置的变量会报错。- 一个命名预处理语句参数在你没有提供它时回退到同名的会话变量,而显式实参总是胜出。
- 位置参数只按位置匹配,不回退到变量。
完整参考见 SET VARIABLE 语句和预处理语句页面,两者都列在 DuckDB 的友好 SQL 特性中。