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

Como executar um gatilho somente quando uma coluna específica é atualizada (SQL Server)


No SQL Server, você pode criar gatilhos DML que executam código somente quando uma coluna específica é atualizada.

O gatilho ainda é acionado, mas você pode testar se uma coluna específica foi atualizada ou não e, em seguida, executar o código somente se essa coluna tiver sido atualizada.

Você pode fazer isso usando o UPDATE() função dentro do seu gatilho. Esta função aceita o nome da coluna como seu argumento. Ele retorna um booleano.

Exemplo


Aqui está a tabela:
CREATE TABLE t1 (
    id int IDENTITY(1,1) NOT NULL,
    c1 int DEFAULT 0,
    c2 int DEFAULT 0,
    c3 int DEFAULT 0
);

E aqui está o gatilho:
CREATE TRIGGER trg_t1
ON t1
AFTER INSERT, UPDATE
AS
IF ( UPDATE (c1) )
BEGIN
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;

Neste exemplo, crio uma tabela chamada t1 e um gatilho chamado trg_t1 .

Eu uso um IF instrução junto com o UPDATE() função para testar se o c1 coluna foi atualizada.

Quando o gatilho é executado, ele só executará o código subsequente se essa condição for verdadeira.

Acione o gatilho


Vamos inserir uma linha, mas inseriremos apenas um valor no c1 coluna.
INSERT INTO t1 (c1) 
VALUES (1);

SELECT * FROM t1;

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

Como esperado, o gatilho foi acionado e a coluna c3 também foi atualizado.

Isso aconteceu porque incluí o INSERT argumento na definição do meu gatilho (ou seja, eu especifiquei AFTER INSERT, UPDATE o que significa que o gatilho é acionado sempre que os dados são inseridos ou atualizados). Se eu tivesse especificado apenas AFTER UPDATE , ele não teria disparado quando eu inseri dados – ele só dispararia sempre que eu atualizasse os dados existentes.

Lembre-se que a tabela foi definida com DEFAULT 0 , então a coluna c2 assumiu o padrão zero.

Agora vamos atualizar o c1 coluna.
UPDATE t1 
SET c1 = c1 + 1
WHERE id = 1;

SELECT * FROM t1;

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

Novamente, o c3 coluna foi atualizada junto com c1 .

Agora vamos fazer uma atualização para o c2 coluna (esta coluna não está incluída no gatilho).
UPDATE t1 
SET c2 = c2 + 1
WHERE id = 1;

SELECT * FROM t1;

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

Desta vez, c2 foi atualizado, mas c3 não era. Isso porque o c1 a coluna não foi atualizada e nosso gatilho apenas atualiza c3 quando c1 é atualizada.

A mesma coisa aconteceria se tivéssemos inserido uma linha sem especificar c1 no INSERT demonstração.

E se eu atualizar a coluna com o mesmo valor?


Se você atualizar uma coluna com o mesmo valor, o UPDATE() função retornará verdadeiro.

Aqui está um exemplo.

Sabemos de nossos exemplos anteriores que a coluna c1 contém um valor de 2 .

Vamos atualizar explicitamente essa coluna com o mesmo valor:1
UPDATE t1 
SET c1 = 2
WHERE id = 1;

SELECT * FROM t1;

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

Então agora c3 foi incrementado, mesmo que o valor para c1 ainda é o mesmo.

Vamos fazê-lo novamente, mas desta vez defina-o para si mesmo (ou seja, altere c1 = 1 para c1 = c1 ).
UPDATE t1 
SET c1 = c1
WHERE id = 1;

SELECT * FROM t1;

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

Novamente, c3 tem incrementado.

Tentativas de atualização malsucedidas


É importante observar que o UPDATE() função meramente indica se um INSERT ou UPDATE tentativa foi feito em uma coluna especificada de uma tabela ou exibição. Ele ainda retornará true se a tentativa não for bem-sucedida.