首页 > 解决方案 > 是否可以使用序列的 nextval 作为 infomrix 数据库中表中字段的默认值?

问题描述

我有一个名为 T1 的表,其中包含一个字段id(int8)和一个名为seq_id.

我可以在 informix 数据库中seq_id.nextval用作默认值吗?id

或者另一种方式,我可以id在插入之前使用触发器进行更新seq_id.nextval吗?

标签: triggerssequenceinformix

解决方案


在 Informix 中,您不能将序列NEXTVAL用作列的默认值。

一种选择是将列转换为BIGSERIAL.

其他选项是使用插入触发器。我没有找到直接NEXTVAL在触发器定义中分配序列的方法,但是可以通过使用存储过程来完成。

CREATE SEQUENCE seq_id 
    INCREMENT BY 1 START WITH 1 
    MINVALUE 0 
    NOCYCLE CACHE 10 
    ORDER; 

CREATE TABLE t1
(
      id BIGINT NOT NULL
    , val1 CHAR(4)
); 

我找到了两种使用该程序的方法。返回序列的通用过程和将序列分配给 idNEXTVAL的触发过程。NEXTVAL

使用通用过程:

CREATE FUNCTION spl_get_seq_id()
RETURNING BIGINT AS seq_id_next;
    DEFINE seq_id_next BIGINT;
    LET seq_id_next = seq_id.NEXTVAL;
    RETURN seq_id_next;
END FUNCTION;

CREATE TRIGGER t1_ti
    INSERT ON t1 REFERENCING NEW AS new_ins
    FOR EACH ROW
    (
        EXECUTE FUNCTION spl_get_seq_id() INTO id
    );

向表中插入一些值并检查结果:

INSERT INTO t1( id, val1 ) VALUES ( 1000, 'AAAA' );
INSERT INTO t1( val1 ) VALUES ( 'AAAB' );
INSERT INTO t1( id ) VALUES ( 1 );
INSERT INTO t1( id, val1 ) VALUES ( NULL::BIGINT, 'AAAD' );

SELECT * FROM t1;

id val1

 1 AAAA
 2 AAAB
 3
 4 AAAD

使用触发程序:

DROP TRIGGER t1_ti;

CREATE PROCEDURE t1_ti_spl_get_seq_id()
REFERENCING NEW AS new_values FOR t1;
    LET new_values.id = seq_id.NEXTVAL;
END PROCEDURE;

CREATE TRIGGER t1_ti
    INSERT ON t1
    FOR EACH ROW
    (
        EXECUTE PROCEDURE t1_ti_spl_get_seq_id() WITH TRIGGER REFERENCES
    );

向表中插入一些值并检查结果:

INSERT INTO t1( id, val1 ) VALUES ( 1000, 'AAAE' );
INSERT INTO t1( val1 ) VALUES ( 'AAAF' );
INSERT INTO t1( id ) VALUES ( 1 );
INSERT INTO t1( id, val1 ) VALUES ( NULL::BIGINT, 'AAAH' );

SELECT * FROM t1;

id val1

 1 AAAA
 2 AAAB
 3
 4 AAAD
 5 AAAE
 6 AAAF
 7
 8 AAAH

我用于BIGINTid列,但它应该适用INT8(至于我为什么使用它,似乎有一些好处:计数器和代码:BIGINT、INT8、INTEGER 和 SMALLINT)。

编辑1:

作为对您的评论的回应,您可以根据会话用户尝试触发器上的条件。这仅在 cdc 软件使用专用用户时才有效。在此示例中,cdc_agent是 cdc 软件在 Informix 中使用的用户。

DATABASE db1;

GRANT CONNECT TO cdc_agent;
GRANT CONNECT TO myuser;

CREATE SEQUENCE seq_id 
    INCREMENT BY 2 START WITH 2 
    MINVALUE 0 
    NOCYCLE CACHE 10 
    ORDER; 

GRANT SELECT ON seq_id TO cdc_agent;
GRANT SELECT ON seq_id TO myuser;

CREATE TABLE t1
(
      id BIGINT NOT NULL
    , val1 CHAR(4)
);

GRANT ALL ON t1 TO cdc_agent;
GRANT ALL ON t1 TO myuser;

CREATE PROCEDURE t1_ti_spl_get_seq_id()
REFERENCING NEW AS new_values FOR t1;
    LET new_values.id = seq_id.NEXTVAL;
END PROCEDURE;

GRANT EXECUTE ON t1_ti_spl_get_seq_id TO cdc_agent;
GRANT EXECUTE ON t1_ti_spl_get_seq_id TO myuser;  

CREATE TRIGGER t1_ti
    INSERT ON t1 REFERENCING NEW AS new_ins
    FOR EACH ROW WHEN ( USER <> "cdc_agent" )
    (
        EXECUTE PROCEDURE t1_ti_spl_get_seq_id() WITH TRIGGER REFERENCES
    );

向表中插入一些值并检查结果:

-- with user "cdc_agent"
INSERT INTO t1( id, val1 ) VALUES ( 11, 'AAAA' );
INSERT INTO t1( id, val1 ) VALUES ( 13, 'AAAC' );
-- with user "myuser"
INSERT INTO t1( id, val1 ) VALUES ( 1, 'AAAB' );
INSERT INTO t1( id, val1 ) VALUES ( 3, 'AAAD' );

SELECT * FROM t1;   

  id val1

  11 AAAA
  13 AAAC
   2 AAAB
   4 AAAD

推荐阅读