Dan*_*ger 3 sql-server sql-server-2014
我有一个更新后触发器,它将记录 ID 排队到另一个表中,以便稍后进行进一步处理。它用于inserted
获取要处理的记录的 ID。
如果唯一的更改是某一特定列,我现在想排除排队到该表的某些记录。如果该列之外的任何其他列发生更改,我仍然想将记录排队。
如何确定是否仅更改了一个特定列?
我看过UPDATE(),但似乎我需要列出表格中的所有其他 47 列,这是我想避免的。
COLUMNS_UPDATED如如何使用 COLUMNS_UPDATED 来检查某些列是否已更新?看起来很有希望,但我无法让它发挥作用。我想排除的列的 ColumnID 为 30。根据我的计算,这给了我536,870,912 ( SELECT POWER(2, 30 - 1)
)的整数位掩码。
当我只对列进行 UPDATE 时,我想排除COLUMNS_UPDATED()
返回的0x000000200040。这将给出一个位模式,表明更新了两个完全不同的列。列 ID 为 7 (2^(7-1)=64) 和 22 (2^(22-1)=2,097,152)。
我不确定采用这种方法是否值得。似乎可以轻松比较其他字段的任何更改。
更新: 我已经在插入和删除之间使用 CHECKSUM 比较其他字段。我不想使用这种方法,因为如果将来将其他字段添加到表中,它可能会导致问题。也有可能发生哈希冲突。
受限于其他答案中提到的限制,COLUMNS_UPDATED
可用于检查触发UPDATE
语句是否仅针对一个(或一些)列。
在将更新语句写入仅提及可能更新的列时,这可能很有用。以下脚本演示:
-- A table with an identity key and 48 other integer nullable columns
CREATE TABLE dbo.Test
(
ID integer IDENTITY PRIMARY KEY,
col01 integer NULL, col02 integer NULL, col03 integer NULL, col04 integer NULL,
col05 integer NULL, col06 integer NULL, col07 integer NULL, col08 integer NULL,
col09 integer NULL, col10 integer NULL, col11 integer NULL, col12 integer NULL,
col13 integer NULL, col14 integer NULL, col15 integer NULL, col16 integer NULL,
col17 integer NULL, col18 integer NULL, col19 integer NULL, col20 integer NULL,
col21 integer NULL, col22 integer NULL, col23 integer NULL, col24 integer NULL,
col25 integer NULL, col26 integer NULL, col27 integer NULL, col28 integer NULL,
col29 integer NULL, col30 integer NULL, col31 integer NULL, col32 integer NULL,
col33 integer NULL, col34 integer NULL, col35 integer NULL, col36 integer NULL,
col37 integer NULL, col38 integer NULL, col39 integer NULL, col40 integer NULL,
col41 integer NULL, col42 integer NULL, col43 integer NULL, col44 integer NULL,
col45 integer NULL, col46 integer NULL, col47 integer NULL, col48 integer NULL
);
-- A single row of sample data
INSERT dbo.Test
(
col01, col02, col03, col04, col05, col06, col07, col08, col09, col10,
col11, col12, col13, col14, col15, col16, col17, col18, col19, col20,
col21, col22, col23, col24, col25, col26, col27, col28, col29, col30,
col31, col32, col33, col34, col35, col36, col37, col38, col39, col40,
col41, col42, col43, col44, col45, col46, col47, col48
)
VALUES
(
01, 02, 03, 04, 05, 06, 07, 08, 09, 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
);
Run Code Online (Sandbox Code Playgroud)
这里的逻辑是建立在预期的值 COLUMNS_UPDATED
时,仅col30
通过有针对性的UPDATE
,并比较与实际遇到的值。触发器用于COLUMNPROPERTY
查找列的 id 以说明未来可能发生的元数据更改。重复 for 的逻辑col30
可以同时测试其他列。
CREATE TRIGGER Test_AU
ON dbo.Test
AFTER UPDATE
AS
BEGIN
IF @@ROWCOUNT = 0 RETURN;
SET ROWCOUNT 0;
SET NOCOUNT ON;
-- Zero @Mask to the same length as COLUMNS_UPDATED()
DECLARE @Mask varbinary(128) =
SUBSTRING(CONVERT(binary(128), 0x), 1, DATALENGTH(COLUMNS_UPDATED()));
DECLARE
@ColumnID integer, -- metadata ID of the target column
@Byte integer, -- byte of @Mask to change
@Work binary(1); -- working value of the byte to change
-- Find the object ID of the trigger's parent table
DECLARE @OID integer;
SELECT @OID = T.parent_id FROM sys.triggers AS T WHERE T.[object_id] = @@PROCID;
/* Set @Mask bits for column(s) of interest */
-- col30
-- Find byte, bit, and bit value to change
SET @ColumnID = COLUMNPROPERTY(@OID, N'col30', 'ColumnId') - 1;
SET @Byte = 1 + (@ColumnID / 8);
-- Retrieve the right @Mask byte and set the target bit
SET @Work = SUBSTRING(@Mask, @Byte, 1);
SET @Work = @Work | POWER(2, @ColumnID % 8);
SET @Mask = CONVERT(varbinary(128), STUFF(@Mask, @Byte, 1, @Work));
-- Test if the resulting mask matches COLUMNS_UPDATED
-- If not, other columns were updated
IF @Mask != COLUMNS_UPDATED() PRINT 'Other columns updated';
END;
Run Code Online (Sandbox Code Playgroud)
无论这些更新产生的消息,因为只有col30
通过有针对性的UPDATE
:
UPDATE dbo.Test
SET col30 = col30;
UPDATE dbo.Test
SET col30 = 1;
Run Code Online (Sandbox Code Playgroud)
所有这些语句都会产生“其他列已更新”消息:
UPDATE dbo.Test
SET col30 = col30,
col31 = col31;
UPDATE dbo.Test
SET col30 = 2,
col31 = 3;
UPDATE dbo.Test
SET col31 = 4;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10972 次 |
最近记录: |