触发器/ If语句中的SQL Server本地化大小写敏感度比较

时间:2016-11-01 21:07:48

标签: sql-server triggers localization sql-server-2014 case-sensitive

我为审核目的创建了一些触发器,用于将旧(现有)字段值与UPDATEINSERT上的新字段进行比较,如果存在更改,则会插入将更改的值转换为[AuditEntry]表。没有什么神奇的或开创性的。触发器运行良好,但有一个例外:当用户仅更改值的 case 时,触发器未检测到任何更改。 (例如:旧值“ s f rancisco”已更改为新值“ S 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语句中的两个值以确保区分大小写? (最好不要更改数据库/服务器级别的排序规则?)

注意:正如您可能从字段名称中猜到的那样,[MyTable].[LocalizedName]中包含的值可能来自任何语言(英语,日语,俄语等),因此无论如何,我对使用SQL_Latin1_General_CP1_CS_AS的可疑尝试可能都是'禁忌'。

(我在SO上看过some examples,其中CASTVARBINARY用于比较,但我不确定这是否合理去。)

2 个答案:

答案 0 :(得分:2)

请试试这个。在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'

答案 1 :(得分:0)

您可以尝试使用字符串的ASCII值     ALTER TRIGGER [dbo]。[gtr_MyTable_Audit]    ON [dbo]。[MyTable]    FOR INSERT,UPDATE 如 开始     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 (ASCII(@NewValue) != ASCII(@OldValue))
    BEGIN
        INSERT INTO [dbo].[AuditEntry] (OldValue, NewValue, ...) VALUES (@OldValue, @NewValue, ...);
    END

...

END

因为' s'不同于' S'以及' f'的价值不同于F' F'这两个字符串将具有不同的ASCII值,并会在字母大小写更改时插入所需的行。