我希望在单个表中针对列的不同值(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; /
答案 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;