Informix中插入触发器的自引用更新

时间:2011-12-05 10:28:25

标签: stored-procedures triggers informix

我将各种来源的数据提取到一个表中。在这个新表中,有一个名为lineno的字段。该字段值应根据公司代码和批号顺序排列。我写了以下程序

CREATE PROCEDURE update_line(company CHAR(4), batch CHAR(8), rcptid CHAR(12));

DEFINE lineno INT;

SELECT Count(*) 
INTO lineno
FROM tmp_cb_rcpthdr
WHERE cbrh_company = company
AND cbrh_batchid = batch;

UPDATE tmp_cb_rcpthdr
SET cbrh_lineno = lineno + 1
WHERE cbrh_company = company
AND cbrh_batchid = batch
AND cbrh_rcptid = rcptid;

END PROCEDURE;

将使用以下触发器

调用此过程
CREATE TRIGGER tmp_cb_rcpthdr_ins INSERT ON tmp_cb_rcpthdr 
REFERENCING NEW AS n
FOR EACH ROW
(
    EXECUTE PROCEDURE update_line(n.company, cbrh_batchid, cbrh_rcptid)
);

然而,我收到以下错误

  

SQL错误= -747表或列匹配中引用的对象   触发声明。

从oninit.com,我了解到触发的SQL语句引起的错误会对触发表起作用,在本例中是触发表是UPDATE语句。 所以我的问题是,我该如何解决这个问题?是否有任何解决方案或更好的解决方案?

1 个答案:

答案 0 :(得分:1)

我认为需要重新考虑设计。首先,如果某些行从tmp_cb_rcpthdr中删除会发生什么? COUNT(*)查询将导致重复的lineno值。

即使这是一个仅限ETL的流程,并且您可以确信数据不会从其他地方进行操作,性能将成为一个问题,并且只会使您拥有的任何一个公司和BATCH_ID。

lineno是否有必要从零开始增加,还是只是为了维持原始的加载顺序?因为如果是后者,表格中的SEQUENCESERIAL字段将实现相同的结果,并且 lot 更有效。

如果你必须以这种方式生成lineno,我建议你创建第二个控制表,键入公司和batch_id,跟踪当前的lineno值,即:(未经测试)

CREATE PROCEDURE update_line(company CHAR(4), batch CHAR(8));

    DEFINE lineno INT;

    SELECT cbrh_lineno INTO lineno 
    FROM linenoctl
    WHERE cbrh_company = company
    AND cbrh_batchid = batch;

    UPDATE linenoctl
    SET cbrh_lineno = lineno + 1
    WHERE cbrh_company = company
    AND cbrh_batchid = batch;
    -- A test that no other process has grabbed this record
    -- might need to be considered here, ie cbrh_lineno = lineno

    RETURN lineno + 1
END PROCEDURE;

然后按如下方式使用:

CREATE TRIGGER tmp_cb_rcpthdr_ins INSERT ON tmp_cb_rcpthdr 
REFERENCING NEW AS n
FOR EACH ROW
(
    EXECUTE PROCEDURE update_line(n.company, cbrh_batchid) INTO cbrh_lineno
);

有关使用带触发器的计算值,请参阅IDS documentation for more

相关问题