KB956718 - OPRAVA: Příkaz MERGE nemusí vynutit omezení cizího klíče, pokud příkaz aktualizuje sloupec jedinečného klíče, který není součástí klíče clusteru, a v SQL Server 2008 existuje jeden řádek jako zdroj aktualizace

Platí pro
SQL Server 2008

Chyba #: 50003167 (oprava hotfix SQL)

Další informace o hlavním seznamu buildů, které byly vydány po vydání jazyka SQL, naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

957826 Kde můžete najít další informace o buildech SQL Server 2008 vydaných po SQL Server 2008 a buildech SQL Server 2005 vydaných po SQL Server 2005 Service Pack 2

Příznaky

V systému Microsoft SQL Server 2008 nemusí být omezení cizího klíče vynuceno při splnění následujících podmínek:

  • Je vydán příkaz MERGE.
  • Cílový sloupec aktualizace má neclusterovaný jedinečný index.

Podívejte se na tento scénář: Příkaz aktualizuje jedinečný sloupec s názvem Sloupec1 tabulky s názvem Tabulka1. Na Tabulku1 odkazuje omezení cizího klíče z tabulky s názvem Tabulka2.

Výsledkem je, že řádky v Tabulce1 se změní, i když by k tomu neměly. Tabulka2 bude navíc obsahovat řádky, které mají nadbytečné odkazy na tabulku1.

K tomuto problému dochází v tomto scénáři v případě, že jsou splněny následující podmínky:

  • Odkazovaný sloupec Sloupec1 v Tabulce1 není součástí clusterovacího klíče Tabulky1.

  • Sloupci Sloupec1 lze přiřadit pouze jednu možnou hodnotu. Nastane například jeden z následujících scénářů:

    • Zdrojem sloučení je jeden řádek dat. Zdroj sloučení například pochází z jednoho z následujících příkazů select:

      • select <ConstantValues>
        
      • select <Parameters>
        

      Poznámka: Tento scénář je nejpravděpodobnější.

    • Zdrojem sloučení je ve skutečnosti jeden řádek dat. Zdroj sloučení například pochází z jednoho z následujících příkazů select:

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

        Všimněte si< TableName>.<Optimalizátor dotazů ví, že jde o jedinečnou hodnotu ColumnName>.

      • select top 1 <ColumnName> from <TableName>
        
    • Spojení mezi zdrojem sloučení a cílem sloučení má predikát, který zaručuje, že bude aktualizován jeden řádek.

    • Klauzule update nastaví sloupec Sloupec1 na konstantní hodnotu bez ohledu na zdroj sloučení.

  • U omezení cizího klíče v tabulce 2 není povolená možnost Kaskáda při aktualizaci.

Poznámka: Tuto opravu hotfix doporučujeme použít, pokud používáte příkaz MERGE k aktualizaci sloupců s neclusterovanými jedinečnými indexy, na které odkazují omezení cizího klíče.

Řešení

Oprava tohoto problému byla poprvé vydána v kumulativní aktualizaci 1. Další informace o získání tohoto balíčku kumulativních aktualizací pro SQL Server 2008 naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

956717 Balíček kumulativní aktualizace 1 pro SQL Server 2008

Poznámka: Vzhledem k tomu, že sestavení jsou kumulativní, obsahuje každá nová verze opravy všechny opravy hotfix a všechny opravy zabezpečení, které byly součástí předchozího vydání opravy pro SQL Server 2008. Doporučujeme zvážit použití nejnovější verze opravy, která obsahuje tuto opravu hotfix. Další informace naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

956909 Buildy SQL Server 2008, které byly vydány po vydání SQL Server 2008

Alternativní řešení

Balíček oprav hotfix tento problém odstraňuje. Použijete-li příkaz MERGE ve scénáři popsaném v části "Příznaky" a rozhodnete se opravu hotfix nepoužít, odstraňte tento problém následujícím postupem:

  1. Přepište příkaz MERGE tak, aby hodnoty pro zdroj hromadné korespondence byly v tabulce, dočasné tabulce nebo proměnné tabulky, a ne vložené v dotazu.

  2. Použijte trasovací příznak 8790. Tento příznak sledování přinutí optimalizátor, aby použil druh plánu, který se nazývá plán široké aktualizace. Široké plány aktualizací tento problém nemají. Tento krok s sebou nese rizika výkonu u všech příkazů DML. Proto byste se měli tomuto kroku vyhnout, pokud není možné aplikaci změnit.

Následující skript jazyka Transact-SQL ukazuje jeden ze způsobů, jak změnit skript a vyřešit tak tento problém, pokud nelze použít tuto opravu hotfix.

Máte například skript, který se podobá následujícímu:

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

Změňte skript tak, aby vypadal nějak takto:

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

Stav

Společnost Microsoft potvrdila, že se jedná o problém produktů Microsoft, které jsou uvedeny v sekci Platí pro.

Další informace

Další informace o měněných souborech a o všech předpokladech použití balíčku kumulativní aktualizace obsahujícího opravu hotfix popsaného v tomto článku znalostní báze znalostní báze Microsoft Knowledge Base naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

956717 Balíček kumulativní aktualizace 1 pro SQL Server 2008

Reference

Další informace o seznamu buildů, které jsou dostupné po vydání verze systému SQL Server 2008, naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

956909 Buildy SQL Server 2008, které byly vydány po vydání SQL Server 2008

Další informace o modelu přírůstkové údržby pro SQL Server naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

935897 Tým SQL Server poskytuje k poskytování oprav hotfix pro hlášené problémy model přírůstkové údržby

Další informace o schématu pojmenování aktualizací pro aktualizace serveru SQL Server naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

822499 Nové schéma pojmenovávání balíčků aktualizací softwaru Microsoft SQL Server

Další informace o terminologii aktualizací softwaru naleznete v následujícím článku znalostní báze znalostní báze Microsoft Knowledge Base:

824684 Popis standardní terminologie používané k popisu aktualizací softwaru společnosti Microsoft

Neclusterované indexy v systému SQL Server 2008

Další informace o neclusterovaných indexech v systému SQL Server 2008 naleznete na následujícím webu služby MSDN (web MSDN (Microsoft Developer Network)):

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