执行触发器时,精确获取返回的行数超过请求的行数 SQL*PLUS

Posted

技术标签:

【中文标题】执行触发器时,精确获取返回的行数超过请求的行数 SQL*PLUS【英文标题】:exact fetch returns more than request number of rows when trigger is executed SQL*PLUS 【发布时间】:2013-12-08 18:00:44 【问题描述】:

我需要将触发器合并到我的一个使用光标的脚本中。所以我有一个带有光标的脚本,以及一个创建触发器的脚本(称为'trigEmpRaise')。触发器的创建没有错误,但是当我使用光标运行脚本(在创建触发器之前运行良好)时,我得到了这些错误:

ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "SCOTT.TRIGEMPRAISE", line 8
ORA-04088: error during execution of trigger 'SCOTT.TRIGEMPRAISE'
ORA-06512: at line 34

以下是表格的说明:

    SQL> describe empcopy
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     EMPNO                                              NUMBER(4)
     ENAME                                              VARCHAR2(10)
     JOB                                                VARCHAR2(9)
     MGR                                                NUMBER(4)
     HIREDATE                                           DATE
     SAL                                                NUMBER(7,2)
     COMM                                               NUMBER(7,2)
     DEPTNO                                             NUMBER(2)

    SQL> describe emp_prob1;
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     EMPNO                                              NUMBER(4)
     ENAME                                              VARCHAR2(10)
     DEPTNO                                             NUMBER(2)
     SAL                                                NUMBER(7,2)

    SQL> describe empraises;
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     EMPNO                                              NUMBER(4)
     ENAME                                              VARCHAR2(15)
     SAL                                                NUMBER(7,2)
     DATEOF                                             DATE

以下是脚本: 带有光标的脚本(触发触发器)

SET SERVEROUTPUT ON
DECLARE
vEMPNO          empcopy.empno%TYPE;
VENAME          empcopy.ename%TYPE;
vDEPTNO         empcopy.deptno%TYPE;
vSAL            empcopy.sal%TYPE;

CURSOR deptnoCUR IS
    SELECT empno, ename, deptno, sal
    FROM empcopy
    ORDER BY deptno;

FUNCTION calcSal
    (fDEPTNO    varchar2, fSAL  number)
    RETURN NUMBER IS
        fNewSal     empcopy.sal%TYPE;
    BEGIN
    IF fDEPTNO = 10 THEN
        fNewSal := fSAL + fSAL * .05;
    ELSE 
        IF fDEPTNO = 20 THEN
            fNewSal := fSAL + fSAL * .075;
        ELSE
            fNewSal := fSAL + fSAL * .10;
        END IF;
    END IF;
    RETURN fNewSal;
END calcSal;
BEGIN
OPEN deptnoCUR;
LOOP
    FETCH deptnoCUR INTO vEMPNO, vENAME, VDEPTNO, vSAL;
    EXIT WHEN deptnoCUR%NOTFOUND;
    vSAL := calcSal(vDEPTNO,vSAL);
INSERT INTO emp_prob1 
    VALUES(vEMPNO,vENAME,vDEPTNO,vSAL);
END LOOP;
CLOSE deptnoCUR;
END;
/
SET SERVEROUTPUT OFF
SELECT * FROM emp_prob1;

和触发脚本:

CREATE OR REPLACE TRIGGER trigEmpRaise
AFTER INSERT ON emp_prob1

DECLARE
vEMPNO      empraises.empno%TYPE;
vENAME      empraises.ename%TYPE;
vSAL        empraises.sal%TYPE;
vDATE       empraises.dateof%TYPE := sysdate;

BEGIN
SELECT empno, ename, sal
INTO vEMPNO, vENAME, vSAL
FROM emp_prob1;
INSERT INTO empraises (empno,ename,sal,dateof)
    VALUES(vEMPNO,vENAME,vSAL,vDATE);
END;
/

带有光标的脚本会简单地遍历表 EMPCOPY 中的每条记录,并根据它们所在的 DEPTNO 对它们进行提升。然后它将新值插入到表 EMP_PROB1 中。

触发器应该在将值插入到 EMP_PROB1 之后发生,并将新的薪水和插入发生的系统日期放入表 EMRAISES。

但是,无论我做什么,上述错误都会不断发生。有什么帮助吗?

【问题讨论】:

【参考方案1】:

SELECT empno, ename, sal INTO vEMPNO, vENAME, vSAL FROM emp_prob1; 必须准确返回 1 行 - 不多也不少。

我的假设是你喜欢这样做:

CREATE OR REPLACE TRIGGER trigEmpRaise
AFTER INSERT ON emp_prob1
FOR EACH ROW

BEGIN
INSERT INTO empraises (empno,ename,sal,dateof)
    VALUES(:new.empno,:new.ename,:new.sal,sysdate);
END;
/

【讨论】:

好的,但我不确定为什么它不只返回 1 行。我做错了什么? @DavidLacombe 每次执行函数时,您都会将值插入到emp_prob1 中,并且触发器内的SELECT-statement 不受任何WHERE-条件的约束,因此您基本上选择了所有多个条目

以上是关于执行触发器时,精确获取返回的行数超过请求的行数 SQL*PLUS的主要内容,如果未能解决你的问题,请参考以下文章

获取 ORA-01422 的原因:精确提取返回的行数超过了请求的行数

当我已经使用游标时,为啥我得到“精确提取返回的行数超过请求的行数”?

“精确提取返回的行数超过了请求的行数”

尝试从两列中提取多条记录时,精确提取返回的行数超过了请求的行数

PL/SQL ORA-01422:精确提取返回的行数超过了请求的行数

需要 ORA-01422 的解决方案:精确提取返回的行数超过请求的行数