Транзакция с ограничением уровня чтения и таблицей - PullRequest
1 голос
/ 27 мая 2009

Табличные ограничения выполняются в одной и той же транзакции?

У меня есть транзакция с уровнем изоляции Read Committed, которая вставляет несколько строк в таблицу. Таблица имеет ограничение, вызывающее функцию, которая, в свою очередь, выбирает несколько строк из одной таблицы.

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

Есть ли обходной путь или я что-то упустил? Спасибо.

Вот коды для транзакции и ограничения:

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

1 Ответ

3 голосов
/ 27 мая 2009

Проверьте, что ограничения не применяются для операций удаления, см. http://msdn.microsoft.com/en-us/library/ms188258.aspx

Ограничения CHECK не проверены во время УДАЛИТЬ заявления. Следовательно, выполнение операторов DELETE для таблиц с определенными типами чеков ограничения могут привести к неожиданным Результаты.

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

Edit # 2 - @reticent, если вы добавляете строки, то функция, вызываемая проверочным ограничением, должна фактически видеть строки. Если этого не произойдет, проверить ограничения будет бесполезно. Вот простой пример, вы обнаружите, что первые 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)
...