Problema com o gatilho criado (na sequência de chave primária)
Pergunta
Eu criei uma sequência começando com 1 sem valor máximo, criei um gatilho para a inserção de chave primária automaticamente, que está abaixo, também definei uma restrição para a tabela em que a chave primária deve ser única e não nula
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)
Resultado:
ERRO na linha 1:
ORA-00001:restrição exclusiva (USER.PK_MY_TEMP) violada
A tabela MY_TEMP já contém valores de 1 a 338 para o campo Id
Então, como devo lidar com isso nos gatilhos e nas minhas instruções de inserção.
Solução
Você pode incrementar sua sequência antes de instalar o gatilho:
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;
/
Outras dicas
Se você realmente deseja a opção de especificar seu próprio valor de ID na inserção e confiar no gatilho usando a sequência em outros momentos, então seu gatilho precisa verificar se foi passado um valor - caso contrário, o ID gerado pelo gatilho terá precedência (e se você especificar MY_TEMP_SEQ.nextval
na inserção, esse valor será ignorado).
BEGIN
IF :NEW.id IS NULL THEN
SELECT MY_TEMP_SEQ.nextval
INTO :NEW.id
FROM DUAL;
END IF;
END;
Lidar com valores que já existem é mais complicado.Se você nunca iria passar seu próprio valor de ID (sem sequência), você poderia simplesmente avançar a sequência para o valor mais alto existente, por exemplo:
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;
Você terá um problema se tentar inserir um registro especificando manualmente um valor de ID sem usar a sequência, que é maior que a sequência (digamos, usando 500).Quando a sequência (eventualmente) atingir esse valor, você ainda receberá um ORA-00001.
Não acho que você possa lidar com isso, ou com seu problema imediato, dentro do gatilho;Acredito que você receberia um erro de tabela mutante se tentasse verificar um valor existente na mesma tabela, e as soluções alternativas para isso apenas adicionam complicações (são necessários três gatilhos) e potencialmente instabilidade.Pelo que sei, a única maneira simples de lidar com esse cenário seria agrupar a inserção em um procedimento e bloquear as inserções diretas, o que também pode não ser uma opção.Você só precisa se preocupar com isso se algum dia inserir valores sem usar a sequência.
Você não pode usar os dois – apenas um ou outro.
No seu exemplo, o id
value já está inserido como o próximo valor da sequência...que é o mesmo valor que o gatilho tenta usar.Posso ter a ordem invertida, mas o resultado é o mesmo.
O gatilho não é necessário se você fizer referência à sequência na instrução 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);
Se estiver usando o gatilho
Ter o gatilho significa que você não pode usar o id
coluna no 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);
A maioria gosta da abordagem de gatilho porque eles são usados para MySQL AUTOINCREMENT ou IDENTITY do SQL Server (o Denali finalmente suportará as sequências ANSI).