Проблема с созданным триггером (последовательность первичных ключей)
Я создал последовательность, начинающуюся с 1 без максимального значения. Я создал триггер для вставки первичного ключа автоматически, что ниже. Я также установил ограничение для таблицы, в которой первичный ключ должен быть уникальным, а не нулевым.
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 для поля Id
Итак, как я должен обрабатывать это в триггерах и в моих операторах вставки.
3 ответа
Вы можете увеличить последовательность перед установкой триггера:
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;
/
Если вы действительно хотите, чтобы опция указывала собственное значение идентификатора при вставке, а в другое время использовала триггер, используя последовательность, тогда ваш триггер должен проверить, было ли передано значение - в противном случае сгенерированный триггером идентификатор будет иметь приоритет (и если вы укажете MY_TEMP_SEQ.nextval
во вставке это значение будет пропущено).
BEGIN
IF :NEW.id IS NULL THEN
SELECT MY_TEMP_SEQ.nextval
INTO :NEW.id
FROM DUAL;
END IF;
END;
Работа с уже существующими ценностями сложнее. Если вы никогда не собираетесь передавать свое собственное (непоследовательное) значение идентификатора, тогда вы можете просто свернуть последовательность вперед до максимально возможного значения, например:
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;
Проблема может возникнуть в том случае, если вы попытаетесь вставить запись, указав значение идентификатора вручную, не используя последовательность, которая больше, чем последовательность (скажем, с использованием 500). Когда последовательность (в конце концов) достигнет этого значения, вы все равно получите ORA-00001.
Я не думаю, что вы можете справиться с этим или с вашей непосредственной проблемой в триггере; Я полагаю, что вы получите ошибку изменяющейся таблицы, если попытаетесь проверить существующее значение в той же таблице, и обходные пути для этого просто добавляют усложнение (требуется три триггера) и потенциально нестабильность. Насколько мне известно, единственный простой способ справиться с этим сценарием - это вместо этого вставить обертку в процедуру и заблокировать прямую вставку, что также может оказаться невозможным. Однако вам нужно беспокоиться об этом только в том случае, если вы когда-нибудь вставите значения без использования последовательности.
Вы не можете использовать оба - только один или другой.
В вашем примере id
значение уже вставлено в качестве следующего значения последовательности... это то же значение, которое пытается использовать триггер. У меня может быть порядок в обратном порядке, но результат тот же.
Триггер не нужен, если вы будете ссылаться на последовательность в операторе INSERT:
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);
Если использовать триггер
Наличие триггера означает, что вы не можете использовать id
столбец в 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);
Больше всего нравится триггерный подход, потому что они используются либо для MySQL AUTOINCREMENT, либо для SQL Server IDENTITY (Denali, наконец, будет поддерживать последовательности ANSI).