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

Executar um acionador somente quando determinadas colunas são atualizadas (SQL Server)


SQL Server tem o UPDATE() função que você pode usar em seus gatilhos DML para verificar se uma coluna específica foi atualizada ou não.

Embora esta função aceite apenas uma coluna, não há nada que impeça você de incluir vários UPDATE() cláusulas com AND ou OR para testar várias atualizações de coluna.

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,
    c4 int DEFAULT 0
);

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

Neste caso, o c4 a coluna será incrementada apenas se o c1 ou c2 colunas foram atualizadas. Isso ocorrerá mesmo se apenas uma dessas duas colunas for atualizada (devido a eu usar OR ao contrário de AND ).

Agora vamos testar o gatilho inserindo dados em c1 .
INSERT INTO t1 (c1) 
VALUES (1);

SELECT * FROM t1;

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

Como esperado, c4 também foi atualizado quando c1 foi atualizado.

Isso também se aplica sempre que c2 é atualizada.
UPDATE t1 
SET c2 = c2 + 1
WHERE id = 1;

SELECT * FROM t1;

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

E, claro, também se aplicaria quando ambos fossem atualizados.

No entanto, não aplicar se atualizarmos c3 (mas não c1 ou c2 ).
UPDATE t1 
SET c3 = c3 + 1
WHERE id = 1;

SELECT * FROM t1;

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

Exigindo que ambas as colunas sejam atualizadas


Podemos alterar o OR para AND para especificar que o c4 coluna só é atualizada se ambos c1 e c2 estão sendo atualizados.

Vamos alterar nosso gatilho para especificar isso:
ALTER TRIGGER trg_t1
ON t1
AFTER INSERT, UPDATE
AS
IF ( UPDATE(c1) AND UPDATE(c2) )
BEGIN
UPDATE t1
SET c4 = c4 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;

Agora atualize c1 só.
UPDATE t1 
SET c1 = c1 + 1
WHERE id = 1;

SELECT * FROM t1;

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

Então c1 foi atualizado conforme especificado, mas c4 não era.

O mesmo aconteceria se atualizassemos c2 mas não c1 .

Mas agora vamos atualizar os dois c1 e c2 .
UPDATE t1 
SET c1 = c1 + 1, c2 = c2 + 1
WHERE id = 1;

SELECT * FROM t1;

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

Como esperado, desta vez c4 também foi atualizado.

Atualizações com falha


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

A função COLUMNS_UPDATED


Outra maneira de verificar atualizações em várias colunas é usar o COLUMNS_UPDATED função.

Esta função retorna um varbinary padrão de bits que indica as colunas inseridas ou atualizadas de uma tabela ou exibição.

Para obter mais informações, consulte a documentação da Microsoft para COLUMNS_UPDATED .