2014-02-18 2 views
0

다른 열의 값 (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

당신은 무엇을 의미합니까? 2016로 레코드를 얻기 전에 수동으로 새 시퀀스를 만들고 트리거를 변경하지 않아도되고 싶습니까? ID가 그 값에 따라 달라야하는 이유는 ID 자체가 고유하지 않으므로 기본 키가 될 수 없다는 것을 의미합니다. 따라서 그 이유는 무엇이며, 왜 단일 시퀀스를 사용하여 그 값을 채울 수 없습니까? 기둥? –

+0

나는 자신의 자치 번호가있는 액세스 권한이있는 많은 오래된 데이터베이스를 가지고 있지만 다른 테이블 참조는 1 년 동안 데이터베이스가 1 개 있습니다. – Albo

+0

두 부분으로 구성된 기본 키는'ID, ESERCIZIO'보다는'ESERCIZIO, ID' 여야한다고 생각합니다. 그런 다음 시퀀스의 틈새에 신경 쓰지 않는다면 동일한 시퀀스가 ​​모든 ID 값에 사용될 수 있습니다. 갭을 가질 수없는 이유가 있습니까? – Glenn

답변

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; 
+0

탱크는 있지만 기존 데이터를 동일한 테이블에 보관하고 현재부터 미래까지 관리하는 방법을 해결하지 못합니다. 내가 제안하는 코드는 개발 환경에 있습니다. – Albo

+0

오브젝트의 동적 이름을 사용하여 시퀀스를 참조하는 방법은 다음과 같습니다 ( ). 'Z_TEST_SEQ_'|| new.esercizio.nextval : new.ID from dual; 여기서 : new.esercizio는 행을 쓰는 중 열이고 시퀀스 이름은 caluclate입니까? 가능하다면 나는 방아쇠에 필요한 순서를 만들 수 있습니다. – Albo

+1

@Albo - 트리거에서 기존 시퀀스를 동적으로 참조 할 수 있지만 새 시퀀스를 작성할 수는 없습니다. 암시 적 커밋을 수행하기 때문에 트리거에서 DDL을 수행 할 수 없습니다. (당신은 일할 수/그 제한을 해킹하지만 정말 그렇게 데이터 모델 문제를 나타냅니다, 내 생각). –

관련 문제