如何使用SYS_REFCURSOR - ORACLE处理NO DATA FOUND

时间:2012-01-11 18:50:48

标签: oracle plsql

如果我的选择不使用SYS_REFCURSOR来获得结果,该怎么办?

我到目前为止尝试使用的是NO_DATA_FOUND,但它不起作用,我STATUS继续将我作为= 1

...   
MYVARIABLE IN OUT SYS_REFCURSOR
...

OPEN MYVARIABLE FOR
     SELECT NAME FROM TABLE WHERE COD = 1; 
     STATUS := 1;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
      STATUS := 0;

任何想法?

谢谢!


真正的sql是这样的:

修改

V_SQL := 'SELECT SUM(T1.VLRLIQ) VALOR,T1.CODCLI,T1.NOMCLI
     ,(SELECT METCLI FROM WEB_CRM_CLIVEN T2
     WHERE T2.CODCLI = T1.CODCLI AND T2.CODVEN = '|| P_CODVEN ||'
      AND T2.MES = '|| V_MES ||' AND T2.ANO = '|| V_ANO ||') META
      FROM SAPIENS.USU_VRESNFV T1,SAPIENS.E085CLI T2
    WHERE T1.CODVEN = '|| P_CODVEN ||'
     AND TO_CHAR(T1.DATEMI,''YYYY'') = '|| V_ANO ||'
     AND TO_CHAR(T1.DATEMI,''MM'') = '|| V_MES ||'
     AND T1.VENFAT = ''S''
     '|| V_CGCCPF ||'
     '|| V_NOMCLI ||'
     AND T2.CODCLI = T1.CODCLI
     AND T1.CODEMP = 1
     GROUP BY T1.CODCLI,T1.NOMCLI
     UNION
   SELECT SUM(''0'') VALOR,CODCLI,NOMCLI,(SELECT METCLI FROM WEB_CRM_CLIVEN T3
      WHERE T3.CODCLI = T2.CODCLI AND T3.CODVEN = '|| P_CODVEN ||'
      AND T3.MES = '|| V_MES ||' AND T3.ANO = '|| V_ANO ||') META
      FROM SAPIENS.E085CLI T2
    WHERE
     CODCLI IN (SELECT CODCLI FROM WEB_CRM_VEN_CARTEIRA
      WHERE CODVEN = '|| P_CODVEN ||' AND MES = '|| V_MES ||' AND ANO = '|| V_ANO ||')
      '|| V_CGCCPF ||'
      '|| V_NOMCLI ||'
     GROUP BY CODCLI,NOMCLI
     ORDER BY VALOR DESC';

     STATUS := 1;

     OPEN RESULTADO FOR V_SQL;

2 个答案:

答案 0 :(得分:7)

在您的代码中,您只是打开光标而不是从中获取光标。当您打开游标时,PL / SQL将执行该游标的查询。它还标识符合WHERE子句和连接条件的条件的行。 OPEN实际上并不检索任何这些行;该动作由FETCH语句执行。然后,您将使用游标属性来检查结果集是否为空;如果是,则以下游标属性将具有以下值:%FOUND = FALSE,%NOTFOUND = TRUE,%ROWCOUNT = 0。

以下是一个例子:

     SQL> DECLARE
       2     l_cur   SYS_REFCURSOR;
       3     l_col   VARCHAR2 (10);
       4  BEGIN
       5     OPEN l_cur FOR
       6        SELECT 'Hi there' col
       7          FROM DUAL
       8         WHERE 1 = 0;
       9
      10     DBMS_OUTPUT.put_line ('Opened cursor');
      11
      12     FETCH l_cur INTO l_col;
      13
      14     DBMS_OUTPUT.put_line ('Fetched from cursor');
      15
      16     IF l_cur%NOTFOUND
      17     THEN
      18        DBMS_OUTPUT.put_line ('Oops! No data found. Raising exception...');
      19        RAISE NO_DATA_FOUND;
      20     END IF;
      21
      22     CLOSE l_cur;
      23  EXCEPTION
      24     WHEN NO_DATA_FOUND
      25     THEN
      26        DBMS_OUTPUT.put_line ('Exception raised.');
      27  END;
      28  /
     Opened cursor
     Fetched from cursor
     Oops! No data found. Raising exception...
     Exception raised.

     PL/SQL procedure successfully completed.

答案 1 :(得分:3)

稍微修改@Eddie Awad的答案,我用来从游标变量中取出的常用代码模式如下:

DECLARE 
  l_cur SYS_REFCURSOR; 
  l_col VARCHAR2 (10); 
BEGIN 
  OPEN l_cur FOR 
    SELECT 'Hi there' col 
      FROM DUAL 
      WHERE 1 = 0; 

  DBMS_OUTPUT.PUT_LINE('Opened cursor'); 

  <<cursor_loop>>
  LOOP
    FETCH l_cur INTO l_col; 

    DBMS_OUTPUT.PUT_LINE('Fetched from cursor'); 

    EXIT cursor_loop WHEN l_cur%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE('Process data fetched from cursor');    
  END LOOP;  -- cursor_loop

  CLOSE l_cur; 
  DBMS_OUTPUT.PUT_LINE('Closed cursor');
END; 

想法是打开游标变量(或从过程中取回),然后循环直到从游标中取出所有行。

分享并享受。