使用触发器在SQL Server中具有复杂条件的表上创建唯一的筛选索引

时间:2018-12-08 08:41:08

标签: sql-server triggers sql-server-2014 sql-server-2016 filtered-index

请考虑以下代码:

CREATE UNIQUE NONCLUSTERED INDEX [idx1] 
ON dbo.Table1 ([Year] ASC,
               [City] ASC,
               [Region] ASC,
               [Sequence] ASC)
WHERE [Region] IN (1, 20) 
  AND [City] NOT LIKE N'C_341%'
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

问题是,似乎无法创建具有复杂条件的过滤索引。我得到这个错误:

  

关键字“ LIKE”附近的语法不正确

是否可以在SQL Server中的那些列上创建唯一性(例如,使用TRIGGER

谢谢

3 个答案:

答案 0 :(得分:1)

来自documentation

  

已过滤的索引在一张表上定义,仅支持简单的比较运算符。如果需要引用多个表或具有复杂逻辑的过滤器表达式,则应创建一个视图。

答案 1 :(得分:1)

不支持基于documentation LIKE运算符。检查这部分

[comparison] ::=  
    column_name [comparison_op] constant  

[comparison_op] ::=  
    { IS | IS NOT | = | <> | != | > | >= | !> | < | <= | !< }  

答案 2 :(得分:1)

其他答案已经指出,过滤索引中不支持LIKE。因此,我将重点介绍强制唯一性的替代方法。是的,您可以使用触发器来执行此操作。您需要在插入后和更新后定义触发器。在其中,您必须检查表的内容,请记住,用此语句插入的行(它们可以是多个)已经存在。如果检测到重复的值,则会回滚事务并引发错误。触发器的代码可能如下所示(假设ID是您的主键字段,这将使我们能够识别新插入的记录):

CREATE TRIGGER [FORCE_UNIQUENESS] on [dbo].[Table1]
INSTEAD OF INSERT, UPDATE
AS
BEGIN
    if exists(select *
        from dbo.Table1 t
        inner join inserted i on
            i.[Year] = t.[Year] and 
            i.[City] = t.[City] and 
            i.[Region] = t.[Region] and 
            i.[Sequance] = t.[Sequance] and 
            t.ID <> i.ID
        where i.Region in (1, 20) and i.[City] NOT LIKE N'C_341%')
    begin
        ROLLBACK TRANSACTION
        RAISERROR('Duplicated values detected', 16, 1);
    end
END

您可以创建INSTEAD OF触发器,而不是引发错误。在这种情况下,触发器将负责实际将数据保存在表中。您可以决定插入所有行,部分行或不插入任何行,以引发错误或静默跳过重复的值,等等。