RETURN不能在OUT参数的功能中使用参数

时间:2017-08-17 02:29:21

标签: database postgresql plpgsql

我从oracle到pgsql进行了数据库迁移,得到了如下代码:

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在OUT参数的函数中没有参数。可以有人帮忙吗?我是pgsql的新手。

2 个答案:

答案 0 :(得分:4)

OUT参数的功能结果由OUT参数的值指定,并且仅由这些值指定。虽然PostgreSQL和Oracle之间的OUT参数语法相似,但实现方式却截然不同。

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

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

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

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值,与声明的boolean相矛盾。 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参数。

答案 1 :(得分:0)

考虑以下示例:

lapply(dfiles, function(x) {
   df <- read.csv(x, header = FALSE)
   write.csv(subset(df, select = 3), paste0('folder2/', x), row.names = FALSE)
})

在开始和结束之间注意“ 更新代码”。如果尝试执行此操作,则会收到与您提到的错误相同的错误,因为在函数参数中 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;
        
        return updateCode;
    END;
$$ LANGUAGE plpgsql