2016-08-08 7 views
9

Hallo I Abfrage haben wie folgt:SQL hinzufügen Filter nur dann, wenn eine Variable nicht null

SELECT route_id [ROUTE_ID] 
    FROM route_master(NOLOCK) 
    WHERE route_ou = 2 
    AND route_query = @l_s_query 
    AND lang_id = 1 

Hier ist die "AND route_query = @l_s_query" Zustand in WHERE-Klausel hinzugefügt werden soll, wenn nur @l_s_query ist nicht leer. Ich möchte nicht IF ELSE Bedingung für @l_s_query schreiben. Gibt es eine Möglichkeit, in WHERE-Klausel selbst direkt zu behandeln. Danke.

+3

Vielleicht '... AND (route_query = @l_s_query OR @l_s_query IS NULL) ...'? – jarlh

+3

fügen Sie dieses 'AND hinzu (@l_s_query IS NULL ODER route_query = @l_s_query)' –

+0

Mögliches Duplikat von [verwenden Sie optionalen Parameter in der WHERE-Klausel] (http://stackoverflow.com/questions/10814893/use-optional-parameter-in- where-clause) –

Antwort

10

Sie können Ihre Anforderung in übersetzen:

SELECT route_id [ROUTE_ID] 
FROM route_master(NOLOCK) 
WHERE route_ou = 2 
AND (@l_s_query is null OR route_query = @l_s_query) 
AND lang_id = 1 
OPTION (RECOMPILE) 

Die OPTION (RECOMPILE) optional ist, aber auf Kosten der zusätzlichen Übersetzungszeit besser Ausführungspläne geben als Dynamic Search Conditions in T‑SQL

in dem kanonischen Artikel zum Thema diskutiert oder

WHERE route_ou = 2 
AND COALESCE(@l_s_query,route_query) = route_query 
AND lang_id = 1 

: mit COALESCE() die OR zu vermeiden Hinweis: Wie @jarlh sagte, wenn route_query Nullable ist, kann dies einige Probleme wegen Null-Vergleich verursachen, so dass Sie die erste Abfrage verwenden möchten.

Eine weitere Möglichkeit ist das zwei separate Abfragen UNION ALL, eine für jeden Zustand mit -

SELECT .. FROM .. 
WHERE @l_s_query IS NULL 
UNION ALL 
SELECT .. FROM .. 
WHERE @l_s_query = route_query 

Auf Bezug auf Leistung, nur die letzte den Index verwenden, glaube ich, die erste der schnellste sein wird

AND ((0 = len(@l_s_query) OR @l_s_query IS NULL OR route_query = @l_s_query) 

ERKLÄRUNGEN:, aber es kann depanding auf die Indizes, Größen der Tabellen ETC ..

+0

Die zweite Abfrage ist etwas anders, wenn es um NULL-Werte in route_query geht. – jarlh

+0

@jarlh Ja .. Ich habe einen Kommentar dazu hinzugefügt :) – sagi

+0

Was ist mit Auswirkungen auf die Leistung? Unterbindet diese Art von Ausdruck nicht die Verwendung von Indizes, oder sind aktuelle Versionen von mssql intelligent genug, um dies zu berücksichtigen? Ich erinnere mich, dass es manchmal notwendig war, zwei Kopien solcher 'SELECT's zu schreiben, eine mit dem Parameter in der WHERE-Klausel und eine ohne, in ein IF eingepackt ... ELSE ... END – dlatikay

0

Sie können mit einem ODER-if-else ändern emulieren tion:

  • AND (...) - die Klammern erforderlich ist, die nicht leer Prüfung nur für dieses Prädikat
  • 0 < len(@l_s_query) anzuwenden - ist ein Weg, nicht-Leere für varchar mich zu bestimmen.
+2

Ihre Abfrage gibt null Ergebnisse zurück, wenn' @ l_s_query' ist 'NULL' oder leer. – xehpuk

+0

"OR" ist der richtige Fallback-Operator. Der Code wurde entsprechend korrigiert. –

+0

Ihre Syntax ist deaktiviert. Sie vermissen einen Operator, denke ich. 'IS EMPTY' scheint jedoch nicht zu existieren. Und wenn '@ l_s_query' nicht leer ist, wird es nicht mit' route_query' abgeglichen. – xehpuk

0
SELECT route_id [ROUTE_ID] 
FROM route_master(NOLOCK) 
WHERE route_ou = 2 
AND (route_query = @l_s_query AND @l_s_query IS NOT NULL) 
AND lang_id = 1 
1

die "AND route_query = @l_s_query" Zustand in WHERE-Klausel sollte nur hinzugefügt werden, wenn @l_s_query nicht leer ist.

WHERE route_ou = 2 
    AND ( (@l_s_query IS NOT NULL AND route_query = @l_s_query) OR 
       @l_s_query IS NULL) 
    AND lang_id = 1 
0

Hier ist eine bessere Art und Weise zu handhaben: mit LEN(ISNULL)... OR:

AND (LEN(ISNULL(@l_s_query,'')) = 0 OR route_query = @l_s_query)