2014-09-05 30 views
0

我需要从表格中获取最大缩进值并将序列设置为该值。Oracle - 将序列值设置为触发器内表格的最大缩进值

为此,我试图从该触发器中读取表中的最大订单值(触发当前触发器)并将该序列设置为该值 但是,当读取表时,我得到突变错误。我使用Oracle 11g。

所以我的问题是有什么办法将序列值设置为此触发器中表的最大缩进值?请指教。

这是我的触发器;

create or replace 
TRIGGER StringTextTrg BEFORE INSERT ON StringText 
FOR EACH ROW 
DECLARE 
v_newVal NUMBER(12) := 0; 
v_incval NUMBER(12) := 0; 
BEGIN 
IF INSERTING AND :new.STxtID IS NULL THEN 
SELECT StringText_STxtID_SEQ.NEXTVAL INTO v_newVal FROM DUAL; 
-- If this is the first time this table have been inserted into (sequence == 1) 
IF v_newVal = 1 THEN 
    --get the max indentity value from the table 
    SELECT NVL(max(STxtID),0) INTO v_newVal FROM StringText; 
    v_newVal := v_newVal + 1; 
    --set the sequence to that value 
    LOOP 
     EXIT WHEN v_incval>=v_newVal; 
     SELECT StringText_STxtID_SEQ.nextval INTO v_incval FROM dual; 
    END LOOP; 
    END IF; 
-- assign the value from the sequence to emulate the identity column 
:new.STxtID := v_newVal; 
END IF; 
END; 
+0

为什么你想要从触发器做到这一点?如果您将代码从手动设置ID更改为从序列中设置代码,那么在定义序列时使用正确的初始值是一次性任务吗? – 2014-09-05 09:13:49

+0

@ Alex - ID可以通过代码手动设置。我只是想迎合这两种情况..任何建议? – LittleBit 2014-09-05 10:08:03

+2

你的'IF v_newVal = 1 THEN'意味着它只会试图检查最大值并调整序列是新的。我的建议是不允许这两种方法,这不是很有用,但会为你节省很多痛苦;但这与你所要求的不同,除非你允许可能高于序列值的手动值(而不是填补空白,甚至通常是一个坏主意)。 – 2014-09-05 10:14:12

回答

0

以下是我的回答,使用这是一件好事,我强烈反对:

CREATE OR REPLACE TRIGGER StringTextTrg 
    BEFORE INSERT 
    ON StringText 
    FOR EACH ROW 
DECLARE 
    v_newVal NUMBER (12) := 0; 
    v_incval NUMBER (12) := 0; 
BEGIN 
    IF INSERTING AND :new.STxtID IS NULL THEN 
     SELECT StringText_STxtID_SEQ.NEXTVAL INTO v_newVal FROM DUAL; 

     -- If this is the first time this table have been inserted into (sequence == 1) 
     IF v_newVal = 1 THEN 
      --get the max indentity value from the table 
      SELECT NVL (MAX (STxtID), 0) INTO v_newVal FROM StringText; 

      v_newVal := v_newVal + 1; 

      --set the sequence to that value 
      EXECUTE IMMEDIATE ('DROP SEQUENCE StringText_STxtID_SEQ'); 
      EXECUTE IMMEDIATE ('CREATE SEQUENCE StringText_STxtID_SEQ START WITH '||to_char(v_newVal)); 
     END IF; 

     -- assign the value from the sequence to emulate the identity column 
     :new.STxtID := v_newVal; 
    END IF; 
END; 
/

序列是数据库对象。你不能重置它们,你必须删除并重新创建它们。因此你必须(ab)为这项工作使用动态SQL。

这不是创建自动生成的顺序整数主键列值的最佳做法。此外,考虑禁止手动输入此列,因为这些列表肯定会按您尝试维护的顺序创建混乱。

+0

问题实际上是在这里:'SELECT NVL(MAX(STxtID),0)INTO v_newVal FROM StringText;'这引发了突变错误。不设置序列值。但我尊重你禁止手动输入的想法。 – LittleBit 2014-09-06 05:14:40

+0

然后,您可以尝试创建复合触发器,将上述查询放入语句级别部分,并在行级别查询中使用该变量。你使用哪个版本的Oracle? – Rachcha 2014-09-06 13:29:23

+0

我正在使用Oracle 11g – LittleBit 2014-09-06 15:24:23

相关问题