Я реализовал проверку диапазона времени в качестве контрольного ограничения, используя функцию в SQL, используя это руководство, почти дословно.
Сначала создайте функцию:
create function dbo.ValidateStatusPeriodInfoTimeRange
(
@btf_id VARCHAR(32),
@start_time BIGINT,
@end_time BIGINT
)
returns bit
as
begin
declare @Valid bit = 1;
if exists( select *
from dbo.StatusPeriodInfoOccurrence o
where o.btf_id = @btf_id
and @start_time <= o.end_time and o.start_time <= @end_time )
set @Valid = 0;
return @Valid;
конец
А затем ограничение, используя функцию:
alter table dbo.StatusPeriodInfoOccurrence with nocheck add constraint
CK_StatusPeriodInfoOccurrence_ValidateTimeRange
check (dbo.ValidateStatusPeriodInfoTimeRange(btf_id, start_time, end_time) = 1);
Когда я пытаюсь вставить элемент в совершенно пустую таблицу, я получаю:
The INSERT statement conflicted with the CHECK constraint
"CK_StatusPeriodInfoOccurrence_ValidateTimeRange". The conflict occurred in
database "D600600TD01_BSM_Surveillance", table "dbo.StatusPeriodInfoOccurrence".
Я попытался выяснить, сделал ли я что-то не так в самой функции, и создал этот запрос, чтобы проверить его возвращаемое значение:
DECLARE @ReturnValue INT
EXEC @ReturnValue = ValidateStatusPeriodInfoTimeRange
@btf_id = 'a596933eff9143bceda5fc5d269827cd',
@start_time = 2432432,
@end_time = 432432423
SELECT @ReturnValue
Но это возвращает 1, как и должно быть.
Я в недоумении, как продолжить отладку этого. Все части вроде работают, а целое нет. Любые идеи о том, как оператор вставки может конфликтовать с ограничением проверки?
Изменить: вот мой оператор вставки для завершения:
INSERT INTO StatusPeriodInfoOccurrence (btf_id, start_time, end_time) VALUES ('a596933eff9143bceda5fc5d269827cd',2432432,432432423);
Существует дополнительный столбец первичного ключа с автоматическим приращением идентификатора.
CHECK
не выполняется, потому что вставленная вами строка нарушает то самое условие, которое она должна проверять — проверка логически происходит после выполнения вставки (но до ее отката). Я думаю, что автор хотел написатьwhere o.btf_id <> @btf_id
, а неwhere o.btf_id = @btf_id
, чтобы избежать именно этого случая. (Это предполагает, чтоbtf_id
сам по себе является ключом, поэтому дубликаты не могут быть вставлены.) - person Jeroen Mostert   schedule 26.03.2018CHECK
должны быть действительными в каждом контексте, и добавлениеSCOPE_IDENTITY
приведет к серьезному нарушению, если строка будет обновлена. Явно передайте идентификатор строки в функцию. - person Jeroen Mostert   schedule 26.03.2018CHECK
происходит после логической вставки строки, поэтому значение уже известно. Вы можете просто определить ограничение какcheck (dbo.ValidateStatusPeriodInfoTimeRange(id, btf_id, start_time, end_time) = 1)
и использовать@id
иid
в функции. - person Jeroen Mostert   schedule 26.03.2018