oracle单个表上的多个序列

oracle单个表上的多个序列,oracle,sequence,Oracle,Sequence,我希望在一个表中为一列的不同值设置不同的序列(esercizio) 我这样做,但不是动态创建和使用序列。 如何抽象这个问题 CREATE TABLE Z_TEST ( ID NUMBER, ESERCIZIO NUMBER, DESCRIZIONE VARCHAR2 (200 BYTE) ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL

我希望在一个表中为一列的不同值设置不同的序列(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; / 创建表Z_测试 ( 身份证号码, ESERCIZIO编号, descripione VARCHAR2(200字节) ) 登录中 无压 诺卡奇 不平行 监测; 更改表Z_TEST ADD(约束Z_TEST_PK主键(ID,ESERCIZIO)); 创建序列Z_TEST_SEQ_2010,从1个MAXVALUE 9999999999999999999999最小值开始,1个NOCYCLE CACHE 20 NOORDER; 创建序列Z_TEST_SEQ_2011,从1个MAXVALUE 9999999999999999999999999最小值1个NOCYCLE CACHE 20 NOORDER开始; 创建序列Z_TEST_SEQ_2012,从1个MAXVALUE 9999999999999999999999999最小值1个NOCYCLE CACHE 20 NOORDER开始; 创建序列Z_TEST_SEQ_2013,从1个MAXVALUE 9999999999999999999999999最小值1个NOCYCLE CACHE 20 NOORDER开始; 创建序列Z_TEST_SEQ_2014,从1个MAXVALUE 9999999999999999999999最小值1个NOCYCLE CACHE 20 NOORDER开始; 创建序列Z_TEST_SEQ_2015,从1个MAXVALUE 9999999999999999999999999最小值1个NOCYCLE CACHE 20 NOORDER开始; 创建或替换触发器Z_测试 插入前 关于Z_检验引用新旧 每行 声明 错误代码; err_msg VARCHAR2(200); 开始 如果:new.esercizio=2010,则从dual中选择Z_TEST_SEQ_2010.nextval至:new.ID;如果结束; 如果:new.esercizio=2011,则从dual中选择Z_TEST_SEQ_2011.nextval至:new.ID;如果结束; 如果:new.esercizio=2012,则从dual中选择Z_TEST_SEQ_2012.nextval至:new.ID;如果结束; 如果:new.esercizio=2013,则从dual中选择Z_TEST_SEQ_2013.nextval至:new.ID;如果结束; 如果:new.esercizio=2014,则从dual中选择Z_TEST_SEQ_2014.nextval至:new.ID;如果结束; 如果:new.esercizio=2015,则从dual中选择Z_TEST_SEQ_2015.nextval至:new.ID;如果结束; 当其他人 err_msg:=SUBSTR(SQLERRM,1200); 错误代码:=SQLCODE; DBMS|u OUTPUT.put_line('error:'| | | err| u code | | | | err|u msg); 结束; /
你忽视了这样做的必要性,从而抽象出问题;您正在创建无法以当前形式维护的额外数据;因此,您不应该尝试创建它

您可以创建单个序列来填充ID列,然后在使用分析函数从数据库中提取时生成辅助序列。因为序列总是递增的,所以只要按“旧”ID列排序,“新”ID列将保持有序

例如:

select row_number() over ( partition by esercizio order by id ) as id
     , descrizione
  from z_test
如果出于某种原因必须将其存储在数据库中,则可以有一个定期填充它的辅助进程

顺便说一句,使用
DBMS\u输出几乎总是不好的做法。在生产代码中放入
,以显示错误。它要求总有人在那里观看它们,这是永远不会发生的。如果你处理了一个错误,你需要做点什么


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

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;

什么意思?比如说,你想避免在获得2016年的记录之前手动创建一个新序列并更改触发器吗?为什么ID需要根据该值而有所不同-这意味着ID本身不是唯一的,因此不能作为主键,那么它是做什么的,为什么不能使用单个序列填充该列?我在access中有许多旧数据库,它们都有自己的自动编号,该表引用了other,但我有一个数据库用于年份。我认为您的两部分主键应该是
ESERCIZIO,ID
,而不是
ID,ESERCIZIO
。然后,如果您不关心序列中的间隔,那么相同的序列可以用于
ID
的所有值。有什么理由不能有间隙吗?现在我需要把所有的数据放在一起,但对所有表中的所有键重新编号,我认为这不是一个好主意。我需要保留id的实际数量,不是唯一的,而是id,ESERCIZIO是的。但不解决如何将现有数据保存到同一个表中,并从现在到将来对其进行管理。我建议的代码在开发环境中。有一种方法可以使用对象的动态名称引用序列(在PLSQL中):例如:选择“Z_TEST_SEQ_|”|:new.esercizio.nextval into:new.ID from dual;其中:new.esercizio是写入行中的esercizio列,序列名是caluclate?因为如果可能,我可以在触发器中创建所需的序列。@Albo-您可以在触发器中动态引用现有序列,但不能创建新序列;不能在触发器中执行DDL,因为它执行隐式提交。(您可能能够绕过该限制,但我认为这样做确实表明存在数据模型问题)。我可以用DDL调用外部过程吗?您能告诉我如何动态引用现有序列吗?过程不是DDL,所以不,您不能调用它。您可以动态引用现有序列,但我强烈反对@Albo这样做。我已经更新了我的答案。