2008-09-18 16 views
10

Todos sabemos que las declaraciones preparadas son una de las mejores maneras de defenderse de los ataques de inyección SQL. ¿Cuál es la mejor manera de crear una declaración preparada con una cláusula "IN"? ¿Hay una manera fácil de hacer esto con una cantidad no especificada de valores? Tome la siguiente consulta, por ejemplo.¿Manejar los datos en una cláusula IN, con parámetros de SQL?

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (1,2,3) 

Actualmente estoy utilizando un bucle sobre mis valores posibles para construir una cadena como.

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (@IDVAL_1,@IDVAL_2,@IDVAL_3) 

¿Es posible usar simplemente pasar una matriz como el valor del parámetro de búsqueda y usar una consulta de la siguiente manera?

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (@IDArray) 

En caso que es importante que estoy trabajando con SQL Server 2000, en VB.Net

+0

agregar una etiqueta SQLServer – MotoWilliams

+0

una etiqueta t-sql también podría ser adecuada. –

Respuesta

1

Si desea pasar una matriz, tendrá una función en SQL que se puede convertir esa matriz en una sub-selección.

Estas funciones son muy comunes, y la mayoría de los sistemas domésticos las aprovechan.

La mayoría de los ORM comerciales, o más bien profesionales, hacen ins haciendo un conjunto de variables, por lo que si tiene ese funcionamiento, creo que ese es el método estándar.

-1

En SQL Server 2008, finalmente lograron resolver este problema clásico agregando un nuevo tipo de datos "de tabla". Aparentemente, eso le permite pasar una matriz de valores, que pueden usarse en una selección secundaria para lograr lo mismo que una instrucción IN.

Si está utilizando SQL Server 2008, entonces podría ver eso.

+0

"En caso de que sea importante, estoy trabajando con SQL Server 2000" – digiguru

5

Aquí tiene - en primer lugar crear la siguiente función ...

Create Function [dbo].[SeparateValues] 
(
    @data VARCHAR(MAX), 
    @delimiter VARCHAR(10) 
) 
    RETURNS @tbldata TABLE(col VARCHAR(10)) 
As 
Begin 
    DECLARE @pos INT 
    DECLARE @prevpos INT 

    SET @pos = 1 
    SET @prevpos = 0 

    WHILE @pos > 0 
     BEGIN 

     SET @pos = CHARINDEX(@delimiter, @data, @prevpos+1) 

     if @pos > 0 
     INSERT INTO @tbldata(col) VALUES(LTRIM(RTRIM(SUBSTRING(@data, @prevpos+1, @[email protected])))) 

     else 

     INSERT INTO @tbldata(col) VALUES(LTRIM(RTRIM(SUBSTRING(@data, @prevpos+1, len(@data)[email protected])))) 

     SET @prevpos = @pos 
    End 

    RETURN 

END 

a continuación, utilizar el siguiente ...

Declare @CommaSeparated varchar(50) 
Set @CommaSeparated = '112,112,122' 
SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (select col FROM [SeparateValues](@CommaSeparated, ',')) 

creo SQL Server 2008 permitirá que las funciones de tabla.

ACTUALIZACIÓN

Usted aprieta un poco de capacidad utilizando la siguiente sintaxis ...

SELECT ID,Column1,Column2 FROM MyTable 
Cross Apply [SeparateValues](@CommaSeparated, ',') s 
Where MyTable.id = s.col 

Debido a que la sintaxis anterior hace que SQL Server para ejecutar un comando extra "Ordenar" mediante el " IN "cláusula. Además, en mi opinión, se ve mejor: D!

+0

Esto resuelve la solución, ya que le da una buena función para crear tablas a partir de listas de cualquier valor separado que desee, ¿por qué votar abajo? – digiguru

+0

Te voté. Esta es la solución que usamos también. Funciona con SQL 2000 y conceptualmente es fácil de entender para los miembros del equipo junior. Si pudiera, te votaría 5 puntos. He visto esta técnica descrita en publicaciones y en artículos. Esta solución también funciona bien con SQL Report Services. –

+0

¡Increíble, gracias! – Jaxedin

-2

Aquí hay una técnica que utilizo

ALTER Procedure GetProductsBySearchString 
@SearchString varchar(1000), 
as 
set nocount on 
declare @sqlstring varchar(6000) 
select @sqlstring = 'set nocount on 
select a.productid, count(a.productid) as SumOf, sum(a.relevence) as CountOf 
from productkeywords a 
where rtrim(ltrim(a.term)) in (''' + Replace(@SearchString,' ', ''',''') + ''') 
group by a.productid order by SumOf desc, CountOf desc' 

exec(@sqlstring) 
+0

Ejecutar cadenas sql es una forma muy peligrosa de hacer cosas en un entorno de producción. – digiguru

0

Se puede crear un TempTable tabla temporal con un único valor de la columna e insertar todos los ID. Entonces podría hacerlo con una subselección:

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (SELECT VALUE FROM TempTable) 
0

Vaya con la solución publicada por digiguru. Es una gran solución reutilizable y usamos la misma técnica también. A los nuevos miembros del equipo les encanta, ya que ahorra tiempo y mantiene constantes nuestros procedimientos almacenados.La solución también funciona bien con SQL Reports, ya que los parámetros pasados ​​a los procedimientos almacenados para crear los conjuntos de registros pasan en varchar (8000). Usted simplemente lo conecta y listo.

Cuestiones relacionadas