Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment concaténer des variables dans des chaînes SQL

Vous pouvez accomplir cela (si je comprends ce que vous essayez de faire) en utilisant SQL dynamique.

L'astuce consiste à créer une chaîne contenant l'instruction SQL. C'est parce que le nom de la table doit être spécifié dans le texte SQL réel, lorsque vous exécutez l'instruction. Les références de table et les références de colonne ne peuvent pas être fournies en tant que paramètres, celles-ci doivent apparaître dans le texte SQL.

Vous pouvez donc utiliser quelque chose comme cette approche :

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

EXEC (@stmt)

Tout d'abord, nous créons une instruction SQL sous forme de chaîne. Étant donné une @KeyValue de 'Foo', cela créerait une chaîne contenant :

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

À ce stade, c'est juste une chaîne. Mais nous pouvons exécuter le contenu de la chaîne, en tant qu'instruction SQL dynamique, en utilisant EXECUTE (ou EXEC pour faire court).

La vieille école sp_executesql La procédure est une alternative à EXEC, une autre façon d'exécuter du SQL dynamique, qui vous permet également de passer des paramètres, plutôt que de spécifier toutes les valeurs sous forme de littéraux dans le texte de l'instruction.

SUIVI

EBarr souligne (correctement et de manière importante) que cette approche est sensible à l'injection SQL.

Considérez ce qui se passerait si @KeyValue contenait la chaîne :

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

La chaîne que nous produirions en tant qu'instruction SQL serait :

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

Lorsque nous exécutons cette chaîne en tant qu'instruction SQL :

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

Et ce n'est pas seulement une DROP TABLE qui pourrait être injectée. N'importe quel SQL pourrait être injecté, et cela pourrait être beaucoup plus subtil et encore plus néfaste. (Les premières attaques peuvent être des tentatives de récupération d'informations sur les tables et les colonnes, suivies de tentatives de récupération de données (adresses e-mail, numéros de compte, etc.)

Une façon de résoudre cette vulnérabilité consiste à valider le contenu de @KeyValue, en disant qu'il ne doit contenir que des caractères alphabétiques et numériques (par exemple, vérifiez s'il y a des caractères qui ne se trouvent pas dans ces plages en utilisant LIKE '%[^A-Za-z0-9]%' . Si un caractère illégal est trouvé, rejetez la valeur et quittez sans exécuter de SQL.