HOWTO · PostgreSQL
在 PostgreSQL 查询中声明变量的方法
了解如何通过 WITH、PL/pgSQL DO 块或自定义设置向 PostgreSQL 查询传值,并掌握每种方式的作用范围。
本页内容
普通 PostgreSQL SQL 查询不能声明通用变量。若要在查询中使用某个值,可以在仅对当前查询有效的 WITH 子句中定义它,在 PL/pgSQL 代码块中声明过程变量,或通过自定义设置传递该值。这些方式的作用范围和生命周期各不相同。如果应用程序使用的数据库驱动支持绑定查询参数,通常应优先使用绑定参数。
在 PostgreSQL 查询中声明一个变量
以下示例使用一个包含三行数据的 vehicle 表。下面的 SQL 用于在 PostgreSQL 数据库中创建表并准备示例数据。vehicle_name、vehicle_type 和 vehicle_model 是 varchar 列,vehicle_price 是整数列。
使用 CREATE TABLE vehicle (vehicle_name varchar(30), vehicle_type varchar(30), vehicle_model varchar(30), vehicle_price integer, id serial UNIQUE NOT NULL PRIMARY KEY); 创建表,再用 INSERT INTO vehicle (vehicle_name, vehicle_type, vehicle_model, vehicle_price) VALUES ('Jaguar Range Rover Evoque', '4WD', '2019 Model', 7000000), ('Porsche Cayenne', '4WD', '2019 Model', 7000000), ('BMW 1 Series', '4WD', '2019 Model', 7000000); 插入示例数据。
请在要尝试这些示例的数据库中执行一次初始化操作。下面的每个查询都会筛选价格为 7000000 的车辆。
在应用程序代码中,应通过 PostgreSQL 驱动提供的参数接口绑定该值,而不要把它直接拼接进 SQL 字符串。下面的 Python 代码展示了 SQL 模板和单独传入的参数值。不同 PostgreSQL 驱动使用的占位符格式可能不同,请按所用驱动的文档选择格式。
query = "SELECT vehicle_name FROM vehicle WHERE vehicle_price = %s;"
params = (7000000,)
print(query)
print(params)
SELECT vehicle_name FROM vehicle WHERE vehicle_price = %s;
(7000000,)
在 PostgreSQL 查询中使用 WITH 子句来声明一个变量
WITH 子句会为一条语句定义一个公用表表达式(CTE)。这里的 prices 是一个仅在当前查询中有效、包含待比较值的关系;它不是通用变量,也不是临时表。
使用 WITH prices AS (SELECT 7000000 AS car_price) SELECT vehicle_name FROM vehicle CROSS JOIN prices WHERE vehicle.vehicle_price = prices.car_price;。
对于上面的示例数据,该查询会返回三辆车的名称:Jaguar Range Rover Evoque、Porsche Cayenne 和 BMW 1 Series。CTE 只对紧随其后的这条语句可用;在其他语句中使用时,需要重新定义它。
使用 PostgreSQL 过程语言在 PostgreSQL 查询中声明变量
PL/pgSQL DO 块可以声明变量,并在代码块中执行过程逻辑。变量 price 仅在该代码块内有效。此示例会将符合条件的行写入临时表;默认情况下,该表在当前数据库会话中存在,会话结束时删除。
运行代码块 DO $$ DECLARE price integer := 7000000; BEGIN CREATE TEMP TABLE expvehicles AS SELECT vehicle_name FROM vehicle WHERE vehicle_price = price; END $$;,然后单独执行 SELECT vehicle_name FROM expvehicles; 读取结果。
CREATE TEMP TABLE 是代码块执行的 SQL 操作;后面的 SELECT 是另一条独立语句。如果改用 CREATE TABLE,PostgreSQL 会创建持久表,除非明确指定创建临时表。重新运行这段初始化代码时,请使用不同的表名,或先删除已有的同名表,因为当前会话中若已存在同名临时表,新表可能无法创建。
使用动态配置设置在 PostgreSQL 查询中声明变量
自定义设置可以在同一个数据库会话的多条语句之间传递值。使用 SET 赋值,再通过 current_setting 读取。由于 current_setting 返回文本,与 vehicle_price 比较前需要将该值转换为整数。
使用 SET my.vars.price = '7000000'; 赋值,然后执行 SELECT vehicle_name FROM vehicle WHERE vehicle_price = current_setting('my.vars.price')::integer; 查询。
该设置会在当前会话中保留。若要将值限制在当前事务内,请先开启事务,再执行 SET LOCAL my.vars.price = '7000000';事务提交或回滚后,本地值即失效。在应用程序查询中,通常使用驱动绑定参数更容易控制作用范围,也比会话设置更安全,尤其是在连接池会重复使用连接时。