2010-06-21 15 views
5

Ho una SQL stored procedure di moduloPassaggio SQL elementi di WHERE

SELECT [fields] FROM [table] WHERE @whereSql 

voglio passare la procedura un argomento (@whereSql) che specifica l'intero WHERE, ma il seguente errore viene restituito:

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

Questo può essere fatto?

+5

Perché vuoi? Si finisce con nessuno dei vantaggi di una stored procedure con tutti i costi. –

+0

Penso che non sia un buon uso per una stored procedure. Amir ti dà una possibilità ma nel tuo caso penso che userò una vista. – DomreiRoam

+0

Joel e Jeff parlano di Parametrizzazione SQL in Podcast 31. https://stackoverflow.fogbugz.com/default.asp?W26423 –

risposta

8

La risposta breve è che non è possibile farlo in questo modo: SQL Server considera il contenuto di una variabile come VALUE. Non crea dinamicamente la stringa da eseguire (motivo per cui questo è il corretto modo per evitare attacchi di SQL injection).

Si dovrebbe fare ogni sforzo per evitare un WHERE dinamico come si sta tentando di fare, in gran parte per questo motivo, ma anche per motivi di efficienza. Invece, prova a costruire la clausola WHERE in modo che cortocircuiti pezzi con un sacco di OR, a seconda della situazione.

Se non c'è modo di aggirarlo, è ancora possibile creare una stringa del proprio assemblato dai pezzi del comando, quindi ESEGUI.

Così si potrebbe fare questo:

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) 

ma vi consiglio, invece, che si esegue questa operazione:

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

Risposta brillante - Anch'io stavo andando alla rotta dell'SQL dinamico (dai miei giorni scrivendo VBA sporco per Access backend) ma questo mi ha mostrato un'alternativa più sicura con solo un cambiamento nel modo di pensare. – Katstevens

8

Credo che questo può essere fatto utilizzando SQL dinamico. Vedi sotto:

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

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

Detto questo, si dovrebbe fare qualche ricerca seria su SQL dinamico prima di usarlo effettivamente. qui ci sono alcuni link che ho trovato dopo una ricerca rapida:

+0

Eliminata la mia risposta e dandoti un +1. Questo è il collegamento che avevo nel mio post: http://msdn.microsoft.com/en-us/library/ms188332.aspx – Amir

0

SQL dinamico elencato in alcune delle risposte è sicuramente una soluzione. Tuttavia, se SQL dinamico deve essere evitato, una delle soluzioni che preferisco è fare uso di variabili di tabella (o tabelle temporanee) per memorizzare il valore del parametro che viene utilizzato per il confronto nella clausola WHERE.

Ecco un esempio di implementazione di stored procedure.

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 

Nel caso si desideri passare più valori, allora i valori separati da virgola possono essere memorizzate come righe nella variabile di tabella e utilizzati allo stesso modo per il confronto.

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