通过触发重置序列

时间:2013-12-16 15:30:52

标签: oracle sequence

我每年都会使用触发器来重置序列,

但是在向触发器调用过程时存在一些问题

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;
/

2 个答案:

答案 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而不是触发器,这对我来说很好用