暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 触发器创建问题

askTom 2018-08-29
335

问题描述

我对触发器有意见。
触发器创建成功,但是一旦用户尝试对其进行测试,它就会失败。
在创建触发器之前,tester可以将新的电子邮件添加到email_t表中。但是一旦我放置触发器,他们就会得到这个:

1) Exception Information
*********************************************
Exception Type: System.Web.Services.Protocols.SoapException
Actor: 
Lang: 
Node: 
Role: 
SubCode: NULL
Message: java.sql.SQLException: Insert Error:row count=0 status=-1001 error message=ORA-01001: invalid cursor
ORA-06512: at "EMAIL_MDM_IU_TRIGGER", line 40
ORA-04088: error during execution of trigger 'EMAIL_MDM_IU_TRIGGER' column=null table=EMAIL_T
Data: System.Collections.ListDictionaryInternal
TargetSite: System.Object[] ReadResponse(System.Web.Services.Protocols.SoapClientMessage, System.Net.WebResponse, System.IO.Stream, Boolean)
HelpLink: NULL
Source: System.Web.Services
<code> 


Here is the trigger script which I am using to create trigger : 


CREATE OR REPLACE TRIGGER EMAIL_MDM_IU_TRIGGER
BEFORE INSERT OR UPDATE
ON EMAIL_T
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE
V_ID NUMBER; 
V_ENTITY_ID VARCHAR2(20); 
V_ENTITY_TYPE_CD VARCHAR2(5);

CURSOR C_ENTITY_LINK IS
           SELECT *
            FROM ENTITY_ADDR_TYPE_LINK_T EATL
            WHERE :Old.ADDR_SEQ_NBR =  EATL.ADDR_SEQ_NBR;
R_ENTITY_LINK C_ENTITY_LINK%ROWTYPE;

BEGIN 
     OPEN C_ENTITY_LINK;
         FETCH C_ENTITY_LINK INTO R_ENTITY_LINK;

        BEGIN
           IF C_ENTITY_LINK%NOTFOUND
             THEN
               CLOSE C_ENTITY_LINK;
           END IF;

          WHILE C_ENTITY_LINK%FOUND
          LOOP 
 
    SELECT MDM_SEQ_NBR.NEXTVAL INTO V_ID FROM DUAL; 
IF 
        :Old.Row_Updater_Nam != 'MDM_SERVICE_UPDT' 
    THEN

    Insert Into ABC
                      ( MDM_IUD_SEQ_NBR
                       ,ENTITY_ID
                       ,ENTITY_TYPE_CD
                       ,DATA_CHANGE_CD
                       ,TABLE_NAME
                       ,PRIMARY_KEY_COL
                       ,SECONDARY_KEY_COL
                       ,PRIMARY_KEY_VAL
                       ,ROW_PROCESS_CD
                       ,ERROR_MSG
                       ,ROW_INSERT_DT
                       ,ROW_UPDATE_DT
                       ,ROW_UPDATER_NAM)
                Values ( V_ID
                       ,V_ENTITY_ID
                       ,V_ENTITY_TYPE_CD
                       ,'C'
                       ,'EMAIL_T'
                       ,NULL
                       ,NULL
                       ,NULL
                       ,'N'
                       ,SYSDATE
                       ,NULL
                       ,NULL
                       ,'EMAIL_MDM_IU_TRIGGER'); 
END IF; 
     END LOOP;
      CLOSE C_ENTITY_LINK;
          
         
             END;
END;
/
复制


这是ABC表的脚本,它在触发触发器后插入数据:

CREATE TABLE ABC
(
  MDM_IUD_SEQ_NBR    NUMBER(20)                 NOT NULL,
  ENTITY_ID          VARCHAR2(20 BYTE)          NOT NULL,
  ENTITY_TYPE_CD     VARCHAR2(5 BYTE)           NOT NULL,
  DATA_CHANGE_CD     VARCHAR2(5 BYTE)           NOT NULL,
  TABLE_NAME         VARCHAR2(100 BYTE)         NOT NULL,
  PRIMARY_KEY_COL    VARCHAR2(50 BYTE),
  SECONDARY_KEY_COL  VARCHAR2(50 BYTE),
  PRIMARY_KEY_VAL    VARCHAR2(50 BYTE),
  ROW_PROCESS_CD     VARCHAR2(1 BYTE)           NOT NULL,
  ERROR_MSG          VARCHAR2(256 BYTE),
  ROW_INSERT_DT      DATE                       NOT NULL,
  ROW_UPDATE_DT      DATE,
  ROW_UPDATER_NAM    VARCHAR2(50 BYTE)
) 
复制


如果您可以帮助我了解问题并提供任何解决方案,那将非常有帮助。

谢谢,

专家解答

你的逻辑是错误的。如果游标不返回任何行,则会看到错误,例如

SQL> create table t as select rownum x from dual connect by level <= 5;

Table created.

SQL>
SQL> set serverout on
SQL> declare
  2    cursor c is select * from t where 1=0;   <<=== returns no rows
  3    v int;
  4  begin
  5    open c;
  6    fetch c into v;
  7    if c%notfound then
  8      close c;
  9    end if;
 10    while c%found loop
 11       dbms_output.put_line(v);
 12    end loop;
 13    close c;
 14  end;
 15  /
declare
*
ERROR at line 1:
ORA-01001: invalid cursor
ORA-06512: at line 10
复制


使用for循环和plsql进行游标管理要简单得多

SQL> set serverout on
SQL> declare
  2    cursor c is select * from t where 1=0;
  3    v int;
  4  begin
  5    for i in c loop
  6       dbms_output.put_line(i.x);
  7    end loop;
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL>
SQL> set serverout on
SQL> declare
  2    cursor c is select * from t;
  3    v int;
  4  begin
  5    for i in c loop
  6       dbms_output.put_line(i.x);
  7    end loop;
  8  end;
  9  /
1
2
3
4
5

PL/SQL procedure successfully completed.
复制


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论