开发者

Problem with the trigger created(Fro primary key sequence)

开发者 https://www.devze.com 2023-03-07 10:17 出处:网络
I have created a sequence starting with 1 with no max value I have created a trigger for primary key insertion automatically which is below

I have created a sequence starting with 1 with no max value I have created a trigger for primary key insertion automatically which is below I have also set a constraint for the table where primary key must be unique and not null

create trigger MY_TEMP_TRIGGER
before insert on MY_TEMP
for each row

BEGIN

  SELECT M开发者_运维问答Y_TEMP_SEQ.nextval 
    INTO :new.Id 
    FROM DUAL;

END;
/

INSERT INTO my_temp  
  (Id,Type, CreateDT, TypeId, TempType, DevType, Msg, File,User, Src, SrcDev)   
VALUES
 (MY_TEMP_SEQ.nextval,3434,2843,2453,2392,435,2390,'pension.txt','rereee',454545,3434)

Result:

ERROR at line 1:

ORA-00001: unique constraint (USER.PK_MY_TEMP) violated

The table MY_TEMP already contains values starting from 1 to 338 fro Id field

So,how should i handle this in triggers and in my insert statements.


If you really do want the option to specify your own ID value on insert, and rely on the trigger using the sequence at other times, then your trigger needs to check whether it was passed a value - otherwise the trigger-generated ID will take precedence (and if you specify MY_TEMP_SEQ.nextval in the insert, that value will be skipped).

BEGIN
    IF :NEW.id IS NULL THEN
        SELECT MY_TEMP_SEQ.nextval 
        INTO :NEW.id 
        FROM DUAL;
    END IF;
END;

Dealing with values that already exist is more complicated. If you weren't ever going to pass your own (non-sequence) ID value in then you could just roll the sequence forward to the highest existing value, e.g.:

ALTER SEQUENCE MY_TEMP_SEQ INCREMENT BY 338; -- or however many you need to skip
SELECT MY_TEMP_SEQ.nextval FROM DUAL;
ALTER SEQUENCE MY_TEMP_SEQ INCREMENT BY 1;

Where you'll have a problem is if you try to insert a record manually specifying a ID value without using the sequence, which is larger than the sequence (say using 500). When the sequence (eventually) gets to that value you'll still get an ORA-00001.

I don't think you can handle that, or your immediate problem, within the trigger; I believe you'd get a mutating table error if you tried to check for an existing value in the same table, and the workarounds for that just add complication (three triggers are needed) and potentially instability. As far as I'm aware the only simple way to deal with that scenario would be to wrap the insert in a procedure instead and block direct inserts, which may not be an option either. You only need to worry about this if you'll ever insert values without using the sequence, though.


You can increment your sequence before you install the trigger:

declare 
  v_max_id my_temp.id%type;
  v_curr_seq  NUMBER;
begin
  select max(id) into v_max_id from my_temp;

  loop
    select MY_TEMP_SEQ.nextval into v_curr_seq from dual;
    exit when v_curr_seq >= v_max_id;
  end loop;
end;
/


You can't use both - only one or the other.
In your example, the id value is already inserted as the next value of the sequence... which is the same value the trigger attempts to use. I might have the order backwards, but the result is the same.

The trigger is not necessary if you'll be referencing the sequence in the INSERT statement:

INSERT INTO my_temp  
  (Id,Type, CreateDT, TypeId, TempType, DevType, Msg, File,User, Src, SrcDev)   
VALUES
  (MY_TEMP_SEQ.nextval,3434,2843,2453,2392,435,2390,'pension.txt','rereee',454545,3434);

If Using the Trigger

Having the trigger means you can't use the id column in the INSERT:

INSERT INTO my_temp  
  (Type, CreateDT, TypeId, TempType, DevType, Msg, File,User, Src, SrcDev)   
VALUES
  (3434, 2843, 2453, 2392, 435, 2390, 'pension.txt', 'rereee', 454545, 3434);

Most like the trigger approach because they're used to either MySQL AUTOINCREMENT, or SQL Server's IDENTITY (Denali will finally support the ANSI sequences).

0

精彩评论

暂无评论...
验证码 换一张
取 消