Проблема с созданным триггером (последовательность первичных ключей) - PullRequest
2 голосов
/ 19 мая 2011

Я создал последовательность, начинающуюся с 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 ]

1 голос
/ 19 мая 2011

Если вы действительно хотите, чтобы опция указывала собственное значение идентификатора при вставке и в других случаях использовала триггер, используя последовательность, тогда ваш триггер должен проверить, было ли передано значение - в противном случае сгенерированный триггером идентификатор будет иметь приоритет (и если вы укажите MY_TEMP_SEQ.nextval во вставке, это значение будет пропущено).

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

Работа с уже существующими значениями сложнее. Если вы никогда не собираетесь передавать свое собственное (непоследовательное) значение идентификатора, тогда вы можете просто свернуть последовательность вперед до максимального существующего значения, например ::10000

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.

Я не думаю, что вы можете справиться с этим или с вашей непосредственной проблемой в триггере; Я полагаю, что вы получите ошибку изменяющейся таблицы, если попытаетесь проверить существующее значение в той же таблице, и обходные пути для этого просто добавляют усложнение (требуется три триггера) и потенциально нестабильность. Насколько мне известно, единственный простой способ справиться с этим сценарием - вместо этого вставить обертку в процедуру и заблокировать прямую вставку, что также может оказаться невозможным. Однако вам нужно беспокоиться об этом только в том случае, если вы когда-нибудь вставите значения без использования последовательности.

0 голосов
/ 19 мая 2011

Вы можете увеличить последовательность перед установкой триггера:

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;
/
0 голосов
/ 19 мая 2011

Вы не можете использовать оба - только одно или другое.
В вашем примере значение 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, либоIDENTITY SQL Server (Denali, наконец, будет поддерживать последовательности ANSI).

...