Создание уникального отфильтрованного индекса для таблицы со сложными условиями в SQL Server с использованием триггеров - PullRequest
0 голосов
/ 08 декабря 2018

Пожалуйста, примите во внимание этот код:

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 голосов
/ 08 декабря 2018

На основании документации LIKE оператор не поддерживается.Проверьте эту часть

[comparison] ::=  
    column_name [comparison_op] constant  

[comparison_op] ::=  
    { IS | IS NOT | = | <> | != | > | >= | !> | < | <= | !< }  
0 голосов
/ 08 декабря 2018

В других ответах уже указывалось, что 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

Вместо появления ошибок вы можете создать INSTEADOF триггер.В этом случае триггер будет отвечать за фактическое сохранение данных в таблице.Вы можете решить вставлять все строки, часть строк или ни одну из них, чтобы вызвать ошибку или пропустить дублированные значения и т. Д.

0 голосов
/ 08 декабря 2018

Из документации :

Отфильтрованные индексы определены для одной таблицы и поддерживают только простые операторы сравнения.Если вам нужно выражение фильтра, которое ссылается на несколько таблиц или имеет сложную логику, вы должны создать представление.

...