Operazione con Read Committed livello di isolamento e di vincoli di tabella
-
06-09-2019 - |
Domanda
La vincoli di tabella vengono eseguiti nella stessa transazione?
Ho una transazione con livello di isolamento Read Committed che inserisce alcune righe in una tabella. La tabella include un vincolo su di esso che chiama una funzione che a sua volta seleziona alcune righe dalla stessa tabella.
Sembra che la funzione viene eseguito senza sapere nulla della transazione e di selezione nella funzione restituisce righe della tabella che erano lì prima della transazione.
C'è una soluzione o mi sto perdendo qualcosa? Grazie.
Ecco i codici per la transazione e il vincolo:
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
Soluzione
Vedi i vincoli non vengono applicate per le operazioni di eliminazione, vedi http: // msdn .microsoft.com / en-us / library / ms188258.aspx
VEDI vincoli non vengono convalidati durante istruzioni DELETE. Perciò, l'esecuzione di istruzioni DELETE sui tavoli con alcuni tipi di controllo vincoli possono produrre inaspettati risultati.
Modifica - per rispondere alla tua domanda sulla soluzione, è possibile utilizzare un trigger di eliminazione per ripristinare se la chiamata di funzione mostra un invariante è rotto
.Modifica # 2 - @reticent, se si sta aggiungendo le righe allora la funzione chiamata dal vincolo di controllo dovrebbe infatti vedere le righe. Se non lo fa, vincoli di controllo sarebbe inutile. Ecco un semplice esempio, vi accorgerete che i primi 2 inserti successo e il terzo non riesce come previsto:
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)