简体   繁体   中英

Oracle - Set the sequence value to max indentity value of the table within trigger

I need to get the max indentity value from the table and set the sequence to that value.

For that I'm trying to read max indentity value from the table(on which current trigger is fired) within this trigger and set the sequence to that value But Im getting mutating error when going to read the table. Im using Oracle 11g.

So my problem is there any way to set the sequence value to max indentity value of the table within this trigger? Please advice.

Here is my trigger ;

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;

The following is my answer, using which is something I am strongly against:

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

Sequences are database objects. You cannot reset them, you have to drop and recreate them. Hence you have to (ab)use dynamic SQL for this job.

This is not the best practice for creating auto-generated sequential integer primary key column values. Moreover, consider forbidding manual entries to this column as those are certainly going to create chaos in the order you are trying to maintain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM