2017-04-18 3 views
0

Ich habe 3 Variablen in meiner gespeicherten SQL-Prozedur und möchte nur dann einen Join hinzufügen, wenn die dritte Variable nicht null ist.SQL JOIN nur, wenn eine Bedingung wahr ist

Dies ist, wie ich es versuche, aber es funktioniert nicht. Es gibt die folgenden Fehler auf der Linie darauf hingewiesen:

falsche Syntax nahe '{'

ALTER PROCEDURE [dbo].[Search] 
@one NVARCHAR(50), @two NVARCHAR(50), @three NVARCHAR(50) 

SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo 
Inner JOIN dbo.values AS cval 
    ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc 
    ON (cval.sID = sc.sID AND sc.Accept = 'A') 
IF @three IS NOT NULL{    **<---------------------** 
LEFT JOIN dbo.Synonym AS synm 
    ON cinfo.ID = synm.ID} 

where (cinfo.NAM LIKE '%'[email protected]+'%' OR cinfo.CAS LIKE '%'[email protected]+'%' OR 
    synm.SynonymID LIKE '%'[email protected]+'%') AND 
    (cval.PropID = '1' OR 
    cval.PropID = '2' OR 
    cval.PropID = '3' OR 
    cval.PropID = '4' OR) 
+0

Sie können dies in 'TSQL' nicht tun. Allerdings können wir die Abfrage schreiben, um Ergebnisse in beiden Bedingungen zu erhalten –

Antwort

2

Sie müssen diesen Zustand geben, während sie sich selbst beitreten.

ALTER PROCEDURE [dbo].[Search] 
@one NVARCHAR(50), @two NVARCHAR(50), @three NVARCHAR(50) 

SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo 
Inner JOIN dbo.values AS cval 
    ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc 
    ON (cval.sID = sc.sID AND sc.Accept = 'A') 
     LEFT JOIN dbo.Synonym AS synm 
    ON (cinfo.ID = synm.ID and @three is not null) **<---------------------** 

where (cinfo.NAM LIKE '%'[email protected]+'%' OR cinfo.CAS LIKE '%'[email protected]+'%' OR 
    synm.SynonymID LIKE '%'[email protected]+'%') AND 
    (cval.PropID = '1' OR 
    cval.PropID = '2' OR 
    cval.PropID = '3' OR 
    cval.PropID = '4' OR) 
-3
You cannot use { for if condition just remove '{' 

ALTER PROCEDURE [dbo].[Search] 
@one NVARCHAR(50), @two NVARCHAR(50), @three NVARCHAR(50) 

SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo 
Inner JOIN dbo.values AS cval 
    ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc 
    ON (cval.sID = sc.sID AND sc.Accept = 'A') 
**IF @three IS NOT NULL**   Remove this line 
LEFT JOIN dbo.Synonym AS synm 
    ON cinfo.ID = synm.ID} 

where (cinfo.NAM LIKE '%'[email protected]+'%' OR cinfo.CAS LIKE '%'[email protected]+'%' OR 
    synm.SynonymID LIKE '%'[email protected]+'%') AND 
    (cval.PropID = '1' OR 
    cval.PropID = '2' OR 
    cval.PropID = '3' OR 
    cval.PropID = '4' OR) 

Try Wie zu schreiben, wenn @three IS NOT NULL ALTER PROCEDURE [dbo]. [Suche] @ein NVARCHAR (50), @zwei NVARCHAR (50), @drei NVARCHAR (50)

SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo 
Inner JOIN dbo.values AS cval 
    ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc 
    ON (cval.sID = sc.sID AND sc.Accept = 'A') 

where (cinfo.NAM LIKE '%'[email protected]+'%' OR cinfo.CAS LIKE '%'[email protected]+'%' OR 
    synm.SynonymID LIKE '%'[email protected]+'%') AND 
    (cval.PropID = '1' OR 
    cval.PropID = '2' OR 
    cval.PropID = '3' OR 
    cval.PropID = '4' OR) 

Ende sonst ALTER PROCEDURE [dbo]. [Suche] @One NVARCHAR (50), @two NVARCHAR (50), @three NVARCHAR (50)

SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo 
Inner JOIN dbo.values AS cval 
    ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc 
    ON (cval.sID = sc.sID AND sc.Accept = 'A') 
LEFT JOIN dbo.Synonym AS synm 
    ON cinfo.ID = synm.ID} 

where (cinfo.NAM LIKE '%'[email protected]+'%' OR cinfo.CAS LIKE '%'[email protected]+'%' OR 
    synm.SynonymID LIKE '%'[email protected]+'%') AND 
    (cval.PropID = '1' OR 
    cval.PropID = '2' OR 
    cval.PropID = '3' OR 
    cval.PropID = '4' OR).. rest code 

Ende

+0

Funktioniert immer noch nicht. Sagt: Falsche Syntax neben dem Schlüsselwort 'LINKS' für die gleiche Zeile – ilmenite

+0

Die IF-Anweisung wird verwendet, um den Fluss zu steuern, Sie können es nicht einfach in der Mitte einer Abfrage wie dieser werfen. –

+0

Sie können nicht IF-Bedingung in der Mitte der Abfrage schreiben, wie Sie es in der aktuellen Bedingung tun. IF State muss eine Abfrage enthalten. beispielsweise. Wenn Bedingung dann Ihre Aussage – NEO

2

Dies ist nicht die korrekte Syntax, aber Sie könnten dies auf verschiedene Arten erreichen, am einfachsten ist es, die Boolesche Überprüfung oben hinzuzufügen.

IF @three IS NOT NULL 
BEGIN 
--FULL QUERY that JOIN dbo.Synonym 
END 

IF @Three IS NULL 
BEGIN 
--FULL QUERY that does not JOIN dbo.Synonym 
END 

Oder Sie könnten case..when verwenden, um zu steuern, tut es das gleiche wie mehrere if

0

Sie dies durch den Aufbau dynamische Abfrage wie folgt erreichen können

ALTER PROCEDURE [dbo].[Search] 
@one NVARCHAR(50), @two NVARCHAR(50), @three NVARCHAR(50) 

DECLARE @query varchar(2000)=' SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo Inner JOIN dbo.values AS cval ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc ON (cval.sID = sc.sID AND sc.Accept = ''A'')' 

IF @three IS NOT NULL 
BEGIN 
    SET @query = @query + ' LEFT JOIN dbo.Synonym AS synm ON cinfo.ID = synm.ID ' 
END 

SET @query = @query + 'where (cinfo.NAM LIKE ''%' + @one + '%'' OR cinfo.CAS LIKE ''%' + @two + '%'' OR 
    synm.SynonymID LIKE ''%' + @three + '%'') AND 
    (cval.PropID = ''1'' OR 
    cval.PropID = ''2'' OR 
    cval.PropID = ''3'' OR 
    cval.PropID = ''4'')' 

EXEC(@query) 
+0

schreiben. Dies hat diese Prozedur nun der SQL-Injektion zugänglich gemacht. Sie müssen diesen dynamischen SQL-Parameter parametrisieren, wenn dies die Lösung ist. –

+0

Dies ist bereits parametrisiert :) –

+0

NEIN es ist nicht !!! Die Parameter befinden sich in der Prozedur, aber Sie erstellen eine Zeichenfolge und führen sie aus. Dies ist ein sehr häufiges Missverständnis. Aber was passiert, wenn der Wert für eins so etwas wie "'x' '; drop database master; -" ist. Dieser Code hat diese Prozedur bis zur SQL-Injektion geöffnet. –

4

Konnten Sie nicht einfach einen and auf dem Join verwenden? Der Join wird versucht, aber wenn @three null ist, dann würden keine Joins zu einem Synonym auftreten ... oder müssen Sie den Join aus Performancegründen wirklich ignorieren? wenn so dynamische SQL ist die einzige Art, wie ich sehen konnte, damit es funktioniert ...

ALTER PROCEDURE [dbo].[Search] 
@one NVARCHAR(50), @two NVARCHAR(50), @three NVARCHAR(50) 

SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo 
Inner JOIN dbo.values AS cval 
    ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc 
    ON (cval.sID = sc.sID AND sc.Accept = 'A') 
LEFT JOIN dbo.Synonym AS synm 
    ON cinfo.ID = synm.ID 
    and @three IS NOT NULL    **<---------------------** 

where (cinfo.NAM LIKE '%'[email protected]+'%' OR cinfo.CAS LIKE '%'[email protected]+'%' OR 
    synm.SynonymID LIKE '%'[email protected]+'%') AND 
    (cval.PropID = '1' OR 
    cval.PropID = '2' OR 
    cval.PropID = '3' OR 
    cval.PropID = '4' OR) 
0

Was:

ALTER PROCEDURE [dbo].[Search] 
@one NVARCHAR(50), @two NVARCHAR(50), @three NVARCHAR(50) 

SELECT cinfo.ID, 
    cinfo.Nam, 
    cinfo.INAM, 
    cinfo.CA, 
    cinfo.Form, 
    cinfo.Std, 
    cval.Prop, 
    cval.Cons, 
    sc.Accep 

From dbo.Info AS cinfo 
Inner JOIN dbo.values AS cval 
    ON cinfo.ID = cval.ID 
INNER JOIN dbo.Sources AS sc 
    ON (cval.sID = sc.sID AND sc.Accept = 'A') 
LEFT JOIN dbo.Synonym AS synm 
    ON (cinfo.ID = synm.ID AND @three IS NOT NULL) 

where (cinfo.NAM LIKE '%'[email protected]+'%' OR cinfo.CAS LIKE '%'[email protected]+'%' OR 
    synm.SynonymID LIKE '%'[email protected]+'%') AND 
    (cval.PropID = '1' OR 
    cval.PropID = '2' OR 
    cval.PropID = '3' OR 
    cval.PropID = '4' OR) 
0

IF @three mit diesem ersetzen:

LEFT JOIN (select * from dbo.Synonym where @three IS NOT NULL) as synm ON cinfo.ID = synm.ID 

und Überprüfen Sie die Syntax der ALTER-Prozedur und die LIKE-Syntax.

Verwandte Themen