Fórum Dúvida - Validar se campo foi alterado na TRIGGER dinamicamente. #610585

11/05/2020

0

Olá, senhores, boa tarde!

Tenho uma tabela (Tabela_B) que listo os campos que devem ser considerados no momento de realizar alteração em uma outra tabela (Tabela_A):

Exemplo: Tabela A (Id, Nome, Descrição, telefone, email)
Tabela B (Nome, Descrição)

Ou seja, apesar da tabela A, onde preciso criar a trigger ter todos os campos acima, só vou executar uma determinada rotina, se forem alterados os valores dos campos presentes na tabela B.

Até aí, tudo bem, com essa quantidade de campos, dá pra fazer a verificação campo a campo.

Porém, são vários campos, o que torna a validação manual inviável, neste caso como poderia fazer isso dinâmico, obter os campos que foram alterados?

Exemplo, estou usando SQL Server:


CREATE TRIGGER TRG_Tabela_A_CONTROLE
ON Tabela_A
AFTER DELETE,UPDATE
AS
BEGIN

DECLARE @FDC_CAMPO VARCHAR(80), @LINHA INT, @ETA_COD VARCHAR(10)



IF EXISTS (SELECT 1 FROM inserted) AND EXISTS (SELECT 1 FROM Deleted) -- UPDATE
BEGIN

DECLARE CS_TESTE CURSOR FOR
Select
FDC_CAMPO, Row_Number() Over (Order By FDT_TABELA) LINHA, ETA_COD
From
Tabela_B

OPEN CS_TESTE

FETCH NEXT FROM CS_TESTE INTO @FDC_CAMPO, @LINHA, @ETA_COD

WHILE @@FETCH_STATUS = 0
BEGIN

IF UPDATE(@FDC_CAMPO) /*AQUI SÓ ACEITA O CAMPO DA TABELA, NÃO ACEITA VARIÁVEL*/
BEGIN

/*AÇÃO A SER REALIZADA*/
END

FETCH NEXT FROM CS_TESTE INTO @FDC_CAMPO, @LINHA, @ETA_COD
END

CLOSE CS_TESTE
DEALLOCATE CS_TESTE

END

END
Jose Carvalho

Jose Carvalho

Responder

Posts

11/05/2020

Emerson Nascimento

tente isto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
CREATE OR ALTER TRIGGER TRG_Tabela_A_CONTROLE
ON Tabela_A
AFTER DELETE,UPDATE
AS
BEGIN
    DECLARE @FDC_CAMPO VARCHAR(80);
    DECLARE @ID_COLUNA INT;
    DECLARE @PW_COLUNA INT;
    DECLARE @BYTE_COLUNA INT;
 
    IF EXISTS (SELECT 1 FROM inserted) AND EXISTS (SELECT 1 FROM Deleted) -- UPDATE
    BEGIN
 
        DECLARE CS_TESTE CURSOR
        FOR Select
                LTRIM(RTRIM(FDC_CAMPO))
            From
                Tabela_B
            Where
                FDC_TABELA = 'Tabela_A';
 
        OPEN CS_TESTE;
 
        FETCH NEXT FROM CS_TESTE
        INTO @FDC_CAMPO;
 
        WHILE @@FETCH_STATUS = 0
        BEGIN
            SELECT
                @ID_COLUNA = COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME),
                COLUMN_NAME, 'ColumnID')
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_NAME = 'Tabela_A' AND COLUMN_NAME = @FDC_CAMPO;
 
            -- é necessário encontar o byte correto para a função COLUMNS_UPDATED()
            SET @BYTE_COLUNA = (@ID_COLUNA / 8);
            SET @ID_COLUNA = (@ID_COLUNA - (8 * @BYTE_COLUNA));
            SET @PW_COLUNA = POWER(2, (@ID_COLUNA-1));
 
            IF ((SUBSTRING(COLUMNS_UPDATED(), (@BYTE_COLUNA+1), 1) & @PW_COLUNA) = @PW_COLUNA)
            BEGIN
                /*AÇÃO A SER REALIZADA*/
                PRINT 'campo ' + @FDC_CAMPO + ' alterado.'
            END
 
            FETCH NEXT FROM CS_TESTE
            INTO @FDC_CAMPO;
        END
 
        CLOSE CS_TESTE;
        DEALLOCATE CS_TESTE;
 
    END
 
END
Responder

Gostei + 0

11/05/2020

Emerson Nascimento

talvez assim seja melhor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
CREATE OR ALTER TRIGGER TRG_Tabela_A_CONTROLE
ON Tabela_A
AFTER DELETE,UPDATE
AS
BEGIN
    DECLARE @FDC_CAMPO VARCHAR(80);
    DECLARE @ID_COLUNA INT;
    DECLARE @PW_COLUNA INT;
    DECLARE @BYTE_COLUNA INT;
 
    IF EXISTS (SELECT 1 FROM inserted) AND EXISTS (SELECT 1 FROM Deleted) -- UPDATE
    BEGIN
        DECLARE CS_TESTE CURSOR
        FOR SELECT
                RTRIM(LTRIM(COLUMN_NAME)),
                COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), 
                COLUMN_NAME, 'ColumnID')
            FROM INFORMATION_SCHEMA.COLUMNS 
            WHERE TABLE_NAME = 'Tabela_A'
                AND COLUMN_NAME IN (SELECT LTRIM(RTRIM(FDC_CAMPO)) FROM Tabela_B WHERE FDC_TABELA = 'Tabela_A')
 
        OPEN CS_TESTE;
 
        FETCH NEXT FROM CS_TESTE
        INTO @FDC_CAMPO, @ID_COLUNA;
 
        WHILE @@FETCH_STATUS = 0
        BEGIN
            -- é necessário encontar o byte correto para a função COLUMNS_UPDATED()
            SET @BYTE_COLUNA = (@ID_COLUNA / 8);
            SET @ID_COLUNA = (@ID_COLUNA - (8 * @BYTE_COLUNA));
            SET @PW_COLUNA = POWER(2, (@ID_COLUNA-1));
 
            IF ((SUBSTRING(COLUMNS_UPDATED(), (@BYTE_COLUNA+1), 1) & @PW_COLUNA) = @PW_COLUNA)
            BEGIN
                /*AÇÃO A SER REALIZADA*/
                PRINT 'campo ' + @FDC_CAMPO + ' alterado.'
            END
 
            FETCH NEXT FROM CS_TESTE
            INTO @FDC_CAMPO, @ID_COLUNA;
        END
 
        CLOSE CS_TESTE;
        DEALLOCATE CS_TESTE;
 
    END
 
END

Responder

Gostei + 0

12/05/2020

Jose Carvalho

Emerson, boa tarde!

Agradeço pelo retorno, mas neste caso mesmo não tendo alterado o valor do campo, ou sem ter alterado um campo que está na tabela B, ele executa a ação a ser realizada.

Exemplo: ao executar UPDATE TABELA_A SET TELEFONE = ''7199999999'' WHERE CHAVE = 1

ele executa a ação "PRINT ''campo '' + @FDC_CAMPO + '' alterado.''", mesmo não tendo este campo na tabela_B e o campo já está esse no banco.

talvez assim seja melhor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
CREATE OR ALTER TRIGGER TRG_Tabela_A_CONTROLE
ON Tabela_A
AFTER DELETE,UPDATE
AS
BEGIN
    DECLARE @FDC_CAMPO VARCHAR(80);
    DECLARE @ID_COLUNA INT;
    DECLARE @PW_COLUNA INT;
    DECLARE @BYTE_COLUNA INT;
 
    IF EXISTS (SELECT 1 FROM inserted) AND EXISTS (SELECT 1 FROM Deleted) -- UPDATE
    BEGIN
        DECLARE CS_TESTE CURSOR
        FOR SELECT
                RTRIM(LTRIM(COLUMN_NAME)),
                COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + ''.'' + TABLE_NAME), 
                COLUMN_NAME, ''ColumnID'')
            FROM INFORMATION_SCHEMA.COLUMNS 
            WHERE TABLE_NAME = ''Tabela_A''
                AND COLUMN_NAME IN (SELECT LTRIM(RTRIM(FDC_CAMPO)) FROM Tabela_B WHERE FDC_TABELA = ''Tabela_A'')
 
        OPEN CS_TESTE;
 
        FETCH NEXT FROM CS_TESTE
        INTO @FDC_CAMPO, @ID_COLUNA;
 
        WHILE @@FETCH_STATUS = 0
        BEGIN
            -- é necessário encontar o byte correto para a função COLUMNS_UPDATED()
            SET @BYTE_COLUNA = (@ID_COLUNA / 8);
            SET @ID_COLUNA = (@ID_COLUNA - (8 * @BYTE_COLUNA));
            SET @PW_COLUNA = POWER(2, (@ID_COLUNA-1));
 
            IF ((SUBSTRING(COLUMNS_UPDATED(), (@BYTE_COLUNA+1), 1) & @PW_COLUNA) = @PW_COLUNA)
            BEGIN
                /*AÇÃO A SER REALIZADA*/
                PRINT ''campo '' + @FDC_CAMPO + '' alterado.''
            END
 
            FETCH NEXT FROM CS_TESTE
            INTO @FDC_CAMPO, @ID_COLUNA;
        END
 
        CLOSE CS_TESTE;
        DEALLOCATE CS_TESTE;
 
    END
 
END

Ler Mais...

Responder

Gostei + 0

12/05/2020

Emerson Nascimento

ao executar a instrução abaixo, trocando Tabela_A pela tabela pertinente, retorna algum registro:
1
2
3
4
5
6
7
SELECT
    RTRIM(LTRIM(COLUMN_NAME)),
    COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + ''.'' + TABLE_NAME), 
    COLUMN_NAME, ''ColumnID'')
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = ''Tabela_A''
    AND LTRIM(RTRIM(COLUMN_NAME)) IN (SELECT LTRIM(RTRIM(FDC_CAMPO)) FROM Tabela_B WHERE FDC_TABELA = ''Tabela_A'')
Responder

Gostei + 0

13/05/2020

Jose Carvalho

Retorna sim, os campos em comum nas tabelas.

ao executar a instrução abaixo, trocando Tabela_A pela tabela pertinente, retorna algum registro:
1
2
3
4
5
6
7
SELECT
    RTRIM(LTRIM(COLUMN_NAME)),
    COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + ''.'' + TABLE_NAME), 
    COLUMN_NAME, ''ColumnID'')
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = ''Tabela_A''
    AND LTRIM(RTRIM(COLUMN_NAME)) IN (SELECT LTRIM(RTRIM(FDC_CAMPO)) FROM Tabela_B WHERE FDC_TABELA = ''Tabela_A'')
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar