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