Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Criar um gatilho “em vez de” no SQL Server


Ao criar um gatilho no SQL Server, você tem a opção de dispará-lo em conjunto com a instrução de gatilho (ou seja, a instrução SQL que disparou o gatilho) ou dispará-lo em vez disso dessa afirmação.

Para disparar o gatilho em vez da instrução de acionamento, use INSTEAD OF argumento.

Isso contrasta com o uso do FOR ou AFTER argumentos. Quando você usa esses argumentos, o acionador é acionado somente quando todas as operações especificadas na instrução SQL de acionamento são iniciadas com êxito.

Exemplo


Crie uma tabela de exemplo:
CREATE TABLE t1 (
    id int IDENTITY(1,1) NOT NULL,
    c1 int DEFAULT 0,
    c2 int DEFAULT 0,
    c3 int DEFAULT 0
);

Crie o acionador:
CREATE TRIGGER trg_t1
ON t1
INSTEAD OF UPDATE
AS
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted);

Insira uma linha de amostra:
INSERT INTO t1 (c1, c2, c3) 
VALUES (1, 1, 1);

SELECT * FROM t1;

Aqui está o que temos até agora:
+------+------+------+------+
| id   | c1   | c2   | c3   |
|------+------+------+------|
| 1    | 1    | 1    | 1    |
+------+------+------+------+

Agora vamos executar um UPDATE declaração contra a tabela (isso irá disparar o gatilho).
UPDATE t1 
SET c1 = c1 + 1
WHERE id = 1;

SELECT * FROM t1;

Resultado:
+------+------+------+------+
| id   | c1   | c2   | c3   |
|------+------+------+------|
| 1    | 1    | 1    | 2    |
+------+------+------+------+

Como esperado, o UPDATE A instrução na instrução de acionamento foi substituída pela do acionador.

Meu gatilho especificou que sempre que houver uma tentativa de atualização da tabela, atualize o c3 coluna em vez disso.

Executar somente quando uma coluna específica é atualizada


Você também pode usar o UPDATE() função para especificar o código a ser executado somente quando uma coluna especificada for atualizada.

Por exemplo, poderíamos alterar nosso gatilho da seguinte forma:
ALTER TRIGGER trg_t1
ON t1
INSTEAD OF UPDATE
AS
IF ( UPDATE(c1) )
BEGIN
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;

Agora execute o UPDATE anterior declaração novamente:
UPDATE t1 
SET c1 = c1 + 1
WHERE id = 1;

SELECT * FROM t1;

Resultado:
+------+------+------+------+
| id   | c1   | c2   | c3   |
|------+------+------+------|
| 1    | 1    | 1    | 3    |
+------+------+------+------+

Novamente, o c3 coluna é incrementada.

Mas, agora vamos tentar atualizar o c2 coluna:
UPDATE t1 
SET c2 = c2 + 1
WHERE id = 1;

SELECT * FROM t1;

Resultado:
+------+------+------+------+
| id   | c1   | c2   | c3   |
|------+------+------+------|
| 1    | 1    | 1    | 3    |
+------+------+------+------+

Nada muda. O c3 coluna permanece a mesma.

Nem mesmo o c2 coluna é atualizada. Isso ocorre porque o gatilho ainda é executado em vez da instrução de gatilho.

Executar Trigger em vez de DELETE


Podemos modificar o gatilho para executar em vez de qualquer DELETE declarações.
ALTER TRIGGER trg_t1
ON t1
INSTEAD OF DELETE
AS
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM deleted);

Agora vamos tentar excluir todas as linhas e, em seguida, selecionar todas as linhas da tabela.
DELETE FROM t1;

SELECT * FROM t1;

Resultado:
+------+------+------+------+
| id   | c1   | c2   | c3   |
|------+------+------+------|
| 1    | 1    | 1    | 4    |
+------+------+------+------+

Observe que para esse gatilho funcionar corretamente, tive que consultar o deleted tabela no meu gatilho (em oposição ao inserted tabela nos exemplos anteriores).

Essas duas tabelas são criadas e gerenciadas pelo SQL Server.

O deleted tabela armazena cópias das linhas afetadas durante DELETE e UPDATE declarações. Durante a execução de um DELETE ou UPDATE instrução, as linhas são excluídas da tabela de gatilhos e transferidas para a tabela excluída.

O inserted tabela armazena cópias das linhas afetadas durante INSERT e UPDATE declarações. Durante uma transação de inserção ou atualização, novas linhas são adicionadas à tabela inserida e à tabela acionadora. As linhas na tabela inserida são cópias das novas linhas na tabela de gatilhos.

Algumas restrições a serem lembradas


Você pode definir no máximo um INSTEAD OF acionado por INSERT , UPDATE , ou DELETE declaração em uma tabela ou exibição.

Você não pode definir INSTEAD OF acionados em visualizações atualizáveis ​​que usam WITH CHECK OPTION .