【问题标题】:Declare variable set = select声明变量集 = 选择
【发布时间】:2013-12-29 09:18:12
【问题描述】:

这听起来可能是一个非常愚蠢的问题,但是如何声明一个用于 PostgreSQL 9.3 查询的变量呢?

CREATE or replace FUNCTION public.test()
  returns int4
AS
$BODY$
DECLARE    
    cod_process bigint :=30001;
    cod_instance bigint ;
    utc_log timestamp without time zone := localtimestamp;
    cod_log_type varchar(100) :='information ';
    txt_log_text varchar(100):= 'start process';
    txt_log varchar(100):= txt_log_text||'_'||cod_process;
    set cod_instance= select max(cod_instance) as cod_instance from public.instance where public.instance.cod_process=cod_process;    
BEGIN  
    INSERT INTO public.log (cod_process, cod_instance, utc_log,cod_log_type,txt_log)
    VALUES (cod_process, cod_instance, utc_log,cod_log_type,txt_log );
    RETURN 11;
END;
$BODY$ LANGUAGE 'plpgsql';
ERROR: type "cod_instance" does not exist
SQL state: 42704
Character: 383

【问题讨论】:

    标签: postgresql variables set plpgsql declare


    【解决方案1】:

    您需要在实际代码块中使用into 子句运行选择,而不是在declare 块中:

    begin
       select max(cod_instance) 
          into cod_instance
       from public.instance 
       where public.instance.cod_process=cod_process;
    
       ....
    end;
    

    给变量(或参数)赋予与表中的列相同的名称通常不是一个好主意。在某些情况下,这可能会使解析器感到困惑。为避免任何潜在问题,请尝试为变量使用不同的名称,例如通过添加前缀(例如,l_cod_process 而不是 cod_processl_cod_instance 而不是 cod_instance

    关于变量赋值的更多细节可以在手册中找到:http://www.postgresql.org/docs/current/static/plpgsql-statements.html

    【讨论】:

      【解决方案2】:

      您的演示函数将像这样工作:

      CREATE or replace FUNCTION public.test()
        RETURNS int4 AS
      $func$
      DECLARE
         _cod_process  bigint := 30001;
         _cod_instance bigint := (SELECT max(cod_instance)
                                  FROM   public.instance
                                  WHERE  cod_process = _cod_process);
         _utc_log      timestamp := localtimestamp;
         _cod_log_type varchar(100) := 'information';
         _txt_log_text varchar(100) := 'start process';
         _txt_log      varchar(100) := txt_log_text || '_' || cod_process;
      BEGIN
         INSERT INTO public.log
                ( cod_process,  cod_instance,  utc_log,  cod_log_type,  txt_log)
         VALUES (_cod_process, _cod_instance, _utc_log, _cod_log_type, _txt_log);
      
         RETURN 11;
      END
      $func$ LANGUAGE plpgsql;
      

      要点

      • 不能使用SET 分配变量。这被认为是用于设置运行时参数的SQL command SET

      • 但是您可以在声明时分配一个变量,甚至为此使用子查询。

      • 使用LANGUAGE plpgsql,而不是LANGUAGE 'plpgsql'。这是一个标识符。

      • @a_horse_with_no_name 已经写过关于命名冲突的文章。

      • 在调试代码时使用干净的格式大有帮助...


      但您可能可以简化为:

      CREATE OR REPLACE FUNCTION public.test(_cod_process bigint = 30001)
        RETURNS integer AS
      $func$
         INSERT INTO public.log
         (cod_process, cod_instance     , utc_log, cod_log_type , txt_log)
         SELECT    $1, max(cod_instance), now()  , 'information', 'start process_' || $1
         FROM   public.instance
         WHERE  cod_process = $1
         GROUP  BY cod_process
         RETURNING 11
      $func$ LANGUAGE sql;
      

      呼叫:

      SELECT public.test();     -- for default 30001
      SELECT public.test(1234);
      

      根据utc_log 的实际数据类型,您可能需要now() AT TIME ZONE 'UTC'

      【讨论】:

      • 这是一个标志,表明 Stack Overflow 用户使用 Postgres 的人数很少,因此这样的答案获得的票数很少。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-14
      • 1970-01-01
      • 2021-03-09
      • 2018-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多