0

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

4

1 回答 1

0

在阅读了这篇不错的帖子后,我可能已经意识到您对许多人做了一些更新。您定义了一个更新后触发器,它更新同一个表。您实际上更新了该用户的所有行。所以假设每个用户有 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@
于 2013-10-07T20:25:09.720 回答