我已经创建了一个以1开始的序列,没有最大值 我已经为主键插入自动创建了一个触发器,如下所示 我还为表中的表设置了一个约束,其中主键必须是唯一的,而不是null

create trigger MY_TEMP_TRIGGER
before insert on MY_TEMP
for each row

BEGIN

  SELECT MY_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)
.

结果:

误差1:
ORA-00001:唯一约束(user.pk_my_temp)违反

表my_temp已包含从1到338 fro id字段开始的值

所以,我应该如何在触发器中处理它,并在我的插入语句中处理。

有帮助吗?

解决方案

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

其他提示

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'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).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top