Muitas vezes precisamos validar se uma "coluna x" foi alterado dentro de uma trigger.
No SQL Server, temos duas maneiras de fazer tal validação.
1) A função Update(nome_coluna) retorna um valor boolean se tal coluna for alterada;
2) E a função Columns_Updated() que retorna um varbinary;
1) Para comparar duas colunas de uma tabela sem se independente das outras, o Update resolve bem o problema.
If (Update(col1) And Update(col2)) Print 'Coluna 1 e Coluna 2 foram alteradas.'
2) Agora, se você quiser comparar uma coluna que depende de outras, aí você terá que utilizar o Columns_Updated(). Essa função retorna uma variável onde cada byte representa 8 colunas da sua tabela. Começando da esquerda para a direita, o primeiro byte referencia da 1ª a 8ª coluna. O segundo byte referencia da 9ª a 16ª coluna e assim por diante.
Falando em linguagem binária, temos 8 bits em que cada posição desse bit referencia a 8 colunas da sua tabela.
Exemplo 1: 00000000 (Nenhuma alteração nas colunas)
Exemplo 2: 00000100 (A 3ª coluna foi alterada)
Exemplo 3: 10100000 (A 6ª e 8ª colunas foram alteradas)
Em decimal, temos:
Exemplo 1: 0 (Nenhuma alteração nas colunas)
Exemplo 2: 4 (A 3ª coluna foi alterada)
Exemplo 3: 160 (A 6ª e 8ª colunas foram alteradas)
Bom, chega de falar de teoria e vamos ao código que tudo vai ficar mais simples.
-- Exemplo 1: -- O valor da comparação é feito em decimal e é utilizado uma comparação binária "&" para retonar o valor inteiro da função Columns_Updated() If (Columns_Updated() & 4) = 4 Print 'Somente a terceira coluna foi alterada' -- Exemplo 2: If (Columns_Updated() & 0) = 0 Print 'Não houve alteração na tabela' -- Exemplo 3: If (Columns_Updated() & 160) = 160 Print 'Colunas 6 e 8 foram alteradas'
2a) Mas e se a minha tabela tiver mais de 8 colunas? Bom, aí teremos que ler cada byte separadamente, pois cada byte corresponde somente a 8 colunas como já foi dito anteriormente. Os exemplos abaixo são somente para uma tabela de até 16 colunas
-- Exemplo 1a:
-- O valor da comparação é feito em decimal e é utilizado uma comparação binária "&" para retonar o valor inteiro da função Columns_Updated()
-- O primeiro substring analisa as 8 primeiras colunas (1ª a 8ª) e depois as 8 próximas colunas (9ª a 16ª)
If ((Substring(Columns_Updated(),1,1) & 4) = 4) And
(Substring(Columns_Updated(),2,1) & 1) = 1))
Print 'Colunas 3 e 9'
-- Exemplo 2a:
If ((Substring(Columns_Updated(),1,1) & 160) = 160) And
(Substring(Columns_Updated(),2,1) & 21) = 21))
Print 'Colunas 6, 8, 9, 11 e 13 foram alteradas'
-- Exemplo 3a:
-- ao invés de utilizar um número decimal, é possível fazer o cálculo através da função power(2, pos_coluna-1)
If ((Substring(Columns_Updated(),1,1) & (power(2, 6-1) + power(2, 8-1)) ) = power(2, 6-1) + power(2, 8-1)) And
(Substring(Columns_Updated(),2,1) & power(2, 1-1) + power(2, 3-1) + power(2, 5-1) ) = power(2, 1-1) + power(2, 3-1) + power(2, 5-1)))
Print 'Colunas 6, 8, 9, 11 e 13 foram alteradas'
-- Exemplo 4: OR (para tabelas com até 8 colunas)
-- é possível validar através do "OU" binário "|"
-- valida se somente as colunas 6 ou 8 foram alterados
If (Columns_Updated() | 160) = 160
Print 'Colunas 6 ou 8 foram alteradas'
-- Exemplo 5: XOR (para tabelas com até 8 colunas)
-- é possível validar através do "OU Exclusivo" binário "^"
-- valida se as colunas 6 ou 8 não foram alterados
If (Columns_Updated() ^ 160) = 160
Print 'Colunas 6 ou 8 não foram alteradas'
Fim, ufa :)
0 comentários:
Postar um comentário