代码之家  ›  专栏  ›  技术社区  ›  EMP

如何在PostgreSQL查询中声明变量

  •  156
  • EMP  · 技术社区  · 15 年前

    如何声明在PostgreSQL 8.3查询中使用的变量?

    在MS SQL Server中,我可以这样做:

    DECLARE @myvar INT
    SET @myvar = 5
    
    SELECT *
    FROM somewhere
    WHERE something = @myvar
    

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

    myvar INTEGER;
    

    有人能给我举个正确语法的例子吗?

    9 回复  |  直到 5 年前
        1
  •  74
  •   J.Wincewicz kgiannakakis    6 年前

    PostgreSQL中没有这样的特性。只能在pl/pgsql(或其他pl/*)中执行,而不能在纯SQL中执行。

    例外是 WITH () 可以作为变量工作的查询,甚至 tuple 变量。它允许您返回一个临时值表。

    WITH master_user AS (
        SELECT
          login,
          registration_date
        FROM users
        WHERE ...
    )
    
    SELECT *
    FROM users
    WHERE master_login = (SELECT login
                          FROM master_user)
          AND (SELECT registration_date
               FROM master_user) > ...;
    
        2
  •  159
  •   a_horse_with_no_name    6 年前

    我用一个 WITH clause 它远不如优雅,但也能做同样的事情。不过,在这个例子中,这实在是太过分了。我也不特别推荐这个。

    WITH myconstants (var1, var2) as (
       values (5, 'foo')
    )
    SELECT *
    FROM somewhere, myconstants
    WHERE something = var1
       OR something_else = var2;
    
        3
  •  59
  •   elixenide Ren    8 年前

    您也可以在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或更高版本。

        4
  •  40
  •   Yevgeniy Afanasyev    7 年前

    这取决于你的客户。

    但是,如果您使用 PSQL 客户端,然后可以使用以下内容:

    my_db=> \set myvar 5
    my_db=> SELECT :myvar  + 1 AS my_var_plus_1;
     my_var_plus_1 
    ---------------
                 6
    
        5
  •  37
  •   ypercubeᵀᴹ    8 年前

    动态配置设置

    您可以为此“滥用”动态配置设置:

    -- choose some prefix that is unlikey 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 在被使用之前,它在一定程度上限制了它的可用性。实际上不是完全的变量,而是配置“class”,它本质上是前缀。但是一旦定义了前缀,任何变量都可以在不更改的情况下使用。 PrGrESQL.CONF

        6
  •  19
  •   Evan Carroll    8 年前

    在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;
    
        7
  •  7
  •   Community TheSoundDefense    7 年前

    我想建议改进一下 @DarioBarrionuevo's answer ,使利用临时表更简单。

    DO $$
        DECLARE myvar integer = 5;
    BEGIN
        CREATE TEMP TABLE tmp_table ON COMMIT DROP AS
            -- put here your query with variables:
            SELECT * 
            FROM yourtable
            WHERE id = myvar;
    END $$;
    
    SELECT * FROM tmp_table;
    
        8
  •  4
  •   Martin    6 年前

    下面是一个使用 PREPARE statements . 你还是不能用 ? ,但您可以使用 $n 表示法:

    PREPARE foo(integer) AS
        SELECT  *
        FROM    somewhere
        WHERE   something = $1;
    EXECUTE foo(5);
    DEALLOCATE foo;
    
        9
  •  0
  •   Jorge Luis    5 年前

    此解决方案基于 fei0x 但是它的优点是不需要在查询中加入常量的值列表,并且可以在查询开始时轻松列出常量。它也适用于递归查询。

    基本上,每个常量都是一个单值表 宣布 在WITH子句中,然后可以在查询的其余部分的任何位置调用该子句。

    • 带两个常量的基本示例:
    WITH
        constant_1_str AS (VALUES ('Hello World')),
        constant_2_int AS (VALUES (100))
    SELECT *
    FROM some_table
    WHERE table_column = (table constant_1_str)
    LIMIT (table constant_2_int)
    

    或者您可以使用 SELECT * FROM constant_name 而不是 TABLE constant_name 这可能对PostgreSQL之外的其他查询语言无效。

    推荐文章