微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何修复ORA-01422:-无法提取

如何解决如何修复ORA-01422:-无法提取

我不明白为什么会发生此错误。我已经看到了与他在一起的示例,但是人们并不使用for或fetch循环。据我所知,在这种情况下,提取将在游标的所有输出中循环,逐行查询并避免此错误

查看代码

CREATE OR REPLACE TYPE tab_dias IS TABLE OF INTEGER;

CREATE OR REPLACE FUNCTION  uf_dias_internado_paciente
(v_cod_paciente IN internacao.COD_PACIENTE%TYPE,v_dt_inicio IN internacao.DT_HORA_ENTradA %TYPE,v_dt_fim IN internacao.DT_HORA_ALTA %TYPE)
RETURN tab_dias
IS 
    v_dias tab_dias := tab_dias();
    CURSOR c_dias IS
        SELECT EXTRACT(DAY FROM (i.DT_HORA_ALTA - i.DT_HORA_ENTradA)) AS dias
        FROM INTERNACAO i 
        WHERE i.COD_PACIENTE  = v_cod_paciente
        AND i.DT_HORA_ENTradA >= v_dt_inicio --13
        AND i.DT_HORA_ALTA <= v_dt_fim;
    linha_dias c_dias%rOWTYPE;
BEGIN 
        OPEN c_dias;
        LOOP
            FETCH c_dias INTO linha_dias;
            EXIT WHEN c_dias%NOTFOUND;
            v_dias(v_dias.last) := linha_dias.dias;
        END LOOP;
        CLOSE c_dias;
        RETURN v_dias;

END;

错误ORA-01422: exact fetch returns more than requested number of rows

我正在运行的代码

SELECT uf_dias_internado_paciente (5007,CURRENT_TIMESTAMP - 500000,CURRENT_TIMESTAMP ) FROM DUAL;

所需的输出

   SELECT (EXTRACT(DAY FROM (i.DT_HORA_ALTA - i.DT_HORA_ENTradA)))
    FROM INTERNACAO i 
    WHERE i.COD_PACIENTE  = 5007
    AND i.DT_HORA_ENTradA >= CURRENT_TIMESTAMP - 500000
    AND i.DT_HORA_ALTA <= CURRENT_TIMESTAMP;

(EXTRACT(DAYFROM(I.DT_HORA_ALTA-I.DT_HORA_ENTradA)))|
----------------------------------------------------|
                                                  11|
                                                   1|
                                                   1|

Oracle文档: https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/06_ora.htm#i36655 https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/13_elems020.htm

解决方法

代码-如您所写-将返回

ORA-06502:PL / SQL:数字或值错误:NULL索引表键值

因为您缺少v_dias.EXTENDORA-01422(即TOO_MANY_ROWS)不会失败;游标不会返回它(除非您有子查询-否则就不会)。

因此,您发布的代码与您所说的代码有误。


由于我没有您的表,因此以下是基于Scott的EMP表的示例:

SQL> CREATE OR REPLACE TYPE tab_dias IS TABLE OF INTEGER;
  2  /

Type created.

SQL> CREATE OR REPLACE FUNCTION f_dias (par_deptno IN NUMBER)
  2     RETURN tab_dias
  3  IS
  4     v_dias      tab_dias := tab_dias ();
  5
  6     CURSOR c_dias IS
  7        SELECT empno AS dias
  8          FROM emp
  9         WHERE deptno = par_deptno;
 10
 11     linha_dias  c_dias%ROWTYPE;
 12  BEGIN
 13     OPEN c_dias;
 14
 15     LOOP
 16        FETCH c_dias INTO linha_dias;
 17
 18        EXIT WHEN c_dias%NOTFOUND;
 19        v_dias.EXTEND;                                   --> this
 20        v_dias (v_dias.LAST) := linha_dias.dias;
 21     END LOOP;
 22
 23     CLOSE c_dias;
 24
 25     RETURN v_dias;
 26  END;
 27  /

Function created.

测试:

SQL> SELECT f_dias (10) FROM DUAL;

F_DIAS(10)
--------------------------------------------------------------------------------
TAB_DIAS(7782,7839,7934)

或者:

SQL> SELECT * FROM TABLE(f_dias (10));

COLUMN_VALUE
------------
        7782
        7839
        7934

SQL>

代替循环,也许您应该考虑批量收集;它更简单,更有效:

SQL> CREATE OR REPLACE FUNCTION f_dias (par_deptno IN NUMBER)
  2     RETURN tab_dias
  3  IS
  4     v_dias  tab_dias := tab_dias ();
  5
  6     CURSOR c_dias IS
  7        SELECT empno AS dias
  8          FROM emp
  9         WHERE deptno = par_deptno;
 10  BEGIN
 11     OPEN c_dias;
 12
 13     FETCH c_dias BULK COLLECT INTO v_dias;
 14
 15     CLOSE c_dias;
 16
 17     RETURN v_dias;
 18  END;
 19  /

Function created.

SQL> SELECT * FROM TABLE (f_dias (10));

COLUMN_VALUE
------------
        7782
        7839
        7934

SQL>

因此,基本上,它有效。还有其他产生TOO_MANY_ROWS的东西,而不是您发布的代码。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。