2010-06-21 39 views
5

I tiene un SQL procedimiento almacenado de la formaPases SQL procedimiento almacenado totalidad de cláusula WHERE

SELECT [fields] FROM [table] WHERE @whereSql 

Quiero pasar el procedimiento de un argumento (@whereSql) que especifica la totalidad cláusula WHERE, pero el siguiente error se devuelve:

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

¿Se puede hacer esto?

+5

¿Por qué le gustaría? Usted termina sin el beneficio de un procedimiento almacenado con todo el costo. –

+0

Creo que no es un buen uso para un procedimiento almacenado. Amir te da una posibilidad, pero en tu caso, creo que usaría una vista. – DomreiRoam

+0

Joel y Jeff hablan sobre la parametrización de SQL en Podcast 31. https://stackoverflow.fogbugz.com/default.asp?W26423 –

Respuesta

8

La respuesta corta es que no puede hacerlo así: SQL Server mira el contenido de una variable como un VALOR. No crea dinámicamente la cadena para ejecutar (por lo que esta es la forma correcta para evitar ataques de inyección SQL).

Debe hacer todos los esfuerzos posibles para evitar un DONDE dinámico como lo está tratando de hacer, en gran parte por este motivo, pero también por el bien de la eficiencia. En cambio, intente construir la cláusula WHERE para que cortocircuite las piezas con muchas RUP, según la situación.

Si no hay forma de evitarlo, aún puede construir una cadena propia ensamblada a partir de las piezas del comando, y luego EXEC.

Por lo que podría hacer esto:

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) 

pero recomiendo vez que haga esto:

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

Respuesta brillante: yo también iba por la ruta del SQL dinámico (desde mis días escribiendo VBA sucio para Access backends) pero esto me ha mostrado una alternativa más segura con solo un cambio en el pensamiento. – Katstevens

8

Creo que esto se puede hacer utilizando SQL dinámico. Vea a continuación:

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

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

Dicho esto, debe hacer algunas investigaciones serias sobre SQL dinámico antes de que realmente lo use. Aquí hay algunos enlaces que me encontré después de una búsqueda rápida:

+0

Eliminé mi respuesta y le doy un +1. Este es el enlace que tuve en mi publicación: http://msdn.microsoft.com/en-us/library/ms188332.aspx – Amir

0

SQL dinámico aparece en algunas de las respuestas es definitivamente una solución. Sin embargo, si se debe evitar el uso de SQL dinámico, una de las soluciones que prefiero es usar variables de tablas (o tablas temporales) para almacenar el valor del parámetro que se utiliza para comparar en la cláusula WHERE.

Aquí hay un ejemplo de implementación de Procedimiento almacenado.

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 

En caso de que desea pasar de múltiples valores, los valores separados por comas se pueden almacenar como filas de la variable de tabla y se utilizan de la misma manera para la comparación.

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 
Cuestiones relacionadas