KB956718 – ÅTGÄRDAT: En MERGE-instruktion kanske inte tillämpar en sekundärnyckelbegränsning när satsen uppdaterar en unik nyckelkolumn som inte ingår i en klusternyckel och det finns en enskild rad som uppdateringskälla i SQL Server 2008

Gäller för
SQL Server 2008

Bug #: 50003167 (SQL Hotfix)

Om du vill veta mer om huvudlistan över versioner som släpptes efter att SQL släpptes klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:

957826 Här hittar du mer information om SQL Server 2008-versioner som släpptes efter SQL Server 2008 och SQL Server 2005-versioner som släpptes efter SQL Server 2005 Service Pack 2

Symptom

I Microsoft SQL Server 2008 kanske en sekundärnyckelbegränsning inte tillämpas när följande villkor är uppfyllda:

  • En MERGE-instruktion utfärdas.
  • Uppdateringens målkolumn har ett unikt index som inte är grupperat.

Tänk dig följande scenario. Instruktionen uppdaterar en unik kolumn med namnet Kolumn1 i en tabell som heter Tabell1. Tabell1 refereras till av ett sekundärnyckelvillkor från en tabell som heter Tabell2.

Resultatet är att rader i Tabell1 ändras när de inte borde ha ändrats. Dessutom har Tabell2 rader som har dinglande referenser till Tabell1.

Det här problemet uppstår för det här scenariot när följande villkor är sanna:

  • Den refererade Kolumn1-kolumnen i Tabell1 är inte en del av klusternyckeln för Tabell1.

  • Endast ett möjligt värde kan tilldelas kolumnen Kolumn1 . Till exempel inträffar något av följande scenarion:

    • Kopplingskällan är en enda rad med data. Kopplingskällan kommer till exempel från något av följande select-instruktioner:

      • select <ConstantValues>
        
      • select <Parameters>
        

      Obs! Det här scenariot är det troligaste scenariot.

    • Kopplingskällan är egentligen en enda rad med data. Kopplingskällan kommer till exempel från något av följande select-instruktioner:

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

        Notera <tabellnamn>.<ColumnName> är ett unikt värde enligt frågeoptimeraren.

      • select top 1 <ColumnName> from <TableName>
        
    • Kopplingen mellan sammanslagningskällan och sammanslagningsmålet har ett predikat som garanterar att en enskild rad uppdateras.

    • Genom uppdateringssatsen anges ett konstant värde för kolumnen Column1 , oavsett sammanslagningskälla.

  • Alternativet Vid uppdatering av kaskad är inte aktiverat för sekundärnyckelbegränsningen i Tabell2.

Obs! Vi rekommenderar att du använder den här snabbkorrigeringen om du använder kommandot MERGE för att uppdatera kolumner som har unika index som inte är grupperade och som refereras till av sekundärnyckelbegränsningar.

Lösning

Korrigeringen för det här problemet släpptes först i kumulativ uppdatering 1. Om du vill veta mer om hur du hämtar det här kumulativa uppdateringspaketet för SQL Server 2008 klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:

956717 Kumulativt uppdateringspaket 1 för SQL Server 2008

Eftersom versionerna är kumulativa innehåller varje ny korrigeringsversion alla snabbkorrigeringar och alla säkerhetskorrigeringar som ingick i den tidigare SQL Server 2008-korrigeringsversionen. Vi rekommenderar att du installerar den senaste snabbkorrigeringen som innehåller den här snabbkorrigeringen. Mer information om hur du åtgärdar det här problemet får du om du klickar på följande artikelnummer i Microsoft Knowledge Base:

956909 SQL Server 2008-versionerna som släpptes efter att SQL Server 2008 släpptes

Lösning

Snabbkorrigeringspaketet eliminerar problemet. Om du använder MERGE-instruktionen i scenariot som beskrivs i avsnittet "Symptom" och om du väljer att inte använda snabbkorrigeringen följer du dessa steg för att eliminera problemet:

  1. Skriv om MERGE-instruktionen så att värdena för sammanslagningskällan finns i en tabell, tillfällig tabell eller tabellvariabel i stället för att vara infogade i frågan.

  2. Använd spårningsflagga 8790. Den här spårningsflaggan tvingar optimeraren att använda en typ av plan som kallas för en bred uppdateringsplan. Breda uppdateringsplaner har inte problemet. Det här steget medför prestandarisker för alla DML-instruktioner. Därför bör du undvika att använda det här steget såvida det inte är omöjligt att ändra programmet.

Följande Transact-SQL-skript visar ett sätt att ändra skriptet för att lösa problemet om du inte kan använda den här snabbkorrigeringen.

Du har till exempel ett skript som liknar följande:

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

Ändra skriptet så att det liknar följande:

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

Status

Microsoft har bekräftat att detta är ett problem i de Microsoft-produkter som anges i avsnittet "Gäller".

Mer information

Om du vill veta mer om vilka filer som har ändrats och om förutsättningarna för att tillämpa det kumulativa uppdateringspaketet som innehåller snabbkorrigeringen som beskrivs i den här artikeln i Microsoft Knowledge Base klickar du på artikelnumret nedan och läser artikeln i Microsoft Knowledge Base:

956717 Kumulativt uppdateringspaket 1 för SQL Server 2008

Referenser

Om du vill veta mer om listan över versioner som är tillgängliga efter lanseringen av SQL Server 2008 klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:

956909 SQL Server 2008-versionerna som släpptes efter att SQL Server 2008 släpptes

Om du vill veta mer om modellen för inkrementell service för SQL Server klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:

935897 En stegvis servicemodell är tillgänglig från SQL Server-teamet för att leverera snabbkorrigeringar för rapporterade problem

Om du vill veta mer om namnschemat för SQL Server uppdateringar klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:

822499 Nytt namnschema för Microsoft SQL Server programuppdateringspaket

Om du vill veta mer om terminologi för programuppdateringar klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:

824684 Beskrivning av standardterminologin som används för att beskriva Microsofts programuppdateringar

Icke-klustrade index i SQL Server 2008

Mer information om icke-klustrade index i SQL Server 2008 finns på följande MSDN-webbplats (Microsoft Developer Network):

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