Транзакция с уровнем изоляции, зафиксированным для чтения, и ограничениями таблицы
-
06-09-2019 - |
Вопрос
Выполняются ли табличные ограничения в одной и той же транзакции?
У меня есть транзакция с уровнем изоляции Read Committed, которая вставляет некоторые строки в таблицу.Таблица имеет ограничение на нее, которое вызывает функцию, которая, в свою очередь, выбирает некоторые строки из той же таблицы.
Похоже, что функция выполняется, ничего не зная о транзакции, и select в функции возвращает строки в таблице, которые были там до транзакции.
Есть ли обходной путь или я что-то упускаю?Спасибо.
Вот коды для транзакции и ограничения:
insert into Treasury.DariaftPardakhtDarkhastFaktor
(DarkhastFaktor, DariaftPardakht, Mablagh, CodeVazeiat,
ZamaneTakhsiseFaktor, MarkazPakhsh, ShomarehFaktor, User)
values
(@DarkhastFaktor, @DariaftPardakht, @Mablagh, @CodeVazeiat,
@ZamaneTakhsiseFaktor, @MarkazPakhsh, @ShomarehFaktor, @User);
constraint expression (enforce for inserts and updates):
([Treasury].[ufnCheckDarkhastFaktorMablaghConstraint]([DarkhastFaktor])=(1))
ufnCheckDarkhastFaktorMablaghConstraint:
returns bit
as
begin
declare @SumMablagh float
declare @Mablagh float
select @SumMablagh = isnull(sum(Mablagh), 0)
from Treasury.DariaftPardakhtDarkhastFaktor
where DarkhastFaktor= @DarkhastFaktor
select @Mablagh = isnull(MablaghKhalesFaktor, 0)
from Sales.DarkhastFaktor
where DarkhastFaktor= @DarkhastFaktor
if @Mablagh - @SumMablagh < -1
return 0
return 1
end
Решение
Ограничения проверки не применяются для операций удаления, см. http://msdn.microsoft.com/en-us/library/ms188258.aspx
Ограничения ПРОВЕРКИ не проверяются во время выполнения инструкций DELETE.Следовательно, выполнение инструкций DELETE в таблицах с определенными типами проверки ограничения могут привести к неожиданным результатам.
Редактировать - чтобы ответить на ваш вопрос об обходном пути, вы можете использовать триггер удаления для отката, если вызов вашей функции показывает, что инвариант нарушен.
Редактировать # 2 - @reticent, если вы добавляете строки, то функция, вызываемая с помощью ограничения check, на самом деле должна видеть строки.Если бы это было не так, ограничения проверки были бы бесполезны.Вот простой пример, вы обнаружите, что первые 2 вставки завершились успешно, а третья завершилась неудачей, как и ожидалось:
create table t1 (id int)
go
create function t1_validateSingleton ()
returns bit
as
begin
declare @ret bit
set @ret = 1
if exists (
select count(*)
from t1
group by id
having count(*) > 1
)
begin
set @ret = 0
end
return (@ret)
end
go
alter table t1
add constraint t1_singleton
check (dbo.t1_validateSingleton()=1)
go
insert t1 values (1)
insert t1 values (2)
insert t1 values (1)