[INFO] MS SQL 2008 > SP1 je nutný

PříspěvekNapsal: 28.07.2010 12:07
od jan.havranek
Chyba SQL dotazů na MSSQL 2008 bez Service Packu
Našli jsme závažnou chybu v SQL Serveru 2008 bez nainstalovaného Service Packu 1. Jde o to, že syntakticky zcela korektní SELECT vrací záznamy, které nevyhovují podmínce WHERE. S nainstalovaným Service Packem 1 se problém neprojevuje. Protože nedokážeme identifikovat všechny SQL příkazy, které jsou chybou postiženy, tak jsme se po delším zkoumání a následné debatě ve Vývoji HeO rozhodli, že jako opatření provedeme následující:

Distribuční verze HeO bude vyžadovat nainstalovaný SP1 na SQL2008, jinak se HeO odmítne spustit!

S velkou pravděpodobností jde o tuto chybu ze Znalostní databáze Microsoft:
FIX: A query returns incorrect results if a passthrough predicate is used with a filter in the query plan
http://support.microsoft.com/kb/958214/
"...This issue occurs because both the FILTER operation and the PASSTHRU predicate are treated as an OR operation instead of being treated as an AND operation. This circumvents the FILTER operation and leads to incorrect results..."

Service Pack 1 lze stáhnout zde:
• pro plný SQL Server 2008
http://www.microsoft.com/downloads/details.aspx?familyid=66AB3DBB-BF3E-4F46-9559-CCC6A4F9DC19
• pro SQL Server 2008 Express Edition:
http://www.microsoft.com/downloads/details.aspx?familyid=01AF61E6-2F63-4291-BCAD-FD500F6027FF

Netýká se těchto verzí:
• SQL Server 2005
• SQL Server 2008 R2

Pro informaci:
• v minulosti bylo podobné opatření u MSSQL 7 SP3 a MSSQL 2000 SP2
• SELECT se vyskytuje v modulu Intrastat (ale podobný může být kdekoliv jinde) a vypadá takto:

Kód: Vybrat vše
SELECT IDMonthMsg, @IDDokladuOZ, TabPohybyZbozi.ID,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN N'99500000' ELSE CASE @AktCelSaz WHEN 1 THEN TabKmenZbozi.CelniNomenklatura ELSE kzd.CelniNomenklaturaOld END END,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN '' ELSE CASE @AktCelSaz WHEN 1 THEN TabKmenZbozi.SZ ELSE kzd.SZOld END END,                               
CASE WHEN @DruhDeklarace IN (0,2) THEN CASE WHEN ISNULL(TabDokZboDodatek.ZemeUrceni,'')='' THEN ISNULL(zPrijemce.CelniKod, ISNULL(zMU.CelniKod, ISNULL(zOdberatel.CelniKod,''))) ELSE ISNULL(TabDokZboDodatek.ZemeUrceni,'') END
ELSE CASE WHEN ISNULL(TabDokZboDodatek.ZemeUrceni,'')='' THEN ISNULL(zOdberatel.CelniKod,'') ELSE ISNULL(TabDokZboDodatek.ZemeUrceni,'') END
END,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN '' ELSE CASE WHEN @DruhDeklarace IN (0,2) THEN '' ELSE ISNULL(TabPohybyZbozi.ZemePuvodu,'') END END,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN NULL ELSE ISNULL(pzsd.Region, TabDokZboDodatek.RegionUrceniPuvodu) END,
           TabPohybyZbozi.CCbezDaniValPoS*CASE WHEN @DruhPohybuZbo IN (24,26) THEN kmpz.Kurz1/kmpz.Kurz2/kmpz.JednotkaMeny ELSE kmdz.Kurz1/kmdz.Kurz2/kmdz.JednotkaMeny END,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN NULL ELSE TabPohybyZbozi.Hmotnost END,
/* Celni sazebnik prislusneho roku */
CASE TabDokZboDodatek.ZPZ
WHEN N'MZ' THEN NULL
ELSE CASE @AktCelSaz
  WHEN 1 THEN
    CASE WHEN csAkt.MJIntr IN (N'KGN',N'KGM') THEN TabPohybyZbozi.Hmotnost
         WHEN csAkt.MJIntr=N'---' THEN 0
         ELSE TabPohybyZbozi.Mnozstvi*TabKmenZbozi.PrepMJ_CMJ
    END
  ELSE
    CASE WHEN csOld.MJIntr IN (N'KGN',N'KGM') THEN TabPohybyZbozi.Hmotnost
         WHEN csOld.MJIntr=N'---' THEN 0
         ELSE TabPohybyZbozi.Mnozstvi*TabKmenZbozi.PrepMJ_CMJ
    END
  END
END,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN '' ELSE TabDokZboDodatek.DodaciPodminky END,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN NULL ELSE TabDokZboDodatek.DD END,
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN NULL ELSE TabDokZboDodatek.PovahaTransakce END,
TabDokZboDodatek.ZPZ,
/* Celni sazebnik prislusneho roku */
CASE TabDokZboDodatek.ZPZ WHEN N'MZ' THEN NULL ELSE CASE @AktCelSaz WHEN 1 THEN csAkt.MJIntr ELSE csOld.MJIntr END END,
/* ECIT prislusneho roku */
CASE WHEN ISNULL(TabKmenZbozi.CLOPopisZbozi,'') LIKE '' THEN CASE @AktCelSaz WHEN 1 THEN ecitAkt.ZboziText ELSE ecitOld.ZboziText END ELSE TabKmenZbozi.CLOPopisZbozi END,
@TypIM,TabDokladyZbozi.ParovaciZnak,2
FROM TabDokladyZbozi
LEFT JOIN TabDokZboDodatek ON TabDokladyZbozi.ID=TabDokZboDodatek.IDHlavicky
JOIN TabPohybyZbozi ON TabDokladyZbozi.ID=TabPohybyZbozi.IDDoklad
JOIN TabStavSkladu ON TabStavSkladu.ID=TabPohybyZbozi.IDZboSklad
JOIN TabKmenZbozi ON TabKmenZbozi.ID=TabStavSkladu.IDKmenZbozi
LEFT OUTER JOIN TabKmenZboziDodatek kzd ON kzd.ID=TabKmenZbozi.ID
/* Celni sazebnik prislusneho roku */
LEFT JOIN TabCelSaz    csAkt ON csAkt.CNALL=TabKmenZbozi.CelniNomenklatura AND @AktCelSaz=1
LEFT JOIN TabCelSazOld csOld ON csOld.CNALL=kzd.CelniNomenklaturaOld AND @AktCelSaz=0
LEFT OUTER JOIN #temp_KurzyMeny kmdz ON kmdz.Mena=ISNULL(TabDokladyZbozi.Mena,@HlavniMena)
LEFT OUTER JOIN #temp_KurzyMeny kmpz ON kmpz.Mena=ISNULL(TabPohybyZbozi.Mena,@HlavniMena)
LEFT OUTER JOIN TabCisOrg coOdberatel ON TabDokladyZbozi.CisloOrg=coOdberatel.CisloOrg
LEFT OUTER JOIN TabZeme zOdberatel ON zOdberatel.ISOKod=coOdberatel.IdZeme
LEFT OUTER JOIN TabCisOrg coMU ON TabDokladyZbozi.MistoUrceni=coMU.CisloOrg
LEFT OUTER JOIN TabZeme zMU ON zMU.ISOKod=coMU.IdZeme
LEFT OUTER JOIN TabCisOrg coPrijemce ON TabDokladyZbozi.Prijemce=coPrijemce.CisloOrg
LEFT OUTER JOIN TabZeme zPrijemce ON zPrijemce.ISOKod=coPrijemce.IdZeme
/* ECIT prislusneho roku */
LEFT OUTER JOIN TabClaEcit    ecitAkt ON ecitAkt.Nomenklatura=TabKmenZbozi.CelniNomenklatura AND ISNULL(ecitAkt.DopKod,N'00')=N'00' AND @AktCelSaz=1
LEFT OUTER JOIN TabClaEcitOld ecitOld ON ecitOld.Nomenklatura=kzd.CelniNomenklaturaOld AND ISNULL(ecitOld.DopKod,N'00')=N'00' AND @AktCelSaz=0
LEFT OUTER JOIN TabPohybyZboziSD pzsd ON pzsd.Id=TabPohybyZbozi.Id
WHERE TabDokladyZbozi.ID=@IDDokladuOZ
      AND ((@AktCelSaz=1 AND csAkt.MJIntr<>'') OR (@AktCelSaz=0 AND csOld.MJIntr<>'')) //<-problematické místo