我如何在PostgreSQL 8.3查询中声明一个变量?

在MS SQL Server我可以这样做:

DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

我如何在PostgreSQL做同样的事情?根据文档,变量被简单地声明为“name type;”,但这给了我一个语法错误:

myvar INTEGER;

谁能给我一个正确语法的例子吗?


当前回答

我通过使用WITH子句实现了同样的目标,它远没有那么优雅,但可以做同样的事情。虽然对于这个例子来说,它真的是太夸张了。我也不特别推荐这个。

WITH myconstants (var1, var2) as (
   values (5, 'foo')
)
SELECT *
FROM somewhere, myconstants
WHERE something = var1
   OR something_else = var2;

其他回答

这取决于你的客户。

然而,如果你正在使用psql客户端,那么你可以使用以下方法:

my_db=> \set myvar 5
my_db=> SELECT :myvar  + 1 AS my_var_plus_1;
 my_var_plus_1 
---------------
             6

如果你使用文本变量,你需要引用。

\set myvar 'sometextvalue'
select * from sometable where name = :'myvar';

在DBeaver中,你可以在查询中使用参数,就像在代码中一样,所以这是可以工作的:

SELECT *
FROM somewhere
WHERE something = :myvar

当你运行查询时,DBeaver会问你:myvar的值并运行查询。

动态配置设置

你可以“滥用”动态配置设置:

-- choose some prefix that is unlikely to be used by postgres
set session my.vars.id = '1';

select *
from person 
where id = current_setting('my.vars.id')::int;

配置设置始终是varchar值,因此在使用它们时需要将它们转换为正确的数据类型。这适用于任何SQL客户端,而\set只适用于psql

以上要求Postgres 9.2或更高版本。

对于以前的版本,该变量必须在使用之前在postgresql.conf中声明,因此在某种程度上限制了它的可用性。实际上不完全是变量,而是配置“类”,本质上是前缀。但是一旦定义了前缀,任何变量都可以使用而不需要改变postgresql.conf

您可以求助于工具的特殊功能。比如DBeaver自己的专有语法:

@set name = 'me'
SELECT :name;
SELECT ${name};

DELETE FROM book b
WHERE b.author_id IN (SELECT a.id FROM author AS a WHERE a.name = :name);

在psql中,你可以使用这些“变量”作为宏。请注意,它们在每次使用时都被“计算”,而不是在“设置”时。

简单的例子:

\set my_random '(SELECT random())'
select :my_random;  -- gives  0.23330629315990592
select :my_random;  -- gives  0.67458399344433542

这样每次都会给出两个不同的答案。

但是,您仍然可以使用这些有价值的简写来避免重复大量的子选择。

\set the_id '(SELECT id FROM table_1 WHERE name = ''xxx'' LIMIT 1)'

然后在以后的查询中使用它

:the_id 

e.g.

INSERT INTO table2 (table1_id,x,y,z) VALUES (:the_id, 1,2,3)

注意,你必须对变量中的字符串加双引号,因为整件事都是字符串插值(即宏展开)到你的查询中。