将存储过程从SQL Server迁移到PostgreSQL时出现问题

时间:2014-04-16 16:46:29

标签: sql database postgresql cursor plpgsql

我来自SQL Server到PostgreSQL(9.0),所以我在执行它时在存储过程/函数中遇到问题。该函数返回此错误消息:

  

SQLSTATE:42601;
  SQLERRM:查询没有结果数据的目的地

我需要做什么将SELECT查询选择的列中的值与OUT参数一起传递到结果中,并避免收到该错误消息?

CREATE OR REPLACE FUNCTION myplfunction(
    IN i_param1 character varying,
    IN i_param2 character varying,
    IN i_param3 character varying,
    IN i_param4 character varying,
    OUT o_call_status integer,
    OUT o_call_message character varying)
  RETURNS record AS
$BODY$
DECLARE 
val1 varchar;
val2 varchar;
...

IF (v_solution_id IS NULL) THEN
    val1 := column1 FROM tbl2 WHERE column2= i_param1;
    IF(val1 IS NULL) THEN
        o_call_status := 1005;
        o_call_message := column1 is not configured or invalid';
        RETURN;
END IF;

    SELECT 'mycolumnname1' as paramName,mycolumn1 as value FROM tb1 WHERE column1 = val
    UNION ALL
    SELECT 'mycolumnname2' as paramName,,mycolumn2 as value  FROM tb1 WHERE column1 = val
    UNION ALL
    SELECT 'mycolumnname2' as paramName,,mycolumn2 as value  FROM tb2 WHERE column2 = val2 
    WHERE tb2paramName4=i_val3;      

    o_call_status := 0;
    o_call_message := '';

    EXCEPTION WHEN OTHERS THEN 
        o_call_message := SQLERRM;
        o_call_status := SQLSTATE;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE

1 个答案:

答案 0 :(得分:1)

通常,PostgreSQL函数只返回单个值(或行)或一组值(或行),但不能并行返回。

返回一张桌子

您可以直接从函数返回一组或多行,使其成为“设置返回函数”,a.k.a。“表函数”。那么除了每行返回参数o_call_statuso_call_message之外你别无选择(如果你实际上根本需要它们的话?)

CREATE OR REPLACE FUNCTION myplfunction(i_val1 int, i_val2 int)
  RETURNS TABLE (col1 text, col2 text          -- use matching types!
               , o_call_status  text           -- text, not int
               , o_call_message text) AS
$func$
BEGIN
   RETURN QUERY 
   SELECT col1, col2
        , '0'::text AS o_call_status
        , ''::text AS o_call_message   -- column aliases irrelevant here
   FROM   tb1
   WHERE  col3 = i_val1
   UNION ALL
   SELECT col4, col5, '0'::text, ''::text
   FROM   tb2
   WHERE  col6 = i_val2
   AND    col7 = i_val3;      -- WHERE was specified twice

   EXCEPTION WHEN OTHERS THEN 
     RETURN QUERY
     SELECT NULL::text, NULL::text, SQLERRM, SQLSTATE;
END
$func$  LANGUAGE plpgsql;

特殊变量SQLERRM的类型为text,顺便说一句。不是integer

或打开游标

或者您必须打开游标以将返回的表与这两个参数分离。

CREATE OR REPLACE FUNCTION myplfunction(
      i_val1 text, i_val2 text, i_val3 text, i_val4 text
    , OUT o_call_status  text
    , OUT o_call_message text) AS
$func$
DECLARE
   curs CURSOR FOR
   SELECT col1, col2 FROM tb1
   WHERE  col3 = i_val1
   UNION ALL
   SELECT col4, col5 FROM tb2
   WHERE  col6 = i_val2
   AND    col7 = i_val3;
BEGIN
   OPEN curs;

   o_call_status  := '0';
   o_call_message := '';

   EXCEPTION WHEN OTHERS THEN 
     o_call_status  := SQLSTATE;
     o_call_message := SQLERRM;
END
$func$  LANGUAGE plpgsql;

但是,游标只存在于同一个事务中。因此,您需要在COMMITROLLBACK之前获取值。

BEGIN;
SELECT * FROM myplfunction (10, 20, 30, 40);
FETCH ALL IN curs;
ROLLBACK;

您甚至可以提交任意光标名称。 This and other details in the manual.

还有more information about errors available since Postgres 9.3.