oracle在单个表上的多个序列

时间:2014-02-18 14:42:33

标签: oracle sequence

我希望在单个表中针对列的不同值(esercizio)使用不同的序列。

我这样做但不是动态创建和使用序列。 如何抽象出问题?


    CREATE TABLE Z_TEST
    (
        ID            NUMBER,
        ESERCIZIO     NUMBER,
        DESCRIZIONE   VARCHAR2 (200 BYTE)
    )
    LOGGING
    NOCOMPRESS
    NOCACHE
    NOPARALLEL
    MONITORING;

    ALTER TABLE Z_TEST ADD (  CONSTRAINT Z_TEST_PK PRIMARY KEY (ID, ESERCIZIO));

    CREATE SEQUENCE Z_TEST_SEQ_2010 START WITH 1 MAXVALUE 999999999999999999999999999 MINVALUE 1 NOCYCLE CACHE 20 NOORDER;
    CREATE SEQUENCE Z_TEST_SEQ_2011 START WITH 1 MAXVALUE 999999999999999999999999999 MINVALUE 1 NOCYCLE CACHE 20 NOORDER;
    CREATE SEQUENCE Z_TEST_SEQ_2012 START WITH 1 MAXVALUE 999999999999999999999999999 MINVALUE 1 NOCYCLE CACHE 20 NOORDER;
    CREATE SEQUENCE Z_TEST_SEQ_2013 START WITH 1 MAXVALUE 999999999999999999999999999 MINVALUE 1 NOCYCLE CACHE 20 NOORDER;
    CREATE SEQUENCE Z_TEST_SEQ_2014 START WITH 1 MAXVALUE 999999999999999999999999999 MINVALUE 1 NOCYCLE CACHE 20 NOORDER;
    CREATE SEQUENCE Z_TEST_SEQ_2015 START WITH 1 MAXVALUE 999999999999999999999999999 MINVALUE 1 NOCYCLE CACHE 20 NOORDER;

    CREATE OR REPLACE TRIGGER Z_TEST_TRG
        BEFORE INSERT
        ON Z_TEST     REFERENCING new AS New old AS Old
        FOR EACH ROW
    DECLARE
        err_code    NUMBER;
        err_msg     VARCHAR2 (200);
    BEGIN
        if :new.esercizio = 2010 then select Z_TEST_SEQ_2010.nextval into :new.ID from dual; end if;
        if :new.esercizio = 2011 then select Z_TEST_SEQ_2011.nextval into :new.ID from dual; end if;
        if :new.esercizio = 2012 then select Z_TEST_SEQ_2012.nextval into :new.ID from dual; end if;
        if :new.esercizio = 2013 then select Z_TEST_SEQ_2013.nextval into :new.ID from dual; end if;
        if :new.esercizio = 2014 then select Z_TEST_SEQ_2014.nextval into :new.ID from dual; end if;
        if :new.esercizio = 2015 then select Z_TEST_SEQ_2015.nextval into :new.ID from dual; end if;
    EXCEPTION WHEN OTHERS THEN
        err_msg := SUBSTR (SQLERRM, 1, 200);
        err_code := SQLCODE;
        DBMS_OUTPUT.put_line ('errore: ' || err_code || ' ' || err_msg);
    END;
    /

1 个答案:

答案 0 :(得分:1)

你忽略了这样做的必要性来抽象问题;您正在创建无法以其当前形式维护的额外数据;所以你不应该试图创造它。

您可以创建单个序列来填充ID列,然后使用分析函数ROW_NUMBER()从数据库中提取时生成辅助序列。由于序列始终递增,因此只要您按“旧”ID列进行排序,就可以保证“新”ID列保持有序。

例如:

select row_number() over ( partition by esercizio order by id ) as id
     , descrizione
  from z_test

如果您出于某种原因绝对必须将其存储在数据库中,则可以使用辅助流程定期填充它。

另外,在生产代码中使用DBMS_OUTPUT.PUT_LINE来显示错误几乎总是不好的做法。它要求有人总是在那里查看它们,这是永远不会发生的。如果您处理错误,则需要对其进行处理。


我不同意这样做,因为没有必要,但如果您愿意,可以动态引用序列:

CREATE OR REPLACE TRIGGER Z_TEST_TRG
    BEFORE INSERT
    ON Z_TEST
    FOR EACH ROW
BEGIN
   execute immediate 'select z_test_seq' || :new.esercizio || '.nextval 
                        from dual'
                into :new.id;
END;