黑马程序员技术交流社区

标题: 触发器的实现问题 [打印本页]

作者: 林洲    时间: 2011-12-7 11:33
标题: 触发器的实现问题
本帖最后由 林洲 于 2011-12-8 17:07 编辑

为数据库中的某张表设置一个触发器,
有没有办法实现,当该表中,某条记录中的某些字段发生改变的时候就触发呢?
我的一个思路是:
1、先读取表中记录各字段的值,存于变量中;
2、隔一定的时间,再读取表中记录字段的值,存于另一组变量中;
3、循环比较各个字段的值,值不一致的就触发
这个思路可行吗,如果可行,在数据量很大的情况下,那效率就很低了,
求思路。
作者: 张连印    时间: 2011-12-7 20:47
其实没那么复杂的,触发器就是为了监控数据表中值的改变而设立的。具体如何做到监控表中值的改变,是有数据库管理系统来决定的,用户无需关心。
例子:
  1. CREATE OR REPLACE TRIGGER audit_emp_values
  2. AFTER DELETE OR INSERT OR UPDATE ON emp
  3. FOR EACH ROW
  4. BEGIN
  5.   INSERT INTO audit_emp_table (user_name, timestamp,
  6.     old_empno,new_empno,old_ename, new_ename, old_job,
  7.     new_job, old_sal, new_sal)
  8.   VALUES (USER, SYSDATE, :OLD.empno,:NEW.empno,
  9.     :OLD.ename, :NEW.ename, :OLD.job,
  10.      :NEW.job, :OLD.sal, :NEW.sal );
  11. END;
复制代码

作者: 张连印    时间: 2011-12-7 20:48
上边是Oracle数据库德写法,其他数据库系统应该大同小异。
作者: 林洲    时间: 2011-12-7 23:58
张连印 发表于 2011-12-7 20:47
其实没那么复杂的,触发器就是为了监控数据表中值的改变而设立的。具体如何做到监控表中值的改变,是有数据 ...

可是,我的需求是当表中的字段值发生改变了,才触发更新的,试想,一个系统的某张表,每天都要同步6W条的数据,第3方的同步软件都是很有压力的,现在的这个系统,前些时候2个星期,就在临时表中积累了80W条数据没有更新同步,很多都是重复的更新,消耗了第三方同步软件的所有资源,其他的数据都不能够同步了。
作者: 林洲    时间: 2011-12-8 17:00
本帖最后由 林洲 于 2011-12-8 17:05 编辑

乎乎,终于解决了
  1. CREATE TRIGGER "update_830309794" after update ON "AICJXOPT"."TB_NTMM_ENTINFO"
  2. REFERENCING   NEW as NEWO  FOR EACH ROW MODE DB2SQL
  3. BEGIN ATOMIC
  4. DECLARE v_MsgTypeId integer;
  5. DECLARE v_MsgServiceId integer;
  6. DECLARE v_QueuedAt  timestamp;
  7. set v_QueuedAt = current timestamp;  
  8. SET v_MsgTypeId = (SELECT MsgTypeId FROM BCG_MsgType where MsgTypeName = 'UU_TB_NTMM_ENTINFO_do');
  9. SET v_MsgServiceId = (SELECT MsgServiceId FROM BCG_MsgService where MsgServiceName = 'TB_NTMM_WEBSITE');
  10. INSERT INTO BCG_Msg ( MsgServiceId, MsgTypeId, MsgQueuedAt, MsgQueuedAtSeqNo, MsgStatus,MsgDeliveredAt, MsgFailedText,OperationType,MsgParam1, MsgParam2, MsgParam3, MsgParam4, MsgParam5,MsgParam6, MsgParam7, MsgParam8, MsgParam9, MsgParam10)
  11. VALUES (v_MsgServiceId, v_MsgTypeId,v_QueuedAt, null, 'NEW',null,'','update',char(NEWO."ENTID"),'','','','','','','','','');end;
复制代码
上边是原来触发器的代码,只需在set v_QueuedAt = current timestamp处,加上几句代码就OK了
  1. --测试字段
  2. CREATE TRIGGER "update_830309794" after update ON "AICJXOPT"."TB_NTMM_ENTINFO"
  3. REFERENCING   NEW as NEWO OLD as OLDO FOR EACH ROW MODE DB2SQL
  4. BEGIN ATOMIC
  5. DECLARE v_MsgTypeId integer;
  6. DECLARE v_MsgServiceId integer;  
  7. DECLARE v_QueuedAt  timestamp;
  8. if NEWO.ENTNAME<>OLDO.ENTNAME or NEWO.DOM<>OLDO.DOM then set v_QueuedAt = current timestamp;
  9. SET v_MsgTypeId = (SELECT MsgTypeId FROM BCG_MsgType where MsgTypeName = 'UU_TB_NTMM_ENTINFO_do');
  10. SET v_MsgServiceId = (SELECT MsgServiceId FROM BCG_MsgService where MsgServiceName = 'TB_NTMM_WEBSITE');
  11. INSERT INTO BCG_Msg ( MsgServiceId, MsgTypeId, MsgQueuedAt, MsgQueuedAtSeqNo, MsgStatus,MsgDeliveredAt, MsgFailedText,OperationType,MsgParam1, MsgParam2, MsgParam3, MsgParam4, MsgParam5,MsgParam6, MsgParam7, MsgParam8, MsgParam9, MsgParam10)
  12. VALUES (v_MsgServiceId, v_MsgTypeId,v_QueuedAt, null, 'NEW',null,'','update',char(NEWO."ENTID"),'','','','','','','','','');
  13. end if;
  14. end
复制代码

作者: arbtaystpw    时间: 2011-12-10 13:11
本帖最后由 arbtaystpw 于 2011-12-10 13:15 编辑

很简单的一个触发器的例子,保证你一看就会:

/*主表*/
create  table VoteMaster
(
VoteID INT PRIMARY KEY,/*主键ID*/
VoteTitle nvarchar(50) not null,/*投票主题*/
VoteSum int not null default(0),/*投票总数*/
)

insert into VoteMaster(VoteID,VoteTitle,VoteSum) values(1,'你喜欢黑马的那些老师?',0)
insert into VoteMaster(VoteID,VoteTitle,VoteSum) values(2,'wp7你觉得难学吗?',0)

select*from voteMaster

/*从表*/
create table VoteDetails
(
VoteID int foreign key references VoteMaster(VoteID),/*外键*/
VoteDetailsID int not null,/*投票流水号*/
VoteItem varchar(50) not null,
VoteNum int not null default(0),/*投票项数*/
primary  key(VoteID,VoteDetailsID)/*联合主键*/
)

select*from VoteDetails
truncate table VoteDetails

insert into VoteDetails values(1,1,'杨老师',0)
insert into voteDetails values(1,2,'邹老师',0)
insert into voteDetails values(1,3,'张老师',0)

insert into voteDetails(VoteID,VoteDetailsID,VoteItem,VoteNum) values(2,1,'非常难',0)
insert into voteDetails(VoteID,VoteDetailsID,VoteItem,VoteNum) values(2,2,'很难',0)
insert into voteDetails(VoteID,VoteDetailsID,VoteItem,VoteNum) values(2,3,'一般',0)


create trigger updateMaster
on VoteDetails
for update
as
begin
    update VoteMaster set VoteSum=VoteSum+1 where VoteID=(select top 1 VoteID from inserted)
end

/*模拟点击投票*/
update VoteDetails set VoteNum=VoteNum+1 where VoteDetailsID=1 AND VoteID=1
update VoteDetails set VoteNum=VoteNum+1 where VoteDetailsID=2 AND VoteID=1






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2