Можно ли реализовать специфичные для строки проверочные ограничения? - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть таблица, в которой каждая строка представляет пару ключ-значение, содержащую параметры, относящиеся к конкретному приложению (например, количество дней для хранения предупреждений и т. Д.).Каждая из этих пар ключ-значение имеет различный диапазон допустимых значений, поэтому ни одно проверочное ограничение не будет одинаково применяться ко всем строкам.Некоторые строки могут вообще не нуждаться в проверке, а другие могут иметь строковые значения, требующие особого рассмотрения.Есть ли какой-нибудь способ, которым я могу создать проверочное ограничение для каждой строки и применить это ограничение при обновлении этой строки?

Я пытался добиться этого несколько раз, но каждый раз сталкивался с препятствиями.Каждая попытка основывается на существовании столбца [Проверка] в таблице, где для этой строки определено ограничение, аналогичное обычному основанному на таблице ограничению (например, «((CAST Value AS INTEGER) <= 60)»). </p>

Моей первой попыткой было создание обычного проверочного ограничения, которое вызывает определяемую пользователем функцию, которая считывает содержимое столбца [Проверка] (на основе значения идентификатора), выполняет проверку ограничения ивозвращает результат true / false в зависимости от того, нарушено ли ограничение.Проблема этого подхода заключается в том, что он требует написания динамического SQL для получения содержимого столбца [Check], а также выполнения кода, который он содержит.Но, конечно, динамический SQL не разрешен в функции.

Затем я попытался изменить функцию на хранимую процедуру, но не представляется возможным вызвать хранимую процедуру с помощью проверочного ограничения.

Наконец, я попытался создать функцию И хранимую процедуру и вызвать хранимую процедуру из функции, но это тоже недопустимо.

Единственный способ, которым я знаю, что это сработает, - это написатьогромное монолитное проверочное ограничение, содержащее проверки для каждой строки по значению идентичности, все OR объединены, например:

(ID = 1 AND (CAST Value AS INTEGER) <= 100) OR (ID =2 И значение IN («да», «нет»)) ИЛИ ... </p>

Но это кошмар, связанный с ошибками.Кто-нибудь знает способ выполнить то, что я хочу, не прибегая к монолитному проверочному ограничению?

По запросу рассмотрим следующее определение таблицы и несколько примеров строк:

CREATE TABLE [dbo].[GenericSetting]
(
  [ID] [INT] IDENTITY(1,1) NOT NULL,
  [Name] [NVARCHAR](50) NOT NULL,
  [Value] [NVARCHAR](MAX) NULL,
  [Check] [NVARCHAR](MAX) NULL,
  CONSTRAINT [PK_GenericSetting] PRIMARY KEY CLUSTERED ([ID])
)

INSERT INTO [dbo].[GenericSetting] ([Name],[Value],[Check]) VALUES ('AlertRetentionDays', 60, 'CAST(Value AS INTEGER) <= 60');
INSERT INTO [dbo].[GenericSetting] ([Name],[Value],[Check]) VALUES ('ExampleMode', 60, 'CAST(Value AS INTEGER) IN (1,2,5)');

Ответы [ 4 ]

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

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

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

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

Вы бы написали такие проверочные ограничения, используя условную логику.В целях безопасности это фактически тот случай, когда я бы использовал case для логической логики:

alter table eav add constraint chk_eav_value
    check (case when attribute = 'amount'
                then (case when try_convert(int, value) >= 0 then 'ok' else 'bad' end)
                when attribute = 'us_zip'
                then (case when value like '[0-9][0-9][0-9][0-9][0-9]' then 'ok' else 'bad' end)
                when attribute like 'city'
                then (case when value not like '%[a-zA-Z ']%' then 'ok' else 'bad'
                else 'ok'
            end) = 'ok');
0 голосов
/ 09 декабря 2018

Проверьте, что ограничения на самом деле не предназначены для этого ... лучше всего вы бы сделали

  • триггер проверки таблицы, который отстой, или

  • реализовать все ваши записи как сами хранимые процедуры и отключить INS / UPD для таблицы в противном случае.Это также отстой.

С риском для того, чтобы быть стереотипом SO, кажется, что вы помещаете бизнес-логику в слой db ... ограничения проверки хороши для статических проверок, но ониWerent действительно предназначен для гораздо большего.Я хотел бы предложить поиск решений для upsteam (уровня DA или общего уровня вашей кодовой базы).

Да, я немного ушел оттуда.Извините заранее.

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

Вам нужно создать триггер для этой таблицы, чтобы выполнить эту задачу.

...