Rozwiązywanie problemów dotyczących błędów i ostrzeżeń na wyrażenia kwerendy

Czasami SQL Server 2008 ocenia wyrażenia w kwerendach sooner niż SQL Server 2000.Takie zachowanie ma następujące zalety ważne:

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

  • Nadmiarowe obliczeń wyniki wyrażenie jest zabronione.

Jednakże, w zależności od charakteru kwerendy i dane w bazie danych, uruchom -czas wyjątków może wystąpić w SQL Server 2008 , jeśli kwerenda ma istniejącego wyrażenie niebezpieczne.Uruchom te -czas następujące wyjątki:

  • Arytmetyczne wyjątki: dzielenie zero, przepełnienie i niedopełnienie.

  • Błędy konwersji takich jak utratę precyzji i próba przekonwertować ciąg znaków nienumerycznych na liczbę.

  • Agregacja nad 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 używa określonych danych.Jednakże planu kwerend, który zostanie zmieniony z powodu zmiany statystyki potencjalnie może spowodować wyjątek w SQL Server 2008.Można uniemożliwić uruchamianie tych -czas wyjątki przez zmodyfikowanie kwerendy zawierają wyrażenia warunkowe, takich jak NULLIF lub w przypadku.

Ważna informacjaWażne:

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ą stosowane zawsze przed kolumny wyników są obliczane.

W poniższym przykładzie wyrażenie x/y na liście wybierz mogą być oceniane w dowolnym czas, nawet dla wierszy, które ostatecznie nie kwalifikują się jako wyjście dla 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, gdy wyrażenie jest sprawdzane dla y=0.

Poniższy kod jest rozwiązanie, które pozwala poprawnego 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 zwraca wartość dla y.Wyrażenie x/NULL daje NULL i występuje nie wyjątku.

Rozważmy następujący przykład, który polega na konwertowaniu danych znakowych typów liczbowych.

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

Kwerenda nie z błędem konwersji, gdy próbuje przekonwertować ciąg kwerendy 'unknown' do tinyint.Jednym ze sposobów rozwiązania tego problemu jest zmodyfikowanie kwerendy do wykonania konwersji tylko wtedy, gdy z jest numeric, wprowadzając CASE instrukcja, takich 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)

Drugim rozwiązaniem jest nie zrezygnują przy użyciu wartości ciąg specjalne 'unknown' bazy danych i użyj NULL zamiast.Trzeci rozwiązaniem jest zmiana typu z kolumna do tinyint całkowicie uniknąć konwersji.Ponieważ rozwiązania takie wymagają zmiany danych i schematu, odpowiednio, stosowanie tych rozwiązań może obejmować więcej pracy niż modyfikowanie kwerendy.Możesz jednak rozważyć tych rozwiązań, jeśli również ułatwiają innych kwerend zapisu.

NULL ostrzeżenie wprowadzania wydane przez funkcje agregujące

Ostrzeżenie wydawania funkcji agregujących, takich jak MIN, że wartość null została wyeliminowana, jeśli ich wprowadzania zawiera wartość NULL.Ostrzeżenie to może być zależny od planu.Jeśli nie chcesz wejść NULL do wartość zagregowana do przetworzenia i nie chcesz, aby ostrzeżenie wydane, można zmodyfikować kwerendę lokalnie w celu wyeliminowania wartości null.Należy rozważyć 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, należy zmienić kwerendę, dodając warunek 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

Zobacz także

Inne zasoby