在 Microsoft SQL Server 中,要在查询窗口中测试类似这样的内容:
select * from Users where LastName = @lastname
我可以在命令前面添加这个:
declare @lastname varchar(16)
set @lastname = 'Troy'
但是在PostgreSQL中,我找不到类似的方法。似乎我唯一能做的就是直接用它的值替换参数名。当临时查询变得复杂,并且同一个参数被使用多次时,这样做会变得很困难。有没有其他方法呢?
在 Microsoft SQL Server 中,要在查询窗口中测试类似这样的内容:
select * from Users where LastName = @lastname
我可以在命令前面添加这个:
declare @lastname varchar(16)
set @lastname = 'Troy'
但是在PostgreSQL中,我找不到类似的方法。似乎我唯一能做的就是直接用它的值替换参数名。当临时查询变得复杂,并且同一个参数被使用多次时,这样做会变得很困难。有没有其他方法呢?
各种选项。
在CTE中提供参数,以在纯SQL中具有“变量”:
WITH var(lastname) AS (SELECT 'Troy'::varchar(16))
SELECT *
FROM users<b>, var v</b>
WHERE lastname = <b>v.lastname</b>;
这适用于任何查询。var
仅包含单个行,因此在FROM子句末尾添加CROSS JOIN
是安全的 - 实际上,在逗号后追加它的短形式可能是最好的,因为显式连接语法在逗号之前绑定。另一个表别名v
是可选的,以进一步缩短语法。
或者如果没有CTE更便宜。顺便问一下,为什么使用varchar(16)
?只需使用text
即可:
SELECT *
FROM users
JOIN (SELECT 'Troy'::text) var(lastname) USING (lastname)
WHERE lastname = var.lastname;
或者使用一个临时表来在同一会话中为所有查询扮演类似的角色。临时表会随着会话结束而消失。
CREATE TEMP TABLE var AS
SELECT text 'Troy' AS lastname;
ANALYZE var; -- temp tables are not covered by autovacuum
SELECT * FROM users JOIN var USING (lastname);
或者您可以像@Houari提供的那样使用DO
语句,或者像这里演示的那样:
请注意,您不能从DO
语句中返回值。(不过您可以使用RAISE ...
)。而且在plpgsql - DO
语句中的默认过程语言中,不能使用没有目标的SELECT
。将SELECT
替换为PERFORM
以丢弃结果。
或者您可以使用自定义选项,您可以在postgresql.conf
中进行设置,以在全局中可见。
或者在会话中设置以在会话期间对同一会话可见:
SET my.lastname = 'Troy';
变量名称必须包括一个点。这种方式限制了数据类型为text
,但所有数据类型都可以表示为text
…您可以将current_setting('my.lastname')
用作值表达式。如果需要,进行转换。例如:current_setting('my.json_var')::json
…或者使用SET LOCAL
使效果仅在当前事务中持续。请参见:Passing user id to PostgreSQL triggers 或者您可以使用微小的IMMUTABLE
函数作为只有特权用户才能操作的全局持久变量。请参见:Is there a way to define a named constant in a PostgreSQL query? 或者在使用psql客户端时,使用\set
或\gset
元命令和变量替换。DO
语句中使用关键字PERFORM
而不是SELECT
。你不能在DO
语句中没有目标地进行SELECT
,也不能返回行... - Erwin Brandstetter我配置了Postgres以记录所有命令,并从日志文件中复制命令,因此所有参数已经替换为值,并在查询窗口中测试该命令。
这可能不是最佳方法,但对我来说很简单且有效。
SET @var = 123
。https://dev59.com/Mmgt5IYBdhLWcg3w3xPC。我知道我之前在MSSQL中使用过它。 - Kasey Speakman