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.

Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top