【问题标题】:RETURN cannot have a parameter in function with OUT parametersRETURN 不能在带有 OUT 参数的函数中有参数
【发布时间】:2018-01-25 07:31:13
【问题描述】:

我做了从 oracle 到 pgsql 的 db 迁移,得到如下代码:

CREATE OR REPLACE FUNCTION PKG_UTIL_BD_LOGISTICS_getsignerinfo (
  i_opCode T_MQ_LOGIC_TRACK_HEAD_LOG.LP_CODE%TYPE, i_remark T_MQ_LOGIC_TRACK_HEAD_LOG.REMARK%TYPE, i_acceptTime T_MQ_LOGIC_TRACK_HEAD_LOG.SIGNED_TIME%TYPE, i_signer T_MQ_LOGIC_TRACK_HEAD_LOG.SIGNER%TYPE, i_lpcode T_MQ_LOGIC_TRACK_HEAD_LOG.LP_CODE%TYPE,
  o_signer OUT T_MQ_LOGIC_TRACK_HEAD_LOG.SIGNER%TYPE, o_signerTime OUT T_MQ_LOGIC_TRACK_HEAD_LOG.SIGNED_TIME%TYPE, o_status OUT T_MQ_LOGIC_TRACK_HEAD_LOG.STATUS%TYPE ) 
RETURNS RECORD AS $body$
DECLARE

  v_signer        T_MQ_LOGIC_TRACK_HEAD_LOG.SIGNER%TYPE;
  v_signerTime    T_MQ_LOGIC_TRACK_HEAD_LOG.SIGNED_TIME%TYPE;
  v_status        T_MQ_LOGIC_TRACK_HEAD_LOG.STATUS%TYPE;

BEGIN
IF i_lpcode = 'SF' THEN
   IF i_opCode = '8000' THEN
      IF POSITION(':back' in i_remark) > 0 THEN
        v_status := '3';
      ELSE
        v_status := '7';
        v_signerTime := i_acceptTime;
        v_signer := SUBSTR(i_remark, POSITION(':' in i_remark) + 1);
      END IF;
  ELSIF i_opCode = '9999' THEN
      v_status := '3';
    ELSIF i_opCode = '80' THEN
      v_status := '7';
      v_signerTime := i_acceptTime;
    ELSIF i_opCode = 70 THEN
      v_status := i_opCode;
    ELSE
      v_status := '1';
    END IF;
ELSE
  IF i_opCode = 'signed' THEN
      v_signerTime := i_acceptTime;
      v_signer := i_signer;
      v_status:='7';
  ELSE
    v_status:='1';
  END IF;

END IF;
  o_status := v_status;
  o_signer := v_signer;
  o_signerTime := v_signerTime;
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    RAISE EXCEPTION '%', 'PKG_UTIL_BD_LOGISTICS.getSignerInfo fetch parameters' || i_remark || 'value error:' || SQLERRM;
END;

$body$
LANGUAGE PLPGSQL
SECURITY DEFINER

当我执行代码时,出现错误:RETURN cannot have a parameter in function with OUT parameters。有人可以帮忙吗?我是 pgsql 新手。

【问题讨论】:

    标签: database postgresql plpgsql


    【解决方案1】:

    带有 OUT 参数的函数的结果由 OUT 参数的值指定,并且仅由这些值指定。尽管 OUT 参数的语法在 PostgreSQL 和 Oracle 之间是相似的,但实现是最大的不同。

    Oracle 使用 OUT 参数的引用 - 因此您可以编写如下内容:

    CREATE FUNCTION foo(a int, OUT b int)
    RETURN boolean IS
    BEGIN
      b := a;
      RETURN true;
    END;
    

    此函数返回布尔值,并作为“副作用”修改通过引用传递的第二个参数。

    PostgreSQL 不支持通过引用传递参数。所有参数仅按值传递。当您使用 OUT 参数时,没有传递引用,而是从结果组合中获取返回值。结果组合仅由 OUT 参数组成。没有任何其他的空间。所以代码:

    CREATE OR REPLACE FUNCTION foo(a INT, OUT b int)
    RETURNS boolean AS $$
    BEGIN
      b := a;
      RETURN true;
    END; $$ LANGUAGE plpgsql
    

    无效,因为foo 函数的实际结果是标量 int 值,与声明的布尔值相矛盾。 RETURN true 也是错误的,因为结果只基于 OUT 参数,然后RETURN 应该没有任何表达式。

    函数 foo 从 Oracle 到 Postgres 的等效翻译是:

    CREATE OR REPLACE FUNCTION foo(a INT, OUT b int, OUT result boolean)
    RETURNS record AS $$
    BEGIN
      b := a;
      result := true;
      RETURN;
    END; $$ LANGUAGE plpgsql
    

    简单规则 - 当函数在 Postgres 中有 OUT 变量时,RETURN 语句仅用于结束执行 - 不用于返回值规范。该值基于 OUT 参数。

    【讨论】:

      【解决方案2】:

      考虑以下示例:

      CREATE OR REPLACE FUNCTION generate_taskcode(IN classIdVar character varying,IN appIdInt integer, OUT pagecoderet character varying) RETURNS character varying AS $$
          DECLARE
              updateCode character varying;
          BEGIN
              update mytable set lastcodeused = to_char(cast(lastcodeused as INTEGER)+1, 'FM999999999999999999') where 
              classid = classIdVar and appid= appIdInt 
              RETURNING concat(pageName,lastcodeused) as pageName
              into updateCode;
              
              return updateCode;
          END;
      $$ LANGUAGE plpgsql
      

      注意开始和结束之间的“更新代码”。如果您尝试执行此操作,您将收到与您提到的相同的错误,因为当您在函数参数中 OUT 时无法返回变量“** return updateCode**” .所以正确的定义如下:

      CREATE OR REPLACE FUNCTION generate_taskcode(IN classIdVar character varying,IN appIdInt integer, OUT pagecoderet character varying) RETURNS character varying AS $$
          DECLARE
              updateCode character varying;
          BEGIN
              update mytable set lastcodeused = to_char(cast(lastcodeused as INTEGER)+1, 'FM999999999999999999') where 
              classid = classIdVar and appid= appIdInt 
              RETURNING concat(pageName,lastcodeused) as pageName
              into updateCode;
              pagecoderet =  updateCode;
              return;
          END;
      $$ LANGUAGE plpgsql
      

      【讨论】:

        猜你喜欢
        • 2019-11-06
        • 1970-01-01
        • 2012-12-11
        • 2018-05-11
        • 2014-01-12
        • 2017-06-11
        • 2013-05-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多