免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 2844 | 回复: 19
打印 上一主题 下一主题

trigger问题求助  [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-04-03 11:21 |只看该作者 |倒序浏览
下面是一个oracle的trigger,创建的时候没有问题,但是update操作的时候,
出现ORA-04091错误,也就是对行触发器来讲,对当前正在改变的表不允许做select操作,但是如果不用行触发器的话,无法知道当前改变的列的值,哪位高人能指点一二,万分感谢。
CREATE OR REPLACE TRIGGER TRIGGER_PING_MONITOR
AFTER DELETE OR INSERT OR UPDATE OF RecordStatus ON PINGMONITOR_ADMIN
FOR EACH ROW
DECLARE
v_num  NUMBER;
BEGIN

SELECT COUNT(*) INTO v_num FROM PINGMONITOR_ADMIN WHERE PINGMONITOR_ADMIN.PingMonitorID=:NEW.PingMonitorID AND PINGMONITOR_ADMIN.RecordStatus=0;
IF v_num>;0 THEN
UPDATE NODE_ADMIN SET PingMonitor = 1   
WHERE NODE_ADMIN.NodeID=:NEW.PingMonitorID;
ELSE
UPDATE NODE_ADMIN SET PingMonitor = 0   
WHERE NODE_ADMIN.NodeID=:NEW.PingMonitorID;
END IF;

END TRIGGER_PING_MONITOR;
/


SQL>; desc PINGMONITOR_ADMIN ;
名前                                      NULL?    型
----------------------------------------- -------- -------------
PINGMONITORID                             NOT NULL VARCHAR2(15)
PINGMONITORCNT                            NOT NULL NUMBER(2)
RECORDSTATUS                                       NUMBER(1)
RECORDUPDATETIME                                   DATE
RECORDCREATETIME                                   DATE

SQL>; desc NODE_ADMIN
名前                                      NULL?    型
----------------------------------------- -------- ------------------
NODEID                                    NOT NULL VARCHAR2(15)
IP                                                 VARCHAR2(40)
GLOBALIP                                           VARCHAR2(40)
HOSTNAME                                           VARCHAR2(64)
PINGMONITOR                                        NUMBER(1)
SERVICEPORTMONITOR                                 NUMBER(1)
PROCESSMONITOR                                     NUMBER(1)
RESOURCEMONITOR                                    NUMBER(1)
LOGMONITOR                                         NUMBER(1)
SNMP_TRAPMONITOR                                   NUMBER(1)
RECORDSTATUS                                       NUMBER(1)
RECORDUPDATETIME                                   DATE
RECORDCREATETIME                                   DATE

论坛徽章:
0
2 [报告]
发表于 2003-04-03 11:56 |只看该作者

trigger问题求助 

你的PINGMONITOR_ADMIN.PingMonitorID是primary key吗?如是
把IF v_num>;0 THEN 改为
if :NEW.PINGMONITOR_ADMIN.RecordStatus=0 then
如不是primary key 那是哪一个
能否把你的意图写一下,表中是否有重复行
一般来说insert or update tigger写在一起的话,可用
if inserting then
--如果是插入
--这时候可以引用:NEW.PINGMONITOR_ADMIN.RecordStatus,但:OLD.PINGMONITOR_ADMIN.RecordStatus是空的
else
--如果是update
--这时:OLD,:NEW都可以引用
end if
我昨天也遇上这个问题,确实不能触发器上对触发表做SELECT

论坛徽章:
0
3 [报告]
发表于 2003-04-03 13:05 |只看该作者

trigger问题求助 

谢谢你的回答.

PINGMONITOR_ADMIN.PingMonitorID和PINGMONITOR_ADMIN.PINGMONITORCNT是primary key
可能是我没说清楚.

是UPDATE或者DELETE的时候,我需要知道PINGMONITOR_ADMIN里符合条件的
记录有没有再去更新NODE_ADMIN.

你的解决方法只能对应UPDATE一条记录的情况.这时候我并不能知道PINGMONITOR_ADMIN里符合条件的记录有没有.

论坛徽章:
0
4 [报告]
发表于 2003-04-03 13:44 |只看该作者

trigger问题求助 

你根本不用去判断
假设你的update或delete是由
update(or delete)  PINGMONITOR_ADMIN set  PINGMONITOR_ADMIN.RecordStatus=0 where PINGMONITOR_ADMIN.PingMonitorID=条件 and  PINGMONITOR_ADMIN.RecordStatus=0;来触发的
那么你直接引用:NEW和:OLD就行了
注意:delete 是没有 :NEW的
如不是上面的假设触发条件,那你把可能的引起触发的语句都写一下行吗?
包括insert,update,delete

论坛徽章:
0
5 [报告]
发表于 2003-04-03 14:03 |只看该作者

trigger问题求助 

问题是我不知道update,delete是的where条件.

就个例子:
PINGMONITOR_ADMIN 中有以下几条记录:
PINGMONITORID ,PINGMONITORCNT,RECORDSTATUS,RECORDUPDATETIME,RECORDCREATETIME
A1,1,0, ,
A1,2,0, ,
A1,3,0, ,
A1,4,9, ,
这时候NODE_ADMIN.PingMonitor =1,如果我删除
A1,1,0, ,
那么NODE_ADMIN.PingMonitor还是1
如果我删除
A1,1,0, ,
A1,2,0, ,
A1,3,0, ,
那么NODE_ADMIN.PingMonitor=0

论坛徽章:
0
6 [报告]
发表于 2003-04-03 15:47 |只看该作者

trigger问题求助 

根据你的trigger 我以为使用表级触发器就可以,使用表级触发不能满足你的要求吗?非得要使用行级触发吗?

论坛徽章:
0
7 [报告]
发表于 2003-04-03 16:34 |只看该作者

trigger问题求助 

可以使用表级触发器的,但是我不熟.
愿闻其详.
谢了先.

论坛徽章:
0
8 [报告]
发表于 2003-04-03 20:37 |只看该作者

trigger问题求助 

把for each row去掉就可以了。

论坛徽章:
0
9 [报告]
发表于 2003-04-04 11:19 |只看该作者

trigger问题求助 

把fro each row去掉也不一定行,因为它要对本表进行查询,可以编译通过,但在运行时却提示本表已被改变。
对于本贴可采用以下办法。
建立一个对表PINGMONITOR_ADMIN中PingMonitorID的数量的监控表
create table pingmon as select PingMonitorID,count(*) coun
        from PINGMONITOR_ADMIN
        where RecordStatus=0
        group by PingMonitorID;
在表PINGMONITOR_ADMIN上建立两个触发器,一个before 一个after
create or replace trigger PINGMONITOR_ADMIN_BE
before delete on PINGMONITOR_ADMIN
for each row
begin
        update pingmon set coun=coun-1
        where PINGMONITORid=:OLD.PINGMONITORid;
--因为这是个行级触发器,所以每删除一行就会在监控表pingmon上相应coun上减1
if sql%rowcount=0 then
        insert into pingmon values (:OLD.PINGMONITORid,1);
--如果在监控表上无相应的行,就插入一行
end if;
end;

create or replace trigger PINGMONITOR_ADMIN_AF
after delete on PINGMONITOR_ADMIN
for each row
begin
UPDATE NODE_ADMIN a SET PingMonitor =
                (select decode(nvl(coun,0),0,0,1) from pingmon b
                        where a.PINGMONITORid=b.PINGMONITORid(+))
--如果监控表上相应行coun为零,NODE_ADMIN就置0,否则置1
end;
你还要做insert和update的触发器来维护pingmon、NODE_ADMIN和PINGMONITOR_ADMIN的一致性问题,这是关键问题

论坛徽章:
0
10 [报告]
发表于 2003-04-04 12:02 |只看该作者

trigger问题求助 

原帖由 "OL.O" 发表:
把fro each row去掉也不一定行,因为它要对本表进行查询,可以编译通过,但在运行时却提示本表已被改变。


really ?

NO!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP