Udostępnij za pośrednictwem


Troubleshooting Errors and Warnings on Query Expressions

Czasami SQL Server 2008 ocenia wyrażenia w kwerendach sooner niż SQL Server 2000. To zachowanie zapewnia następujące istotne korzyści:

  • Indeksy na podstawie kolumn obliczanych można dopasować do wyrażenia w kwerendzie, które są takie same, jak wyrażenie kolumna obliczana.

  • Nie będzie mógł być zbędnych obliczeń wyniki wyrażenie.

Jednak w zależności od rodzaju danych w bazie danych i kwerendy, wyjątki od czas wykonywania może wystąpić w SQL Server 2008 Jeśli kwerenda ma istniejących niebezpieczne wyrażenie. Te wyjątki od czas wykonywania, należą:

  • Operacje arytmetyczne wyjątki: dzielenie zero, przepełnienie i błędu niedopełnienia.

  • Błędy konwersji, takie jak utrata dokładność i podjęto próbę konwersji ciąg nieliczbowe na liczbę.

  • agregacja dla zestaw wartości, które nie są wszystkie gwarantowana niepustych.

W SQL Server 2000, wyjątki te nie mogą występować w określonej aplikacji, która korzysta z określonych danych. Jednak plan kwerend, które uległy zmianie z powodu zmiany statystyki potencjalnie może spowodować wyjątek w SQL Server 2008. Można uniemożliwić uruchomienie tych-czas wyjątki modyfikując kwerendę tak, aby zawierała wyrażeń warunkowych, takich jak NULLIF lub przypadek.

Important noteImportant Note:

Expressions that appear in a search condition, select list, or any other location within a query may be broken down and reorganized into one or more independent expressions.SQL Server may evaluate these independent expressions in any order with respect to each other.Operacje filtrowania, w tym sprzężeń, nie są zawsze stosowane przed kolumn z wynikami są obliczane.

W poniższym przykładzie wyrażenie x/y na liście select może zostać poddane ocenie w dowolnym momencie, nawet dla wierszy, które ostatecznie nie kwalifikują się w danych wyjściowych kwerendy.

USE tempdb
GO
IF OBJECT_ID('T','U') IS NOT NULL
    DROP TABLE T
IF OBJECT_ID('S','U') IS NOT NULL
    DROP TABLE S
GO
CREATE TABLE T(x float, y float, z nvarchar(30))
CREATE TABLE S(a float, b float)
GO
INSERT INTO T VALUES (1, 0, 'unknown')
INSERT INTO T VALUES(1, 2, '10')
GO
INSERT INTO S VALUES (1, 1)
INSERT INTO S VALUES (1, 2)
INSERT INTO S VALUES (1, 3)
INSERT INTO S VALUES (1, 4)
INSERT INTO S VALUES (1, 5)

Następująca kwerenda nie powiedzie się w SQL Server 2008 ale wykończenie SQL Server 2000.

SELECT x/y FROM T INNER JOIN S ON x = a AND y > b
OPTION(HASH JOIN)

Kwerenda nie powiedzie się, ponieważ x/y wyrażenie powoduje błąd dzielenia przez zero, jeśli wyrażenie jest oceniane na y=0.

Następujący kod to rozwiązanie, które umożliwia poprawne wykonać kwerendy:

SELECT x/NULLIF(y,0) FROM T INNER JOIN S ON x = a AND y > b
OPTION(HASH JOIN)

Wyrażenie NULLIF(y,0) Zwraca NULL Jeśli y = 0. W przeciwnym wypadku wyrażenie zwróci wartość y. Wyrażenie x/NULL daje w wyniku NULL i nie wyjątku.

Należy wziąć pod uwagę w poniższym przykładzie, które polega na konwersji danych znakowych typów liczbowych.

SELECT CONVERT(tinyint, z) FROM T INNER JOIN S ON x = a AND y > b
OPTION(HASH JOIN)

Kończy się niepowodzeniem z błędem konwersji podczas próby konwersji ciąg kwerendy 'unknown' Aby tinyint. Jednym ze sposobów rozwiązania tego problemu należy zmodyfikować kwerendę tak, aby wykonać konwersję, tylko wtedy, gdy jest z jest numeric, wprowadzając CASE Oświadczenie takie jak:

SELECT CASE WHEN ISNUMERIC(z) = 1
    THEN CONVERT(tinyint, z) 
    ELSE 0 
END
FROM T INNER JOIN S ON x = a AND y > b
OPTION(HASH JOIN)

Drugie rozwiązanie polega na forgo przy użyciu wartości ciąg znaków specjalnych 'unknown' w bazie danych i użycia NULL w zamian. Trzeci rozwiązaniem jest zmiana typu z kolumnatinyint Aby uniknąć zamiany całkowicie. Ponieważ rozwiązań takich jak te wymagają zmian danych i schematu, odpowiednio, stosując te rozwiązania może obejmować więcej pracy niż modyfikacji kwerendy.Jednak warto wziąć pod uwagę te rozwiązania, jeśli również ułatwiają inne kwerendy zapisu.

Wartość NULL ostrzeżenie wprowadzania został wystawiony przez funkcje agregacja

Ostrzeżenie wydać funkcji agregujących, takich jak MIN, że wartość null zostało usunięte, jeśli ich dane wejściowe zawiera wartość NULL.Ostrzeżenie to może być zależny od planu.Jeśli nie chcesz, aby wejść wartości NULL do agregacja, które mają być przetwarzane i nie chce, aby wystawiony ostrzeżenie, można zmodyfikować kwerendę lokalnie w celu wyeliminowania wartości null.Należy wziąć pod uwagę SELECT Instrukcja w następującym przykładzie:

USE tempdb
GO
IF OBJECT_ID('newtitles','U') IS NOT NULL
....DROP TABLE newtitles 
GO
CREATE TABLE dbo.newtitles 
   (title varchar (80) NULL ,
    pubdate datetime NULL)
GO
INSERT dbo.newtitles VALUES('Title 1', NULL)
INSERT dbo.newtitles VALUES('Title 2', '20050311')
GO
SELECT t.title, t.pubdate, m.min_pubdate
FROM newtitles AS t,
   (SELECT MIN(pubdate) AS min_pubdate 
    FROM newtitles) AS m
WHERE t.pubdate = m.min_pubdate
GO

W SQL Server 2008, to kwerenda tworzy ostrzeżenie. Aby wyłączyć ostrzeżenia, zmienić kwerendę, dodając warunku WHERE pubdate IS NOT NULL Aby odfiltrować wartości null przed agregacja:

SELECT t.title, t.pubdate, m.min_pubdate
FROM newtitles AS t,
   (SELECT MIN(pubdate) AS min_pubdate 
    FROM newtitles
    WHERE pubdate IS NOT NULL) AS m
WHERE t.pubdate = m.min_pubdate
GO

See Also

Other Resources