首页 > 解决方案 > oracle单行变成变量

问题描述

我需要在一行中获得所有结果......它正在工作,但是当我想在 dbms 中看到它时,没有任何想法......为什么?

  CREATE OR REPLACE PROCEDURE NXMESEP.SP_IN_CHECK_AND_SEND_SMS

(    RC_TABLE0   OUT SYS_REFCURSOR,
    RS_CODE            OUT        VARCHAR2,     -- RETURN 코드
    RS_MSG             OUT        VARCHAR2
    ) IS   ERROR_EXCEPTION            EXCEPTION;

BEGIN 

     begin
        DECLARE
        promena varchar2(32767);

            BEGIN

                OPEN RC_TABLE0 FOR
                SELECT listagg(ITEM_ID,', ') within group(order by ITEM_ID)
                 INTO promena
                  FROM TB_PL_M_WRKORD WRKOD
                WHERE 1 = 1
                AND WO_DATE = '20181012'
                AND WRKOD.ITEM_ID NOT IN (SELECT ITEM_ID FROM TB_CM_M_FERT_COST_CHK FERT)
                AND WC_ID = 'U';
                LOOP
                FETCH rc_table0 INTO promena;
                EXIT WHEN rc_table0%NOTFOUND;
                dbms_output.put_line(promena);
                END LOOP;
                  CLOSE rc_table0;

               end;
                   EXCEPTION
    ....    END;

   RS_CODE := 'S';    RS_MSG := 'Complete successfully!';

   RETURN; END SP_CHECK_AND_SEND_SMS; /

这应该是我所期望的。

" 12993NXUA, 13595NXUA, 14495NXUA, 16589NX, 16589NX, 16590NX, 16590NX, 16622NX, 16622NX "

现在它正在工作,但每次执行时我都会收到未知错误 ORA-65535。但在此之后我可以看到 dbms 结果是好的。

标签: oracleplsql

解决方案


假设您的真实代码已RC_TABLE0声明为 ref 游标,那么您的变量最终为 null,因为将游标打开某些东西并没有真正做任何事情。您不能同时打开游标并将游标查询中的某些内容选择到单独的变量中,无论您尝试采用哪种方式。您需要一个游标一个简单的select ... into

DECLARE
  promena varchar2(32767);
BEGIN
  SELECT listagg(ITEM_ID,', ') within group (order by ITEM_ID)
  INTO promena
  FROM TB_PL_M_WRKORD WRKOD
  WHERE 1 = 1
  AND WO_DATE = '20181012'
  AND WRKOD.ITEM_ID NOT IN (SELECT ITEM_ID FROM TB_CM_M_FERT_COST_CHK FERT)
  AND WC_ID = 'U';

  dbms_output.put_line('test: '||promena);
END;
/

test: 12993NXUA, 13595NXUA, 14495NXUA ...

PL/SQL procedure successfully completed.

当然,您还必须set serveroutput on或等效地实际看到结果。

我还删除了多余distinct的、不必要的select .. from dual——这似乎是奇怪游标结构的一部分——以及begin/end.

顺便说一句,您的代码暗示这wo_date是一个字符串,这似乎不太可能,或者至少不理想。如果它实际上是一个真实的日期,那么您不应该使用字符串进行比较,因为您正在强制进行隐式转换;改用实际日期,可能是 ANSI 日期文字:

  AND WO_DATE = DATE '2018-10-12'

如果您确实想使用显式游标方法,则需要使用循环来填充字符串变量:

DECLARE
  promena varchar2(32767);
  rc_table0 sys_refcursor;
BEGIN
  OPEN rc_table0 FOR
    SELECT DISTINCT listagg(ITEM_ID,', ') within group (order by ITEM_ID)
    FROM TB_PL_M_WRKORD WRKOD
    WHERE 1 = 1
    AND WO_DATE = '20181012'
    AND WRKOD.ITEM_ID NOT IN (SELECT ITEM_ID FROM TB_CM_M_FERT_COST_CHK FERT)
    AND WC_ID = 'U';

  LOOP
    FETCH rc_table0 INTO promena;
    EXIT WHEN rc_table0%NOTFOUND;
    dbms_output.put_line('test: '||promena);
  END LOOP;

  CLOSE rc_table0;
END;
/

由于您只期望返回一行,因此这样做没有多大意义;如果您期望多行(来自修改后的查询,例如获取几天的数据并按天分组),那么隐式游标无论如何都会更简单:

BEGIN
  FOR r IN (
    SELECT DISTINCT listagg(ITEM_ID,', ') within group (order by ITEM_ID) AS promena
    FROM TB_PL_M_WRKORD WRKOD
    WHERE 1 = 1
    AND WO_DATE = '20181012'
    AND WRKOD.ITEM_ID NOT IN (SELECT ITEM_ID FROM TB_CM_M_FERT_COST_CHK FERT)
    AND WC_ID = 'U'
  )
  LOOP
    dbms_output.put_line('test: '||r.promena);
  END LOOP;
END;
/

如果这确实是过程的一部分并且rc_table0OUT参数,那么您就不能这样做。在您发布为您尝试的答案的代码中:

OPEN RC_TABLE0 FOR
  SELECT listagg(ITEM_ID,', ') within group(order by ITEM_ID)
  INTO promena
  FROM TB_PL_M_WRKORD WRKOD
  ...

在该构造中,into仍然忽略了,因为open没有获取任何东西。如果你像我上面那样在你的过程中循环和获取以显示结果,那么你正在使用结果集,所以调用者将不会得到任何结果(或者“ORA-01001:无效游标”,如果你在过程中关闭它) .

你不能同时做这两个,除非你重新打开光标,这似乎是你可能不想要的开销......


推荐阅读