Partilhar via


COLUMNS_UPDATED (Transact-SQL)

Aplica-se a:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceBase de dados SQL no Microsoft Fabric

Esta função retorna um padrão de bit varbinary indicando as colunas inseridas ou atualizadas de uma tabela ou exibição. Use COLUMNS_UPDATED qualquer lugar dentro do corpo de um Transact-SQL INSERT ou UPDATE gatilho para testar se o gatilho deve executar determinadas ações.

Transact-SQL convenções de sintaxe

Sintaxe

COLUMNS_UPDATED ( )

Tipos de devolução

Varbinary

Observações

COLUMNS_UPDATED UPDATE testa ou INSERT executa ações em várias colunas. Para testar UPDATE ou INSERT tentar em uma coluna, use UPDATE().

COLUMNS_UPDATED Retorna um ou mais bytes ordenados da esquerda para a direita. O bit mais à direita de cada byte é o bit menos significativo. O bit mais à direita do byte mais à esquerda representa a primeira coluna da tabela na tabela, o próximo bit à esquerda representa a segunda coluna e assim por diante. COLUMNS_UPDATED Retorna vários bytes se a tabela na qual o gatilho é criado contiver mais de oito colunas, sendo o byte menos significativo o mais à esquerda. COLUMNS_UPDATED retorna TRUE para todas as colunas em INSERT ações porque as colunas têm valores explícitos ou valores implícitos (NULL) inseridos.

Para testar atualizações ou inserções em colunas específicas, siga a sintaxe com um operador bit a bit e uma máscara de bits inteira das colunas testadas. Por exemplo, digamos que a tabela t1 contém colunas C1, C2, , C3C4, e C5. Para verificar se as colunas C2, C3e C4 todas atualizadas com êxito (com a tabela t1 tendo um UPDATE gatilho), siga a sintaxe com & 14. Para testar se apenas a coluna C2 é atualizada, especifique & 2. Consulte o Exemplo A e o Exemplo B para exemplos reais.

Use COLUMNS_UPDATED em qualquer lugar dentro de um Transact-SQL INSERT ou UPDATE gatilho. Se isso for executado fora de um gatilho, um NULL será retornado.

A ORDINAL_POSITION coluna do INFORMATION_SCHEMA.COLUMNS modo de exibição não é compatível com o padrão de bits das colunas retornadas pelo COLUMNS_UPDATED. Para obter um padrão de bits compatível com COLUMNS_UPDATEDo , consulte a ColumnIDCOLUMNPROPERTY propriedade da função do sistema ao consultar a INFORMATION_SCHEMA.COLUMNS exibição, conforme mostrado no exemplo a seguir.

SELECT TABLE_NAME, COLUMN_NAME,
    COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME),
    COLUMN_NAME, 'ColumnID') AS COLUMN_ID
FROM AdventureWorks2022.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Person';

Se um gatilho se aplicar a uma coluna, o COLUMNS_UPDATED retornará como true ou 1, mesmo que o valor da coluna permaneça inalterado. Isso é por design, e o gatilho deve implementar uma lógica de negócios que determine se a operação de inserção/atualização/exclusão é permitida ou não.

Conjuntos de colunas

Quando um conjunto de colunas é definido em uma tabela, a COLUMNS_UPDATED função se comporta das seguintes maneiras:

  • Ao atualizar explicitamente uma coluna membro do conjunto de colunas, o bit correspondente para essa coluna é definido como 1, e o bit do conjunto de colunas é definido como 1.

  • Ao atualizar explicitamente um conjunto de colunas, o bit do conjunto de colunas é definido como 1, e os bits de todas as colunas esparsas nessa tabela são definidos como 1.

  • Para operações de inserção, todos os bits são definidos como 1.

    Como as alterações em um conjunto de colunas fazem com que os bits de todas as colunas do conjunto de colunas sejam redefinidos para 1, as colunas inalteradas em um conjunto de colunas aparecerão modificadas. Consulte Usar conjuntos de colunas para obter mais informações sobre conjuntos de colunas.

Exemplos

Um. Use COLUMNS_UPDATED para testar as oito primeiras colunas de uma tabela

Este exemplo cria duas tabelas: employeeData e auditEmployeeData. A employeeData tabela contém informações confidenciais da folha de pagamento dos funcionários e os membros do departamento de recursos humanos podem modificá-las. Se o número de segurança social (SSN), o salário anual ou o número da conta bancária de um funcionário mudarem, é gerado e inserido um registo de auditoria na tabela de auditEmployeeData auditoria.

Com a função, podemos testar rapidamente quaisquer alterações feitas em colunas que contenham informações confidenciais dos COLUMNS_UPDATED() funcionários. O uso COLUMNS_UPDATED() dessa maneira funciona apenas ao tentar detetar alterações nas oito primeiras colunas da tabela.

USE AdventureWorks2022;
GO

IF EXISTS (SELECT TABLE_NAME
           FROM INFORMATION_SCHEMA.TABLES
           WHERE TABLE_NAME = 'employeeData')
    DROP TABLE employeeData;

IF EXISTS (SELECT TABLE_NAME
           FROM INFORMATION_SCHEMA.TABLES
           WHERE TABLE_NAME = 'auditEmployeeData')
    DROP TABLE auditEmployeeData;
GO

CREATE TABLE dbo.employeeData
(
    emp_id INT NOT NULL PRIMARY KEY,
    emp_bankAccountNumber CHAR (10) NOT NULL,
    emp_salary INT NOT NULL,
    emp_SSN CHAR (11) NOT NULL,
    emp_lname NCHAR (32) NOT NULL,
    emp_fname NCHAR (32) NOT NULL,
    emp_manager INT NOT NULL
);
GO

CREATE TABLE dbo.auditEmployeeData
(
    audit_log_id UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY,
    audit_log_type CHAR (3) NOT NULL,
    audit_emp_id INT NOT NULL,
    audit_emp_bankAccountNumber CHAR (10) NULL,
    audit_emp_salary INT NULL,
    audit_emp_SSN CHAR (11) NULL,
    audit_user sysname DEFAULT SUSER_SNAME(),
    audit_changed DATETIME DEFAULT GETDATE()
);
GO

CREATE TRIGGER dbo.updEmployeeData
ON dbo.employeeData
AFTER UPDATE AS
/* Check whether columns 2, 3 or 4 have been updated. If any or all
columns 2, 3 or 4 have been changed, create an audit record.
The bitmask is: power(2, (2-1)) + power(2, (3-1)) + power(2, (4-1)) = 14.
This bitmask translates into base_10 as: 2 + 4 + 8 = 14.
To test whether all columns 2, 3, and 4 are updated, use = 14 instead of > 0
(below). */

    IF (COLUMNS_UPDATED() & 14) > 0
    /* Use IF (COLUMNS_UPDATED() & 14) = 14 to see whether all columns 2, 3,
    and 4 are updated. */
    BEGIN
    -- Audit OLD record.
        INSERT INTO dbo.auditEmployeeData (
           audit_log_type,
           audit_emp_id,
           audit_emp_bankAccountNumber,
           audit_emp_salary,
           audit_emp_SSN)
        SELECT 'OLD',
           del.emp_id,
           del.emp_bankAccountNumber,
           del.emp_salary,
           del.emp_SSN
        FROM deleted AS del;
    -- Audit NEW record.
        INSERT INTO dbo.auditEmployeeData (
           audit_log_type,
           audit_emp_id,
           audit_emp_bankAccountNumber,
           audit_emp_salary,
           audit_emp_SSN)
        SELECT 'NEW',
           ins.emp_id,
           ins.emp_bankAccountNumber,
           ins.emp_salary,
           ins.emp_SSN
        FROM inserted AS ins;
    END
GO

/* Inserting a new employee does not cause the UPDATE trigger to fire. */
INSERT INTO employeeData
VALUES (101, 'USA-987-01', 23000, 'R-M53550M', N'Mendel', N'Roland', 32);
GO

/* Updating the employee record for employee number 101 to change the   
salary to 51000 causes the UPDATE trigger to fire and an audit trail to   
be produced. */
UPDATE dbo.employeeData
SET emp_salary = 51000
WHERE emp_id = 101;
GO

SELECT * FROM auditEmployeeData;
GO

/* Updating the employee record for employee number 101 to change both
the bank account number and social security number (SSN) causes the
UPDATE trigger to fire and an audit trail to be produced. */
UPDATE dbo.employeeData
SET emp_bankAccountNumber = '133146A0',
    emp_SSN = 'R-M53550M'
WHERE emp_id = 101;
GO

SELECT * FROM dbo.auditEmployeeData;
GO

B. Use COLUMNS_UPDATED para testar mais de oito colunas

Para testar atualizações que afetam colunas diferentes das oito primeiras colunas da tabela, use a SUBSTRING função para testar o bit correto retornado pelo COLUMNS_UPDATED. Este exemplo testa atualizações que afetam as colunas 3, 5e 9 na AdventureWorks2022.Person.Person tabela.

USE AdventureWorks2022;
GO

IF OBJECT_ID(N'Person.uContact2', N'TR') IS NOT NULL
    DROP TRIGGER Person.uContact2;
GO

CREATE TRIGGER Person.uContact2
    ON Person.Person
    AFTER UPDATE AS
        IF ((SUBSTRING(COLUMNS_UPDATED(), 1, 1) & 20 = 20)
            AND (SUBSTRING(COLUMNS_UPDATED(), 2, 1) & 1 = 1))
            PRINT 'Columns 3, 5 and 9 updated';
GO

UPDATE Person.Person
    SET NameStyle = NameStyle,
        FirstName = FirstName,
        EmailPromotion = EmailPromotion;
GO