Я пытаюсь применить настраиваемую проверку с помощью CHECK + UDF, тем не менее, в моем случае она не работает должным образом, более того, после поиска есть мнение, что такой подход может повлиять на производительность, и он не является надежным.

Есть ли в T-SQL какие-то существующие инструменты для решения моей проблемы?

Вот мой sql:

DROP TABLE IF EXISTS dbo.test_name_uniq;

CREATE TABLE dbo.test_name_uniq (
  name VARCHAR(255),
  state VARCHAR(255)
)

ALTER TABLE dbo.test_name_uniq DROP CONSTRAINT IF EXISTS test_name_uniq_constraint;
DROP FUNCTION IF EXISTS dbo.validate_test_name_uniq;

GO
CREATE FUNCTION dbo.validate_test_name_uniq(@name VARCHAR(255))
  RETURNS BIT
AS
  BEGIN
    DECLARE @unique_name BIT = 0;
    SELECT @unique_name = CASE
                          WHEN COUNT(*) > 0
                            THEN 0
                          ELSE 1
                          END
    FROM dbo.test_name_uniq i
    WHERE i.name = @name AND i.state <> 'Removed';
    RETURN @unique_name;
  END;
GO

ALTER TABLE dbo.test_name_uniq
  WITH NOCHECK ADD CONSTRAINT test_name_uniq_constraint CHECK (dbo.validate_test_name_uniq(name) = 1 );
GO

DELETE FROM dbo.test_name_uniq;

GO
INSERT INTO dbo.test_name_uniq (name, state) VALUES
  ('Test application', 'Active');

Каждый раз, когда я пытаюсь вставить строку, я получаю сообщение об ошибке:

The INSERT statement conflicted with the CHECK constraint "test_name_uniq_constraint". The conflict occurred in database "data_local_test", table "dbo.test_name_uniq", column 'name'.

Заранее спасибо!

1
slesh 1 Мар 2018 в 14:03

1 ответ

Лучший ответ

Вы можете попробовать с помощью УНИКАЛЬНЫЙ ФИЛЬТР ИНДЕКС в столбце name, где state<>'Removed':

CREATE UNIQUE INDEX uix_name
ON dbo.test_name_uniq (name)
WHERE where state<> 'Removed';

Надеюсь, это поможет.

4
Emilio Lucas Ceroleni 13 Апр 2019 в 00:51