我有以下触发器,确保只有一个记录具有DEFAULTCARD = 1
字段create trigger TRG_U_XSTRDCRD
after update on XSTOREDCARD referencing new as N old as O
for each row mode db2sql
begin atomic
if N.DEFAULTCARD = 1 then
update XSTOREDCARD
set DEFAULTCARD = 0
where USERS_ID = N.USERS_ID and ID <> N.ID;
end if;
end@
我还想确保只有一条记录的EBACTIVE字段值为1,所以我尝试了这个。
create trigger TRG_U_XSTRDCRD
after update on XSTOREDCARD referencing new as N old as O
for each row mode db2sql
begin atomic
if N.DEFAULTCARD = 1 then
update XSTOREDCARD
set DEFAULTCARD = 0
where USERS_ID = N.USERS_ID and ID <> N.ID;
end if;
if N.EBACTIVE = 1 then
update XSTOREDCARD
set EBACTIVE = 0
where USERS_ID = N.USERS_ID and ID <> N.ID;
end if;
end@
但它没有用,它会在更新几分钟后导致超时:
Caused by: com.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -101, SQLSTATE: 54001, SQLERRMC: null
at com.ibm.db2.jcc.b.zc.e(zc.java:1606)
at com.ibm.db2.jcc.b.zc.a(zc.java:1206)
at com.ibm.db2.jcc.a.db.h(db.java:149)
at com.ibm.db2.jcc.a.db.a(db.java:43)
at com.ibm.db2.jcc.a.r.a(r.java:30)
at com.ibm.db2.jcc.a.sb.g(sb.java:152)
at com.ibm.db2.jcc.b.zc.n(zc.java:1186)
at com.ibm.db2.jcc.b.ad.db(ad.java:1761)
at com.ibm.db2.jcc.b.ad.d(ad.java:2203)
at com.ibm.db2.jcc.b.ad.V(ad.java:521)
at com.ibm.db2.jcc.b.ad.executeUpdate(ad.java:504)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2595)
... 19 more
有关错误或如何做的任何建议?
干杯! NFV
答案 0 :(得分:0)
阅读this nice post后,我可能已经意识到你对很多人做了一些更新。您定义了一个更新后触发器,它会更新同一个表。实际上,您更新了该用户的所有行。所以假设每个用户有10行,一行更改了DEFAULTCARD标志。这意味着无论是否需要更新,都会更新9行。这听起来不是什么大问题,但是,如果您有5,000,000条记录,那么即使您只需要更新一条记录(即旧的DEFAULTCARD记录),您也会更新4,999,999条记录。
update XSTOREDCARD
set DEFAULTCARD = 0
where USERS_ID = N.USERS_ID and DEFAULTCARD = 1 and ID <> N.ID;
此声明仅应影响1或不影响记录。因此,您只需要进行一次更新,而不是运行4,999,999次更新和触发调用。
EBACTIVE也是如此。更好的是,如果EBACTIVE和DEFAULTCARD对于不同的记录是1,它将变得非常混乱,因为更新到EBACTIVE将触发对DEFAULTCARD的更新,这将再次触发对EBACTIVE的更新。所以,如果我没有弄错的话,你处于无限循环中。
begin atomic
if N.DEFAULTCARD = 1 then
update XSTOREDCARD
set DEFAULTCARD = 0
where USERS_ID = N.USERS_ID and DEFAULTCARD = 1 and ID <> N.ID;
end if;
if N.EBACTIVE = 1 then
update XSTOREDCARD
set EBACTIVE = 0
where USERS_ID = N.USERS_ID and EBACTIVE = 1 and ID <> N.ID;
end if;
end@
这应该更好。
编辑:第二次尝试
如果值实际发生了变化,我应该只更新数据集。
begin atomic
if N.DEFAULTCARD = 1 and O.DEFAULTCARD != 1 then
update XSTOREDCARD
set DEFAULTCARD = 0
where USERS_ID = N.USERS_ID and DEFAULTCARD = 1 and ID <> N.ID;
end if;
if N.EBACTIVE = 1 and O.EBACTIVE !=1 then
update XSTOREDCARD
set EBACTIVE = 0
where USERS_ID = N.USERS_ID and EBACTIVE = 1 and ID <> N.ID;
end if;
end@