Проблема с созданным триггером (FRO первичной ключевой последовательности)
Вопрос
Я создал последовательность, начиная с 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).