Pergunta

Eu estou tentando escrever um gatilho em uma tabela para inserção evitar de dois nomes que não são sinalizadas como IsDeleted. Mas a primeira parte da seleção contém o inserido e assim a condição é sempre verdadeira. I embora que o uso pela palavra-chave faz com que o gatilho para executar antes da inserção, mas neste caso a linha inserida já está em cima da mesa. Estou errado ou isso é como tudo para o trabalho gatilho?

ALTER TRIGGER TriggerName
ON MyTable
FOR INSERT, UPDATE
AS
BEGIN 
    If exist (select [Name] From MyTable WHERE IsDeleted = 0 AND [Name] in (SELECT [Name] FROM INSERTED)
    BEGIN
    RAISERROR ('ERROR Description', 16, 1);
    Rollback;
    END  
END
Foi útil?

Solução

Para corridas depois os dados são alterados, em vez de é o que eu acho que você está depois.

EDIT:. Como dito por outros, em vez de corridas em vez dos dados que estão mudando, portanto, você precisa inserir os dados se ele é válido, em vez de parar a inserção se ele é inválido

Leia esta pergunta para uma explicação mais detalhada dos tipos de disparadores.

SQL Server "depois de inserir" gatilho não ver a linha recém-inserida

Outras dicas

FOR é o mesmo que AFTER. se você quiser "simular" ANTES gatilho, usar em vez de, advertência, não é exatamente o que você esperaria no gatilho ANTES adequada, ou seja, se você não fornecer as medidas necessárias vez disso, seu inseridos / dados atualizados podem ser perdidos / ignorado.

MSSQL não tem ANTES gatilho.

Para o SQL Server, PARA corre atrás do SQL que provocou isso.

De: http://msdn.microsoft.com/en-us/library/ms189799. aspx

FOR | DEPOIS

após Especifica que o gatilho DML é disparado apenas quando todas as operações especificado no SQL desencadeando declaração tenha executado com sucesso. Todas as ações em cascata referencial e verificações de restrição também deve ter sucesso perante este gatilho dispara.

AFTER é o padrão quando PARA é o única palavra-chave especificada.

após gatilhos não podem ser definidas em vista.

Eu realmente tive um problema semelhante recentemente, e encontrou uma maneira legal para lidar com isso. Eu tinha uma mesa que pode ter várias linhas para um id, mas apenas um deles poderia ser marcado como principal.

No SQL Server 2008, você vai ser capaz de fazer um índice algo parcial única como esta:

create unique index IX on MyTable(name) where isDeleted = 0;

No entanto, você pode realizá-lo com um pouco mais de trabalho no SQL Server 2005. O truque é fazer uma vista que mostra apenas as linhas que não são apagados, e em seguida, criar um índice agrupado exclusivo sobre ele:

 create view MyTableNotDeleted_vw
 with schema_binding /* Must be schema bound to create an indexed view */
 as
 select name 
 from dbo.MyTable /* Have to use dbo. for schema bound views */
 where isDeleted = 0;

 GO

 create unique clustered index IX on MyTableNotDeleted_vw ( name );

Isso vai efetivamente criar uma restrição exclusiva afetando apenas as linhas que ainda não foram apagados, e provavelmente terá um desempenho melhor do que um gatilho feito sob encomenda!

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