如何在简单的PostgreSQL脚本中使用变量?


Answers:


131

完整答案位于官方PostgreSQL文档中

您可以使用新的PG9.0匿名代码块功能(http://www.postgresql.org/docs/9.1/static/sql-do.html

DO $$
DECLARE v_List TEXT;
BEGIN
  v_List := 'foobar' ;
  SELECT *
  FROM   dbo.PubLists
  WHERE  Name = v_List;
  -- ...
END $$;

您还可以获得最后的插入 ID:

DO $$
DECLARE lastid bigint;
BEGIN
  INSERT INTO test (name) VALUES ('Test Name') 
  RETURNING id INTO lastid;

  SELECT * FROM test WHERE id = lastid;
END $$;

7
(也不要忘记;之后END $$,就像这样:END $$;。)
KajMagnus 2012年

3
近来我不工作,我在plpgsql语言的开始和结束之间也有一些功能。
2016年

49
此示例中的代码不起作用。ERROR: query has no destination for result data HINT: If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT: PL/pgSQL function inline_code_block line 7 at SQL statement
杰森

1
对PostgreSQL来说是全新的,这让我有些烦恼,这里还有更多提示:+确保您以分号结束语句!+因为没有变量标识符,所以您可能需要使用_或类似的名称以避免模棱两可的列名。+您可以像这样使用DECLARE _accountid INT:= 1;将变量设置为行中的值。
编码员

1
不要为我工作。使用松鼠。错误:错误:“ $$或附近的未终止美元报价的字符串
Oliver Watkins'Aug

39
DO $$
DECLARE  
   a integer := 10;  
   b integer := 20;  
   c integer;  
BEGIN  
   c := a + b;
    RAISE NOTICE'Value of c: %', c;
END $$;

3
不要为我工作。使用松鼠。错误:错误:“ $$或附近的未终止美元报价的字符串
Oliver Watkins'Aug

花了我一段时间才能弄清楚,要使用该变量,您不得在其:前面加上其他变量。@ achilles-ram-nakirekanti您可以在select语句中添加使用此示例以使其更清楚?
exhuma

28

您可以使用:

\set list '''foobar'''
SELECT * FROM dbo.PubLists WHERE name = :list;

那会做


3
错误:“ \”或附近的语法错误我缺少什么?
scw 2015年

14
@scw仅在psql控制台上可用。您将无法在应用程序的SQL中编写此代码。
owensmartin

@owensmartin您将能够使用通过管道传递到psql的任何内容..或psql读取的任何脚本...
Evan Carroll

4
这根本无法回答问题。在MS SQL中,您可以在查询中定义一个变量,然后在同一工具中在那里使用它。我不明白为什么人们在这个问题的每个版本中都不断提出这个答案。

@stone显然是因为这是一个巨大的“失误”,postgresql并且它是最糟糕的选择。一般来说,我已经相当满意postgresql:但是这是一个令人惊讶的大失败
javadba

10

这是在plpgsql中使用变量的示例:

create table test (id int);
insert into test values (1);
insert into test values (2);
insert into test values (3);

create function test_fn() returns int as $$
    declare val int := 2;
    begin
        return (SELECT id FROM test WHERE id = val);
    end;
$$ LANGUAGE plpgsql;

SELECT * FROM test_fn();
 test_fn 
---------
       2

请查看plpgsql文档以获取更多信息。


4

我遇到了一些其他文档,它们使用它们\set来声明脚本变量,但是该值似乎像常量值,我正在寻找一种可以像变量而不是常量的行为。

例如:

\set Comm 150

select sal, sal+:Comm from emp

sal是表“ emp”中存在的值,并且comm是恒定值。


2

我不得不做这样的事情

CREATE OR REPLACE FUNCTION MYFUNC()
RETURNS VOID AS $$
DO
$do$
BEGIN
DECLARE
 myvar int;
 ...
END
$do$
$$ LANGUAGE SQL;

2

PostgreSQL没有裸变量,您可以使用一个临时表。变量仅在代码块中或作为用户界面功能可用。

如果您需要裸变量,则可以使用临时表:

CREATE TEMP TABLE list AS VALUES ('foobar');

SELECT dbo.PubLists.*
FROM   dbo.PubLists,list
WHERE  Name = list.column1;

作为附带好处,此方法与数据库无关,使您的测试在后端的可移植性更高。
主教

2

对@ nad2000答案,并建立@帕维尔的答案在这里,这是我结束了我的迁飞迁移脚本。处理手动修改数据库架构的方案。

DO $$
BEGIN
    IF NOT EXISTS(
        SELECT TRUE FROM pg_attribute 
        WHERE attrelid = (
            SELECT c.oid
            FROM pg_class c
            JOIN pg_namespace n ON n.oid = c.relnamespace
            WHERE 
                n.nspname = CURRENT_SCHEMA() 
                AND c.relname = 'device_ip_lookups'
            )
        AND attname = 'active_date'
        AND NOT attisdropped
        AND attnum > 0
        )
    THEN
        RAISE NOTICE 'ADDING COLUMN';        
        ALTER TABLE device_ip_lookups
            ADD COLUMN active_date TIMESTAMP;
    ELSE
        RAISE NOTICE 'SKIPPING, COLUMN ALREADY EXISTS';
    END IF;
END $$;


1

对于例如alter table中的use变量:

DO $$ 
DECLARE name_pk VARCHAR(200);
BEGIN
select constraint_name
from information_schema.table_constraints
where table_schema = 'schema_name'
      and table_name = 'table_name'
      and constraint_type = 'PRIMARY KEY' INTO name_pk;
IF (name_pk := '') THEN
EXECUTE 'ALTER TABLE schema_name.table_name DROP CONSTRAINT ' || name_pk;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.