2010-06-21 5 views
5

Ich habe eine gespeicherte SQL-Prozedur des FormularsPassing gespeicherte SQL-Prozedur Gesamtheit der WHERE-Klausel

SELECT [fields] FROM [table] WHERE @whereSql 

Ich mag ein Argument, das Verfahren zu übergeben (@whereSql), die die gesamten spezifiziert WHERE-Klausel, aber die folgenden Fehler wird zurückgegeben:

An expression of non-boolean type specified in a context where a condition is expected 

Kann dies getan werden?

+5

Warum möchten Sie? Sie erhalten keinen Vorteil einer gespeicherten Prozedur mit allen Kosten. –

+0

Ich denke, das ist keine gute Verwendung für eine gespeicherte Prozedur. Amir gibt dir eine Möglichkeit, aber in deinem Fall denke ich, dass ich eine Sichtweise verwende. – DomreiRoam

+0

Joel und Jeff sprechen über SQL-Parametrisierung in Podcast 31. https://stackoverflow.fogbugz.com/default.asp?W26423 –

Antwort

8

Die kurze Antwort ist, dass Sie es nicht so machen können - SQL Server betrachtet den Inhalt einer Variablen als VALUE. Es wird die auszuführende Zeichenfolge nicht dynamisch aufgebaut (daher ist dies der korrekte Weg SQL Injection Attacken zu vermeiden).

Sie sollten alle Anstrengungen unternehmen, um eine dynamische WHERE zu vermeiden, vor allem aus diesem Grund, aber auch aus Gründen der Effizienz. Versuchen Sie stattdessen, die WHERE-Klausel so aufzubauen, dass je nach Situation Teile mit vielen ORs kurzgeschlossen werden.

Wenn es keinen Weg gibt, können Sie aus den Teilen des Befehls eine eigene Zeichenfolge erstellen und dann EXEC ausführen.

So könnten Sie dies tun:

DECLARE @mywhere VARCHAR(500) 
DECLARE @mystmt VARCHAR(1000) 
SET @mywhere = ' WHERE MfgPartNumber LIKE ''a%'' ' 
SELECT @mystmt = 'SELECT TOP 100 * FROM Products.Product AS p ' + @mywhere + ';' 
EXEC(@mystmt) 

Aber ich empfehlen stattdessen, dass Sie dies tun:

SELECT TOP 100 * 
    FROM Products.Product AS p 
    WHERE 
     (MfgPartNumber LIKE 'a%' AND ModeMfrPartNumStartsWith=1) 
    OR (CategoryID = 123 AND ModeCategory=1) 
+0

Brilliante Antwort - auch ich ging den Weg des dynamischen SQL (von meinen Tagen schreiben schmutzige VBA für Access Backends), aber das hat mir eine sicherere Alternative mit nur einem Umdenken gezeigt. – Katstevens

8

Ich glaube, das dynamische SQL verwenden getan werden kann. Siehe unten:

CREATE PROCEDURE [dbo].[myProc] 
@whereSql nvarchar(256) 

AS 
    EXEC('SELECT [fields] FROM [table] WHERE ' + @whereSql) 
GO 

Das gesagt, sollten Sie einige ernsthafte Forschung über dynamisches SQL tun, bevor Sie es tatsächlich verwenden. Hier sind ein paar Links, die ich nach kurzer Suche stieß auf:

+0

Löschte meine Antwort und gab Ihnen +1. Dies ist der Link, den ich in meinem Beitrag hatte: http://msdn.microsoft.com/en-us/library/ms188332.aspx – Amir

0

dynamische SQL in einigen der Antworten aufgelistet ist auf jeden Fall eine Lösung. Wenn jedoch Dynamic SQL vermieden werden muss, ist eine der Lösungen, die ich bevorzuge, die Verwendung von Tabellenvariablen (oder temporären Tabellen), um den Parameterwert zu speichern, der für den Vergleich in der WHERE-Klausel verwendet wird.

Hier ist ein Beispiel für die Implementierung einer gespeicherten Prozedur.

CREATE PROCEDURE [dbo].[myStoredProc] 
@parameter1 varchar(50) 
AS 

declare @myTempTableVar Table(param1 varchar(50)) 
insert into @myTempTableVar values(@parameter1) 

select * from MyTable where MyColumn in (select param1 from @myTempTableVar) 

GO 

Falls Sie in mehr Werten übergeben will, dann kann die comma separated values ​​als Zeilen in der Tabelle variabel und in der gleichen Art und Weise zum Vergleich herangezogen werden gespeichert.

CREATE PROCEDURE [dbo].[myStoredProc] 
@parameter1 varchar(50) 
AS 

--Code Block to Convert Comma Seperated Parameter into Values of a Temporary Table Variable 
declare @myTempTableVar Table(param1 varchar(50)) 
declare @index int =0, @tempString varchar(10) 

if charindex(',',@parameter1) > 0 
begin 
set @index = charindex(',',@parameter1) 
while @index > 0 
    begin 
    set @tempString = SubString(@parameter1,1,@index-1) 
    insert into @myTempTableVar values (@tempString) 
    set @parameter1 = SubString(@parameter1,@index+1,len(@parameter1)[email protected]) 
    set @index = charindex(',',@parameter1) 
    end 

    set @tempString = @parameter1 
    insert into @myTempTableVar values (@tempString) 
end 
else 
insert into @myTempTableVar values (@parameter1) 

select * from MyTable where MyColumn in (select param1 from @myTempTableVar) 

GO