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

问题描述 投票:0回答:12

例如,在 MS-SQL 中,您可以打开查询窗口并运行以下命令:

DECLARE @List AS VARCHAR(8)

SELECT @List = 'foobar'

SELECT *
FROM   dbo.PubLists
WHERE  Name = @List

这在 PostgreSQL 中是如何完成的?可以做吗?

postgresql variables
12个回答
188
投票

完整的答案位于官方 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 $$;

您还可以获得最后一个insert id:

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

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

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

37
投票

您可以使用:

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

这样就可以了


16
投票

这是在 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 文档以获取更多信息。


8
投票

我遇到过一些其他文档,他们使用

\set
来声明脚本变量,但该值似乎是常量值,我正在寻找可以充当变量而不是常量变量的方法。

例如:

\set Comm 150

select sal, sal+:Comm from emp

这里

sal
是表“emp”中存在的值,
comm
是常量值。


7
投票

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

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

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

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

5
投票

基于@nad2000的答案和@Pavel在这里的答案,这就是我最终获得Flyway迁移脚本的地方。处理手动修改数据库架构的场景。

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

5
投票

例如在更改表中使用变量:

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;

3
投票

我必须做这样的事情

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

3
投票

您还可以简单地创建一个在实际查询中使用的常量查询:

WITH vars as (SELECT 'foobar' AS list) 
SELECT *
FROM   dbo.PubLists, vars
WHERE  Name = vars.list

3
投票

鉴于受欢迎程度和有些不完整的答案,我将提供两种解决方案。

  1. 不会返回行的 do 块。您可以使用事务游标返回行,但这有点混乱。
  2. 一个函数(返回行)

下面我将使用一个过度烘焙的示例,将右下角“blurb”上的推文更新为“hello world”。

id(序列号) pub_id(文本) 推文(文本)
1 abc 世界你好
2 定义 宣传

一个简单的 do 块

do $$
declare
    src_pub_id text;
    dst_pub_id text;
    src_id    int; 
    dest_id   int;
    src_tweet text;
begin
    src_pub_id := 'abc';
    dst_pub_id := 'def';
    
    -- query result into a temp variable
    src_id := (select id from tweets where pub_id = src_pub_id);

    -- query result into a temp variable (another way)
    select tweet into src_tweet from tweets where id = src_id;

    dest_id := (select id from tweets where pub_id = dst_pub_id);
    update tweets set tweet=src_tweet where id = dest_id;
end $$ language plpgsql; -- need the language to avoid ERROR 42P13

一个功能

create or replace function sync_tweets(
    src_pub_id text, -- function arguments
    dst_pub_id text
) returns setof tweets as -- i.e. rows. int, text work too
$$
declare
    src_id    int; -- temp function variables (not args)
    dest_id   int;
    src_tweet text;
begin
    -- query result into a temp variable
    src_id := (select id from tweets where pub_id = src_pub_id);

    -- query result into a temp variable (another way)
    select tweet into src_tweet from tweets where id = src_id;

    dest_id := (select id from tweets where pub_id = dst_pub_id);
    update tweets set tweet=src_tweet where id = dest_id;

    return query -- i.e. rows, return 0 with return int above works too
        select * from tweets where pub_id in (src_pub_id, dst_pub_id);
end
$$ language plpgsql; -- need the language to avoid ERROR 42P13

-- Run it!
select * from sync_tweets('abc', 'def');

-- Optional drop if you don't want the db to keep your function
drop function if exists sync_tweets(text, text);

/*
  Outputs
   __________________________________________________ 
  |  id (serial)  |  pub_id (text)  |  tweet (text)  |
  |---------------|-----------------|----------------|
  |  1            |  abc            |  hello world   |
  |  2            |  def            |  blurb         |
  --------------------------------------------------
*/

0
投票

*备注:

您可以在

:=
子句中使用
=
DECLARE
声明局部变量,如下所示:

DO $$
DECLARE
  value1 INT := 1; -- Here
  value2 INT = 2; -- Here
  value3 INT DEFAULT 3; -- Here
  value4 CONSTANT INT := 4; -- Here
  value5 INT; -- Here
BEGIN
  RAISE INFO '%', value1 + value2 + value3; -- 6
END
$$;

*备注:

  • :=
    =
    DEFAULT
    是相同的。
  • 尝试更改常量局部变量
    value4
    会出错。
  • 未初始化的局部变量
    value5
    NULL
  • 您可以在 PL/pgSQL 函数和过程以及
    DECLARE
    语句中使用
    DO
    子句声明局部变量。
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.