Galite gauti neteisingas reikšmes naudodami SCOPE_IDENTITY() ir @@IDENTITY

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.

Daugiau informacijos

"„Microsoft“ Connect" klaida dėl šios problemos

Maksimalus lygiagretumo laipsnis (MAXDOP)