我每年都会使用触发器来重置序列,
但是在向触发器调用过程时存在一些问题
CREATE OR REPLACE TRIGGER t_dmd_pk
BEFORE INSERT
ON S_DEMANDE
FOR EACH ROW
BEGIN
IF (TO_CHAR (SYSDATE, 'dd') = '16' AND TO_CHAR (SYSDATE, 'mm') = '12')
THEN
reset_seq ('SEQ_ID_DMD');
END IF;
SELECT SEQ_ID_DMD.NEXTVAL || TO_CHAR (SYSDATE, 'yyyy')
INTO :new.DMD_ID
FROM DUAL;
END;
/
那是我的程序
CREATE OR REPLACE PROCEDURE reset_seq (p_seq_name IN VARCHAR2)
IS
l_val NUMBER;
BEGIN
EXECUTE IMMEDIATE 'select ' || p_seq_name || '.nextval from dual'
INTO l_val;
EXECUTE IMMEDIATE
'alter sequence ' || p_seq_name || ' increment by -' || l_val;
END;
/
答案 0 :(得分:1)
你的程序没有按照你认为应该的方式工作..如果你的序列最后一个值是10,那么你每次调用时都要改变序列增加-10。我猜你第一次执行它,你得到一个ORA-08004,因为你的minvalue可能是1,它会尝试返回0(这是不允许的)。即使这没有错误,下次你调用它也会,因为它会尝试在我的例子中返回-10。我相信你真正想要的是:
CREATE OR REPLACE PROCEDURE reset_seq (p_seq_name IN VARCHAR2)
IS
l_val NUMBER;
BEGIN
-- Get Current Value of Sequence
EXECUTE IMMEDIATE 'select ' || p_seq_name || '.nextval from dual'
INTO l_val;
-- Alter to sequence to allow to go to 0 and decrease by current value
EXECUTE IMMEDIATE
'alter sequence ' || p_seq_name || ' minvalue 0 increment by -' || l_val;
-- Get value from sequence again (should set seq to 0)
EXECUTE IMMEDIATE 'select ' || p_seq_name || '.nextval from dual'
INTO l_val;
-- Alter sequence to increase by 1 again
EXECUTE IMMEDIATE
'alter sequence ' || p_seq_name || ' increment by 1';
END;
这允许序列为0(如果希望下一次调用返回1,则需要该序列),将其设置为0,然后在每次连续调用时将其更改为1。但是,删除并重新创建序列可能要容易得多。
真正的问题是,为什么你会想要这样做。这看起来像糟糕的设计。序列只是返回一个唯一的数字。没有更多,没有更少。数字背后应该没有任何意义,看起来你似乎想在这里指定意义。序列不保证您的行将按顺序插入,并且不保证不会有间隙,它们只提供唯一的编号。连接这个独特数字结尾的年份使这个设计更加可疑。
答案 1 :(得分:0)
我找到了一个解决方案,我使用了dbms_job而不是触发器,这对我来说很好用