如何修复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的东西,而不是您发布的代码。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...