KB956718 - KORJAUS: YHDISTÄMISLAUSE ei välttämättä pakota viiteavaimen rajoitusta, kun lauseke päivittää yksilöllisen avainsarakkeen, joka ei ole osa klusterointiavainta, ja SQL Server 2008:ssa päivityslähteenä on yksi rivi

Käytetään kohteeseen
SQL Server 2008

Virhe #: 50003167 (SQL-hotfix-korjaus)

Saat lisätietoja SQL:n julkaisemisen jälkeen julkaistujen koontiversioiden pääluettelosta napsauttamalla seuraavaa artikkelin numeroa, jolloin pääset lukemaan artikkelin Microsoft Knowledge Base -tietokanta -tietokannassa:

957826 Lisätietoja SQL Server 2008 -koontiversioista, jotka on julkaistu SQL Server 2008 jälkeen, sekä SQL Server 2005 -koontiversioista, jotka on julkaistu SQL Server 2005 Service Pack 2:n jälkeen

Ongelman ilmenemistapa

Microsoft SQL Server 2008:ssa viiteavainrajoitusta ei ehkä oteta käyttöön, kun seuraavat ehdot täyttyvät:

  • MERGE-lause annetaan.
  • Päivityksen kohdesarakkeella on klusteroimaton yksilöllinen indeksi.

Mieti alla kuvattua tilannetta. Lauseke päivittää Taulukko1-nimisen taulukon yksilöllisen sarakkeen nimeltä Sarake1. Taulukko1:een viitataan viiteavainrajoitteella taulukosta, jonka nimi on Taulukko2.

Tuloksena on, että Taulukko1:n rivit muuttuvat, vaikka niiden ei olisi pitänyt muuttua. Lisäksi Taulukko2:ssa on rivejä, joissa on roikkuvia viittauksia taulukko1:een.

Tämä ongelma ilmenee tässä skenaariossa, kun seuraavat ehdot täyttyvät:

  • Taulukon1 viitattu Sarake1-sarake ei kuulu taulukon1 klusterointiavaimeen.

  • Sarake1-sarakkeeseen voi määrittää vain yhden mahdollisen arvon. Esimerkiksi jokin seuraavista skenaarioista tapahtuu:

    • Yhdistämislähde on yksittäinen tietorivi. Yhdistämislähde on esimerkiksi jostakin seuraavista SELECT-lausekkeista:

      • select <ConstantValues>
        
      • select <Parameters>
        

      Huomautus: Tämä on todennäköisin skenaario.

    • Yhdistämislähde on itse asiassa yksittäinen tietorivi. Yhdistämislähde on esimerkiksi jostakin seuraavista SELECT-lausekkeista:

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

        Merkitse taulukon nimi> muistiin<.<Kyselyn optimointitoiminto tietää ColumnName-arvon> olevan yksilöllinen arvo.

      • select top 1 <ColumnName> from <TableName>
        
    • Yhdistämislähteen ja yhdistämisen kohteen välisellä liitoksella on predikaatti, joka takaa, että yksittäinen rivi päivitetään.

    • Update-lause asettaa Column1-sarakkeen vakioarvon yhdistämislähteestä riippumatta.

  • On Update Incsade -asetus ei ole käytössä taulukon 2 viiteavainrajoitteessa.

Huomautus Suosittelemme tämän hotfix-korjauksen käyttämistä, jos päivität MERGE-lausekkeella sarakkeita, joissa on ei-klusteroituja yksilöllisiä indeksejä, joihin viitataan viiteavainrajoitteissa.

Ratkaisu

Tämän ongelman korjaus julkaistiin ensin kumulatiivisessa päivityksessä 1. Saat lisätietoja tämän SQL Server 2008:n kumulatiivisen päivityspaketin hankkimisesta napsauttamalla seuraavaa artikkelin numeroa, jolloin pääset lukemaan artikkelin Microsoft Knowledge Base -tietokanta -tietokannassa:

956717 Kumulatiivinen päivityspaketti 1 SQL Server 2008:lle

Huomautus: Koska koontiversiot ovat kumulatiivisia, jokainen uusi korjausversio sisältää kaikki edelliseen SQL Server 2008 -korjausversioon sisältyvät hotfix-korjaukset ja tietoturvakorjaukset. Suosittelemme, että otat käyttöön uusimman korjausversion, joka sisältää tämän hotfix-korjauksen. Lisätietoja saat napsauttamalla seuraavaa Microsoft Knowledge Base -tietokanta -artikkelinumeroa:

956909 SQL Server 2008 -koontiversiot, jotka on julkaistu SQL Server 2008 jälkeen

Vaihtoehtoinen menetelmä

Hotfix-paketti poistaa ongelman. Jos käytät MERGE-lausetta Oireet-osassa kuvatussa skenaariossa etkä halua käyttää hotfix-korjausta, voit korjata ongelman seuraavasti:

  1. Kirjoita MERGE-lause uudelleen niin, että yhdistämislähteen arvot ovat taulukossa, tilapäistaulukossa tai taulukonmuuttujassa sen sijaan, että ne olisivat rivissä kyselyssä.

  2. Käytä jäljitysmerkintää 8790. Tämä seurantamerkintä pakottaa optimoijan käyttämään suunnitelmaa, jota kutsutaan laajaksi päivityssuunnitelmaksi. Wide update -sopimuksissa ei ole tätä ongelmaa. Tähän vaiheeseen liittyy suorituskykyriskejä kaikkien DML-lausekkeiden osalta. Vältä tämän vaiheen käyttöä, ellei sovelluksen muuttaminen ole mahdotonta.

Seuraava Transact-SQL-komentosarja näyttää yhden tavan muuttaa komentosarjaa tämän ongelman ratkaisemiseksi, jos et voi käyttää tätä hotfix-korjausta.

Oletetaan, että sinulla on esimerkiksi seuraavankaltainen komentosarja:

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);

Muuta komentosarjaa seuraavanlaiseen muotoon:

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);

Tila

Microsoft on vahvistanut tämän olevan ongelma niissä Microsoftin tuotteissa, jotka ovat listattuna Koskee seuraavia tuotteita -osiossa.

Lisätietoja

Saat lisätietoja muutetuista tiedostoista ja tässä Microsoft Knowledge Base -tietokanta -artikkelissa kuvatun hotfix-korjauksen sisältävän kumulatiivisen päivityspaketin käyttöönoton edellytyksistä napsauttamalla seuraavaa artikkelin numeroa, jolloin pääset lukemaan artikkelin Microsoft Knowledge Base -tietokanta -tietokannassa:

956717 Kumulatiivinen päivityspaketti 1 SQL Server 2008:lle

Viitteet

Saat lisätietoja SQL Server 2008:n julkaisun jälkeen käytettävissä olevien koontiversioiden luettelosta napsauttamalla seuraavaa artikkelin numeroa, jolloin pääset lukemaan artikkelin Microsoft Knowledge Base -tietokanta -tietokannassa:

956909 SQL Server 2008 -koontiversiot, jotka on julkaistu SQL Server 2008 jälkeen

Saat lisätietoja SQL Server:n lisäävästä ylläpitomallista napsauttamalla seuraavaa artikkelin numeroa, jolloin pääset lukemaan artikkelin Microsoft Knowledge Base -tietokanta -tietokannassa:

935897 SQL Server-tiimi tarjoaa lisäävän ylläpidon mallin, joka toimittaa hotfix-korjauksia ilmoitettuihin ongelmiin

Saat lisätietoja SQL Server -päivitysten nimeämisrakenteesta napsauttamalla seuraavaa artikkelin numeroa, jolloin pääset lukemaan artikkelin Microsoft Knowledge Base -tietokanta -tietokannassa:

822499 Microsoft SQL Server -ohjelmistopäivityspakettien uusi nimeämisrakenne

Saat lisätietoja ohjelmistopäivityksiin liittyvästä terminologiasta napsauttamalla seuraavaa artikkelin numeroa, jolloin pääset lukemaan artikkelin Microsoft Knowledge Base -tietokanta -tietokannassa:

824684 Microsoftin ohjelmistopäivityksiä kuvaavan vakioterminologian kuvaus

Klusteroimattomat indeksit SQL Server 2008:ssa

Lisätietoja ei-klusteroiduista indekseistä SQL Server 2008:ssa on seuraavassa Microsoft Developer Network (MSDN) -sivustossa:

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