Oracle单行成变量

时间:2018-10-19 07:54:10

标签: oracle plsql

我需要将所有结果都放在一行中...它正在工作,但是当我想在dbms中看到它时,没有提示..为什么?

docker tag image:version docker.mydomain.com/image:version

这应该是我期望的程序。

  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; /

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

1 个答案:

答案 0 :(得分:3)

假设您的真实代码已声明RC_TABLE0作为引用游标,则您的变量最终将为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:无效的游标”)

除非您重新打开游标,否则您将无法做到这两者,这似乎是您可能不希望的开销...