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

在MS SQL Server我可以这样做:

DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

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

myvar INTEGER;

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


当前回答

下面是一个使用PREPARE语句的例子。你仍然不能使用?,但你可以使用$n符号:

PREPARE foo(integer) AS
    SELECT  *
    FROM    somewhere
    WHERE   something = $1;
EXECUTE foo(5);
DEALLOCATE foo;

其他回答

您可以求助于工具的特殊功能。比如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);

动态配置设置

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

-- 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

你也可以在PLPGSQL中尝试:

DO $$
DECLARE myvar integer;
BEGIN
    SELECT 5 INTO myvar;

    DROP TABLE IF EXISTS tmp_table;
    CREATE TABLE tmp_table AS
    SELECT * FROM yourtable WHERE   id = myvar;
END $$;

SELECT * FROM tmp_table;

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

在pl/PgSQL之外使用临时表

除了使用pl/pgsql或其他建议的pl/*语言之外,这是我能想到的唯一其他可能性。

begin;
select 5::int as var into temp table myvar;
select *
  from somewhere s, myvar v
 where s.something = v.var;
commit;

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

SELECT *
FROM somewhere
WHERE something = :myvar

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