DB2触发器超时

时间:2013-10-07 14:52:06

标签: sql triggers db2

我有以下触发器,确保只有一个记录具有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

1 个答案:

答案 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@