sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo concatenar variables en cadenas SQL

Puede lograr esto (si entiendo lo que está tratando de hacer) usando SQL dinámico.

El truco es que necesita crear una cadena que contenga la instrucción SQL. Esto se debe a que el nombre de la tabla debe especificarse en el texto SQL real, cuando ejecuta la instrucción. Las referencias de tablas y columnas no se pueden proporcionar como parámetros, deben aparecer en el texto SQL.

Así que puedes usar algo como este enfoque:

SET @stmt = 'INSERT INTO @tmpTbl1 SELECT ' + @KeyValue 
    + ' AS fld1 FROM tbl' + @KeyValue

EXEC (@stmt)

Primero, creamos una instrucción SQL como una cadena. Dado un @KeyValue de 'Foo', eso crearía una cadena que contiene:

'INSERT INTO @tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'

En este punto, es solo una cadena. Pero podemos ejecutar el contenido de la cadena, como una instrucción SQL dinámica, usando EXECUTE (o EXEC para abreviar).

El sp_executesql de la vieja escuela El procedimiento es una alternativa a EXEC, otra forma de ejecutar SQL dinámico, que también le permite pasar parámetros, en lugar de especificar todos los valores como literales en el texto de la instrucción.

SEGUIMIENTO

EBarr señala (correctamente y de manera importante) que este enfoque es susceptible a la inyección de SQL.

Considere lo que sucedería si @KeyValue contenía la cadena:

'1 AS foo; DROP TABLE students; -- '

La cadena que produciríamos como declaración SQL sería:

'INSERT INTO @tmpTbl1 SELECT 1 AS foo; DROP TABLE students; -- AS fld1 ...'

Cuando EJECUTAMOS esa cadena como una declaración SQL:

INSERT INTO @tmpTbl1 SELECT 1 AS foo;
DROP TABLE students;
-- AS fld1 FROM tbl1 AS foo; DROP ...

Y no es solo una DROP TABLE que podría inyectarse. Se podría inyectar cualquier SQL, y podría ser mucho más sutil e incluso más nefasto. (Los primeros ataques pueden ser intentos de recuperar información sobre tablas y columnas, seguidos de intentos de recuperar datos (direcciones de correo electrónico, números de cuenta, etc.)

Una forma de abordar esta vulnerabilidad es validar el contenido de @KeyValue, digamos que debe contener solo caracteres alfabéticos y numéricos (por ejemplo, verifique si hay caracteres que no estén en esos rangos usando LIKE '%[^A-Za-z0-9]%' . Si se encuentra un carácter ilegal, rechace el valor y salga sin ejecutar ningún SQL.