【问题标题】:How do you use variables in a simple PostgreSQL script?如何在简单的 PostgreSQL 脚本中使用变量?
【发布时间】:2010-10-20 11:32:39
【问题描述】:

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

DECLARE @List AS VARCHAR(8)

SELECT @List = 'foobar'

SELECT *
FROM   dbo.PubLists
WHERE  Name = @List

这是如何在 PostgreSQL 中完成的?能做到吗?

【问题讨论】:

标签: postgresql variables


【解决方案1】:

完整答案位于official PostgreSQL documentation

您可以使用新的 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 $$;

【讨论】:

  • (别忘了;END $$之后,像这样:END $$;。)
  • DOESN'T WORK FOR ME ERROR NEAR DO,我在 plpgsql 语言的开头和结尾之间也有一些功能。
  • 此示例中的代码不起作用。 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
  • 对 PostgreSQL 完全陌生,这让我有一段时间了,这里还有一些提示: + 确保你的语句以分号结束! + 因为没有变量标识符,您可能需要使用 _ 或类似的东西来避免列名不明确。 + 您可以使用这样的 DECLARE _accountid INT := 1; 将变量设置为行中的值
  • 不要为我工作。使用松鼠。错误:错误:在“$$ 处或附近未终止的美元引号字符串
【解决方案2】:
DO $$
DECLARE  
   a integer := 10;  
   b integer := 20;  
   c integer;  
BEGIN  
   c := a + b;
    RAISE NOTICE'Value of c: %', c;
END $$;

【讨论】:

  • 不要为我工作。使用松鼠。错误:错误:在“$$ 处或附近未终止的美元引号字符串
  • 我花了一段时间才弄清楚,为了使用该变量,您不得像使用其他变量一样在其前面加上 :。 @achilles-ram-nakirekanti 您可以在select 语句中添加一个使用此示例以使其更清晰?
  • 你能详细说明这是做什么的吗?这对我很有用。我知道 $$ 只是替换引号来执行文字,但为什么我们需要 DO $$ 块呢?
【解决方案3】:

你可以使用:

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

这样就可以了

【讨论】:

  • 错误:“\”处或附近的语法错误我错过了什么?
  • @scw 这只能从psql 控制台获得。您将无法在应用的 SQL 中编写此代码。
  • @owensmartin 您将能够使用通过管道传输到 psql.. 的任何内容或 psql 读取的任何脚本...
  • 这根本不能回答问题。在 MS SQL 中,您可以在查询中定义 var 并在同一工具中直接使用它。我不明白为什么人们在这个问题的每个版本中都不断提出这个作为答案。
  • @stone 显然是因为这在postgresql 中是一个巨大的“失误”,而且它是最差的选择。总的来说,我对postgresql 感到非常满意:但这是一个令人惊讶的大失败
【解决方案4】:

这是一个在 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 docs 了解更多信息。

【讨论】:

    【解决方案5】:

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

    例如:

    \set Comm 150
    
    select sal, sal+:Comm from emp
    

    这里sal 是表“emp”中的值,comm 是常量值。

    【讨论】:

      【解决方案6】:

      例如在alter table中使用变量:

      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;
      

      【讨论】:

        【解决方案7】:

        在@nad2000 的回答和@Pavel's answer here 的基础上,我最终完成了我的 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 $$;
        

        【讨论】:

          【解决方案8】:

          我不得不这样做

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

          【讨论】:

            【解决方案9】:

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

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

            CREATE TEMP TABLE list AS VALUES ('foobar');
            
            SELECT dbo.PubLists.*
            FROM   dbo.PubLists,list
            WHERE  Name = list.column1;
            

            【讨论】:

            • 附带的好处是,这种方法与数据库无关,使您的测试在后端更易于移植。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-07-09
            • 2021-01-12
            • 2011-09-10
            • 1970-01-01
            • 2020-08-20
            • 2010-09-07
            相关资源
            最近更新 更多