2010-12-17 17 views
9

Estoy pasando una lista de int (separadas por comas)t-sql Convertir cadenas separadas por comas en int, sin usar la función creada por el usuario

ie. 1, 2, 3, 4

a mi sp. Pero recibo un error porque la lista es una cadena y estoy comparando con un campo int. ¿Hay alguna manera de convertir la lista en int sin utilizar una función creada por el usuario?

Nota: employeeID es INT

declare @intArray varchar(200) 

SELECT * 
FROM tbl_Employee 
WHERE employeeID IN (@intArray) 

El error es "No se puede convertir tipo varchar a int"

+0

¿Qué versión de SQL Server? ¿Y puedes cambiar el código que está llamando a tu sp? –

+0

@Damien SQL Server 2005. Sí, puedo cambiar el código llamando a mi sp. – Kukoy

+1

ratas. Para 2008, sugiero cambiar a usar parámetros con valores de tabla. –

Respuesta

8

No desea convertir esa lista en un int, sino en una lista de entradas.

No hay un operador o función de conversión para eso, pero puede usar SQL dinámico para evitarlo.

Básicamente se escribe

EXECUTE('SELECT * FROM tbl_Employee WHERE employeeID IN ('[email protected]+')') 

estar al tanto de los ataques de inyección SQL sin embargo!

+3

Esta es una buena forma nativa de hacer lo que el OP quiere. Tenga en cuenta que a medida que la lista de empleados y 'ID's crece, la frase' IN' se vuelve cada vez más ineficaz. En 2005/2008, se prefiere 'EXISTS'. Además, SQL dinámico no se puede almacenar en caché, por lo que la ejecución nunca es más rápida que con otras declaraciones. – Brad

+0

@Brad: las declaraciones dinámicas se almacenan en caché, así como cualquier otra. Siempre que no cambie el texto de la consulta, se tomará el plan en caché. Por supuesto, diferentes listas de ID aquí serían un problema si la consulta se ejecuta con mucha frecuencia. EXISTS requeriría una tabla (temporal) para almacenar los ID buscados. Si solo tiene la lista (i.mi. desde una aplicación web donde el usuario puede seleccionar ciertos empleados con casillas de verificación), IN sigue siendo su mejor opción. – TToni

+0

Acepto que 'EXISTS' no es exactamente práctico aquí, simplemente quería señalar que es * preferred * si la tabla o la lista' IN' son grandes. Eso es bueno para aprender que SQL hace planes de caché para SQL dinámico (para cada cambio). Pero creo que este almacenamiento en caché es en gran medida descontable, ya que la consulta cambiará con frecuencia. Si no, ¿por qué elegirías usar SQL dinámico? – Brad

4

Usted está tratando de convertir no sólo un string a int, pero variosint s en uno. ¿Espera que su SELECT devolverá todos los empleados con una identificación incluida en la matriz?

Me doy cuenta de que quería hacer esto sin una función. Sin embargo, así es como lo hago actualmente y funciona muy bien. Toma lo que quieras de mi respuesta.

Este código utiliza un bucle while que podría mejorarse a un CTE recursivo si está en SQL 2005/2008. Puede utilizar la salida de la función como una tabla que INNER JOIN le permitirá filtrar rápidamente.

/* 
************************************************************************************************************************ 
    Name:   ConvertDelimitedListIntoTable 
    Description: Converts a list of delimited values into a table for use like a dynamic IN statment 

    Modification History 
    Date  Author   Description 
    ========== ============ ==================================== 
    2009-01-31 B. Williams  Initial Creation 

************************************************************************************************************************ 
*/ 
ALTER FUNCTION [dbo].[ConvertDelimitedListIntoTable] (
    @list NVARCHAR(MAX) ,@delimiter CHAR(1)) 
RETURNS @table TABLE ( 
    item VARCHAR(255) NOT NULL) 
AS 
    BEGIN 
     DECLARE @pos INT ,@nextpos INT ,@valuelen INT 

     SELECT @pos = 0 ,@nextpos = 1 

     WHILE @nextpos > 0 
      BEGIN 
       SELECT @nextpos = CHARINDEX(@delimiter,@list,@pos + 1) 
       SELECT @valuelen = CASE WHEN @nextpos > 0 THEN @nextpos 
             ELSE LEN(@list) + 1 
            END - @pos - 1 
       INSERT @table (item) 
       VALUES (CONVERT(INT,SUBSTRING(@list,@pos + 1,@valuelen))) 
       SELECT @pos = @nextpos 

      END 

     DELETE FROM @table 
     WHERE item = '' 

     RETURN 
    END 

Uso:

DECLARE @intArray varchar(200) 

SELECT * 
FROM tbl_Employee e 
     INNER JOIN dbo.ConvertDelimitedListIntoTable(@intArray,',') arr 
       ON e.EmployeeID = arr.Item 

También puede ser una forma rápida de hacer esto con una mesa tally.

+0

¡Eso es genial, gracias! –

+0

No logró hacer que la primera solución funcione en el procedimiento almacenado. ¡Gracias por este! –

Cuestiones relacionadas