Požymiai
Kai naudojate funkcijas SCOPE_IDENTITY() arba @@IDENTITY reikšmėms, įterptoms į tapatybės stulpelį, gauti, galite pastebėti, kad šios funkcijos kartais pateikia neteisingas reikšmes. Problema kyla tik tada, kai užklausos naudoja lygiagrečius vykdymo planus.
Priežastis
"„Microsoft“" patvirtino, kad tai yra šio straipsnio pradžioje išvardytų "„Microsoft“" produktų problema.
Sprendimas
Kaupiamojo naujinimo informacija
„SQL Server“ 2008 R2 1 pakeitimų paketas
Šios problemos pataisa pirmą kartą buvo išleista "„SQL Server“ 2008 R2" 1 pakeitimų paketo 5 kaupiamajame naujinime. Jei norite gauti daugiau informacijos, kaip gauti šį kaupiamąjį naujinimo paketą, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:
2659694 5 kaupiamasis naujinimo paketas, skirtas "„SQL Server“ 2008 R2" 1 pakeitimų paketui
Atkreipkite dėmesį Kadangi komponavimo versijos yra kaupiamosios, kiekvienoje naujoje pataisoje yra visos karštosios pataisos ir visos saugos pataisos, kurios buvo įtrauktos į ankstesnį "„SQL Server“ R2" pataisų leidimą. Rekomenduojame taikyti naujausią pataisos leidimą, kuriame yra ši karštoji pataisa. Norėdami gauti papildomos informacijos, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:
2567616 „SQL Server“ 2008 R2" komponavimo versijos, išleistos po „SQL Server“ 2008 R2 1 pakeitimų paketo išleidimo
Sprendimo būdas
"„Microsoft“" rekomenduoja nenaudoti nei vienos iš šių funkcijų užklausose, kai naudojami lygiagrečiai planai, nes jie ne visada yra patikimi. Vietoj to naudokite sakinio INSERT sąlygą OUTPUT, kad gautumėte tapatybės reikšmę, kaip parodyta toliau pateiktame pavyzdyje.
Sąlygos OUTPUT naudojimo pavyzdys:
DECLARE @MyNewIdentityValues table(myidvalues int)
declare @A table (ID int primary key)
insert into @A values (1)
declare @B table (ID int primary key identity(1,1), B int not null)
insert into @B values (1)
select
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE\_IDENTITY] = SCOPE\_IDENTITY()
set statistics profile on
insert into \_ddr\_T
output inserted.ID into @MyNewIdentityValues
select
b.ID
from @A a
left join @B b on b.ID = 1
left join @B b2 on b2.B = -1
left join \_ddr\_T t on t.T = -1
where not exists (select \* from \_ddr\_T t2 where t2.ID = -1)
set statistics profile off
select
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE\_IDENTITY] = SCOPE\_IDENTITY(),
[IDENT\_CURRENT] = IDENT\_CURRENT('\_ddr\_T')
select \* from @MyNewIdentityValues
go
Jei jūsų situacija reikalauja naudoti kurią nors iš šių funkcijų, galite naudoti vieną iš toliau nurodytų būdų problemai išspręsti.
1 būdas:
Į užklausą įtraukite šią parinktį
OPTION (MAXDOP 1)
Pastaba: tai gali pakenkti jūsų užklausos dalies SELECT našumui.
2 būdas:
Perskaitykite reikšmę iš SELECT dalies į kintamųjų rinkinį (arba vieną lentelės kintamąjį), tada įterpkite į paskirties lentelę naudodami MAXDOP=1. Kadangi INSERT planas nebus lygiagretus, gausite tinkamą semantinę, tačiau jūsų SELECT bus lygiagretus, kad pasiektumėte norimą našumą.
3 metodas:
Vykdykite šį sakinį, kad maksimalaus lygiagretumo laipsnio parinktį nustatytumėte į 1:
sp\_configure 'max degree of parallelism', 1
go
reconfigure with override
go
Pastaba: Šis metodas gali pabloginti serverio našumą. Šio metodo naudoti nereikėtų, nebent jį įvertinote testavimo ar etapų aplinkoje.