SQL Trigger/If-Statement 中的服务器本地化区分大小写比较
SQL Server Localized Case-Sensitivity Comparison in Trigger/If-Statement
我已经为 审计目的创建了一些触发器 将旧的(现有的)字段值与 UPDATE
或 INSERT
上的新字段值进行比较,如果存在更改,它将更改的值插入 [AuditEntry]
table。没有什么神奇或开创性的。触发器运行良好,但有一个例外:当用户仅更改值的 case 时,触发器未检测到任何更改。 (例如:旧值“san francisco”改为新值“San F未检测到 rancisco"。)
注意到这个错误后,我尝试将触发器更改为类似于以下内容以检查是否区分大小写(没有运气):
ALTER TRIGGER [dbo].[gtr_MyTable_Audit]
ON [dbo].[MyTable]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @OldValue NVARCHAR(2000),
@NewValue NVARCHAR(2000);
...
SELECT @NewValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM INSERTED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
SELECT @OldValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM DELETED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
IF (@NewValue != @OldValue)
BEGIN
INSERT INTO [dbo].[AuditEntry] (OldValue, NewValue, ...) VALUES (@OldValue, @NewValue, ...);
END
...
END
添加 COLLATE SQL_Latin1_General_CP1_CS_AS
没有解决问题,所以我显然不明白如何进行比较。
我的问题是:
如何正确比较 IF 语句中的两个值以确保区分大小写? (最好不要更改 database/server-level 处的排序规则?)
注意:正如您可能从字段名称中猜到的那样,[MyTable].[LocalizedName]
中包含的值可能来自任何语言(英语、日语、俄语)等)所以我可疑地尝试使用 SQL_Latin1_General_CP1_CS_AS
可能无论如何都是 'no-no'。
(我在 SO 上看到 some examples,其中 CAST
到 VARBINARY
用于比较,但我不确定这是否是一个合理的方式。)
您可以尝试使用字符串的 ASCII 值,这样
改变触发器 [dbo].[gtr_MyTable_Audit]
在 [dbo].[MyTable]
对于插入,更新
作为
开始
设置无计数;
DECLARE @OldValue NVARCHAR(2000),
@NewValue NVARCHAR(2000);
...
SELECT @NewValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM INSERTED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
SELECT @OldValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM DELETED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
IF (ASCII(@NewValue) != ASCII(@OldValue))
BEGIN
INSERT INTO [dbo].[AuditEntry] (OldValue, NewValue, ...) VALUES (@OldValue, @NewValue, ...);
END
...
结束
由于 's' 的值不同于 'S' 并且 'f' 的值不同于 'F' 两个字符串将具有不同的 ASCII 值并且将插入当字母大小写改变时你想要的行。
请试试这个。在 if 语句中进行整理以进行比较。
DECLARE @Old NVARCHAR(100)
DECLARE @New NVARCHAR(100)
SELECT @Old = Name from Deleted
SELECT @New = Name from Inserted
IF(@New COLLATE Latin1_General_CS_AS != @Old COLLATE Latin1_General_CS_AS)
PRINT 'Not Equal'
ELSE
PRINT 'Equal'
我已经为 审计目的创建了一些触发器 将旧的(现有的)字段值与 UPDATE
或 INSERT
上的新字段值进行比较,如果存在更改,它将更改的值插入 [AuditEntry]
table。没有什么神奇或开创性的。触发器运行良好,但有一个例外:当用户仅更改值的 case 时,触发器未检测到任何更改。 (例如:旧值“san francisco”改为新值“San F未检测到 rancisco"。)
注意到这个错误后,我尝试将触发器更改为类似于以下内容以检查是否区分大小写(没有运气):
ALTER TRIGGER [dbo].[gtr_MyTable_Audit]
ON [dbo].[MyTable]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @OldValue NVARCHAR(2000),
@NewValue NVARCHAR(2000);
...
SELECT @NewValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM INSERTED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
SELECT @OldValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM DELETED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
IF (@NewValue != @OldValue)
BEGIN
INSERT INTO [dbo].[AuditEntry] (OldValue, NewValue, ...) VALUES (@OldValue, @NewValue, ...);
END
...
END
添加 COLLATE SQL_Latin1_General_CP1_CS_AS
没有解决问题,所以我显然不明白如何进行比较。
我的问题是:
如何正确比较 IF 语句中的两个值以确保区分大小写? (最好不要更改 database/server-level 处的排序规则?)
注意:正如您可能从字段名称中猜到的那样,[MyTable].[LocalizedName]
中包含的值可能来自任何语言(英语、日语、俄语)等)所以我可疑地尝试使用 SQL_Latin1_General_CP1_CS_AS
可能无论如何都是 'no-no'。
(我在 SO 上看到 some examples,其中 CAST
到 VARBINARY
用于比较,但我不确定这是否是一个合理的方式。)
您可以尝试使用字符串的 ASCII 值,这样 改变触发器 [dbo].[gtr_MyTable_Audit] 在 [dbo].[MyTable] 对于插入,更新 作为 开始 设置无计数;
DECLARE @OldValue NVARCHAR(2000),
@NewValue NVARCHAR(2000);
...
SELECT @NewValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM INSERTED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
SELECT @OldValue = [LocalizedName] COLLATE SQL_Latin1_General_CP1_CS_AS FROM DELETED; // Added COLLATE SQL_Latin1_General_CP1_CS_AS
IF (ASCII(@NewValue) != ASCII(@OldValue))
BEGIN
INSERT INTO [dbo].[AuditEntry] (OldValue, NewValue, ...) VALUES (@OldValue, @NewValue, ...);
END
...
结束
由于 's' 的值不同于 'S' 并且 'f' 的值不同于 'F' 两个字符串将具有不同的 ASCII 值并且将插入当字母大小写改变时你想要的行。
请试试这个。在 if 语句中进行整理以进行比较。
DECLARE @Old NVARCHAR(100)
DECLARE @New NVARCHAR(100)
SELECT @Old = Name from Deleted
SELECT @New = Name from Inserted
IF(@New COLLATE Latin1_General_CS_AS != @Old COLLATE Latin1_General_CS_AS)
PRINT 'Not Equal'
ELSE
PRINT 'Equal'