KB956718 - PATAISYMAS: SULIEJIMO sakinys gali neįgalinti išorinio rakto apribojimo, kai sakinys atnaujina unikalų rakto stulpelį, kuris nėra klasterio rakto dalis, ir yra viena eilutė kaip naujinimo šaltinis „SQL Server“ 2008"

Taikoma
SQL Server 2008

Klaida #: 50003167 (SQL karštoji pataisa)

Norėdami gauti daugiau informacijos apie pagrindinį komponavimo versijų, išleistų po SQL išleidimo, sąrašą, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:

957826 Kur galite rasti daugiau informacijos apie „SQL Server“ 2008" komponavimo versijas, išleistas po 2008 „SQL Server“., ir „SQL Server“ 2005" komponavimo versijas, išleistas po 2005 „SQL Server“ 2 pakeitimų paketo

Požymiai

Naudojant "Microsoft „SQL Server“ 2008", išorinio rakto apribojimas gali būti netaikomas, kai tenkinamos šios sąlygos:

  • Pateikiamas MERGE pareiškimas.
  • Naujinimo paskirties stulpelis turi nesugrupuotą unikalų indeksą.

Apsvarstykite toliau nurodytą scenarijų. Sakinys atnaujina unikalų stulpelį, pavadintą Lentelė1 lentelėje, pavadintoje Lentelė1. Lentelė1 nurodo išorinio rakto apribojimas iš lentelės, pavadintos Lentelė2.

Rezultatas bus tas, kad Lentelės1 eilutės bus pakeistos, kai jų neturėjo būti. Be to, 2lentelėje bus eilučių, kuriose yra kabančių nuorodų į Lentelę1.

Ši problema kyla esant šiam scenarijui, kai atitinkamos toliau išvardytos sąlygos.

  • Nurodomas Stulpelio1 stulpelis, esantis Lentelėje1 , nėra Lentelės1 grupavimo rakto dalis.

  • Stulpeliui 1 galima priskirti tik vieną galimą reikšmę. Pvz., vienas iš šių scenarijų:

    • Suliejimo šaltinis yra viena duomenų eilutė. Pavyzdžiui, suliejimo šaltinis yra iš vieno iš šių select sakinių:

      • select <ConstantValues>
        
      • select <Parameters>
        

      Pastaba: šis scenarijus yra labiausiai tikėtinas.

    • Suliejimo šaltinis iš tikrųjų yra viena duomenų eilutė. Pavyzdžiui, suliejimo šaltinis yra iš vieno iš šių select sakinių:

      • select <ColumnName> from <TableName> where <TableName>.<ColumnName> = 1
        

        Atkreipkite dėmesį į <Lentelės pavadinimas>.<Užklausų optimizavimo priemonė žino, kad "ColumnName> " yra unikali reikšmė.

      • select top 1 <ColumnName> from <TableName>
        
    • Jungtis tarp suliejimo šaltinio ir suliejimo tikslo turi taisyklės sąlygas, garantuojančias, kad bus atnaujinta viena eilutė.

    • Sąlyga update nustato stulpelio Column1 konstantą reikšmę, neatsižvelgiant į suliejimo šaltinį.

  • Parinktis Naujinant pakopomis neįgalinta dėl išorinio rakto apribojimo, esančio 2 lentelėje.

Pastaba: Rekomenduojame taikyti šią karštąją pataisą, jei naudojate sakinį MERGE, norėdami atnaujinti stulpelius, kuriuose yra neklasterinių unikalių indeksų, kuriuos nurodo išorinio rakto apribojimai.

Sprendimas

Šios problemos pataisa pirmą kartą buvo išleista 1 kaupiamajame naujinime. Norėdami gauti daugiau informacijos apie tai, kaip gauti šį "„SQL Server“ 2008" kaupiamųjų naujinimų paketą, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:

956717 1 kaupiamasis naujinimų paketas, skirtas "„SQL Server“ 2008"

Pastaba Kadangi komponavimo versijos yra kaupiamosios, kiekvienoje naujoje pataisoje yra visos karštosios pataisos ir visos saugos pataisos, kurios buvo įtrauktos į ankstesnį "„SQL Server“ 2008" 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į:

956909 „SQL Server“ 2008" komponavimo versijos, išleistos po 2008 „SQL Server“ išleidimo

Sprendimo būdas

Karštųjų pataisų paketas pašalina problemą. Jei naudojate sakinį MERGE scenarijuje, aprašytame skyriuje "Požymiai", ir jei pasirenkate netaikyti karštosios pataisos, atlikite šiuos veiksmus, kad pašalintumėte šią problemą:

  1. Perrašykite sakinį MERGE, kad suliejimo šaltinio reikšmės būtų lentelėje, laikinojoje lentelėje arba lentelės kintamajame, o ne užklausoje.

  2. Naudokite sekimo vėliavėlę 8790. Ši sekimo vėliavėlė priverčia optimizatorių naudoti tam tikrą planą, kuris vadinamas plataus naujinimo planu. Plataus naujinimo planai problemos neturi. Šis veiksmas kelia visų DML patvirtinimų veikimo riziką. Todėl turėtumėte vengti naudoti šį veiksmą, nebent neįmanoma pakeisti programos.

Šis Transact-SQL scenarijus rodo vieną būdą pakeisti scenarijų šiai problemai išspręsti, jei negalite taikyti šios karštosios pataisos.

Pavyzdžiui, turite scenarijų, panašų į šį:

use tempdb;

drop table sale, product;
create table product(pno int not null primary key, name char(30), pAlternateKey char(6) not null unique);
create table sale(sno int not null primary key, pAlternateKey char(6) not null references product(pAlternateKey));
insert product values(1, 'Office Chair', 'ochair');
insert sale values(1, 'ochair')

-- No violation of foreign key constraint is detected. However, one should be.
merge into product
using (select 'Office Chair2' as name, 1 as pno, 'oxx' as pAlternateKey) as src
on product.pno = src.pno
when matched then
   update set product.pAlternateKey = src.pAlternateKey, 
              product.name = src.name
when not matched then
   insert values(src.pno, src.name, src.pAlternateKey);

Pakeiskite scenarijų taip, kad jis būtų panašus į šį:

insert product values(1, 'Office Chair', 'ochair');
insert sale values(1, 'ochair')
-- A foreign key constraint violation is detected, and the update fails.
declare @source table 
   (name nchar(30), pno int, pAlternateKey nchar(30));
insert into @source values('Office Chair2',1,'oxx');

merge into product
using @source as src
on product.pno = src.pno
when matched then
   update set product.pAlternateKey = src.pAlternateKey, 
              product.name = src.name
when not matched then
   insert values(src.pno, src.name, src.pAlternateKey);

Būsena

„„Microsoft““ patvirtino, kad tai yra „„Microsoft““ produktų, išvardytų dalyje „Taikoma“, problema.

Daugiau informacijos

Norėdami gauti daugiau informacijos apie tai, kokie failai yra keičiami, ir apie visas būtinąsias sąlygas, taikomas kaupiamojo naujinimo paketui, kuriame yra karštosios pataisos, aprašytos šiame "Microsoft" žinių bazės straipsnyje, spustelėkite nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:

956717 1 kaupiamasis naujinimų paketas, skirtas "„SQL Server“ 2008"

Nuorodos

Norėdami gauti daugiau informacijos apie komponavimo versijų, pasiekiamų po "„SQL Server“ 2008" išleidimo, sąrašą, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:

956909 „SQL Server“ 2008" komponavimo versijos, išleistos po 2008 „SQL Server“ išleidimo

Norėdami gauti daugiau informacijos apie „SQL Server“ papildomą priežiūros modelį, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:

935897 "„SQL Server“" komanda siūlo papildomą priežiūros modelį, teikiantį karštąsias pataisas, skirtas praneštų problemų karštosioms pataisoms

Norėdami gauti daugiau informacijos apie „SQL Server“ naujinimų pavadinimų suteikimo schemą, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:

822499 Nauja "Microsoft „SQL Server“" programinės įrangos naujinimo paketų pavadinimų suteikimo schema

Jei norite gauti daugiau informacijos apie programinės įrangos naujinimo terminiją, spustelėkite toliau nurodytą straipsnio numerį ir peržiūrėkite "Microsoft" žinių bazės straipsnį:

824684 Standartinių terminų, naudojamų "„Microsoft“" programinės įrangos naujinimams apibūdinti, aprašas

Neklasteriniai indeksai „SQL Server“ 2008

Norėdami gauti daugiau informacijos apie nesugrupuotus indeksus "„SQL Server“ 2008", apsilankykite šioje "Microsoft" kūrėjų tinklo (MSDN) svetainėje:

https://msdn.microsoft.com/library/ms179325(sql.100).aspx