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

Comment passer une variable contenant une liste à une requête SQL dynamique ?

Tout simplement

EXECUTE ('select id from  [dbo].[CSVToTable] ('''[email protected]+''')')
        declare @listOfIDs varchar(1000);

Ou, quelle est la meilleure façon

SET @listOfIDs = '5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61'; 

EXECUTE sp_executesql N'select id from  [dbo].[CSVToTable] (@listOfIDs)',
                      N'@listOfIDs VARCHAR(1000)',
                      @listOfIDs;
  • Pourquoi j'obtiens cette erreur ?

Parce que vous transmettez vraiment trop de paramètres, plus que nécessaire, pour comprendre cela, exécutez cette requête et voyez ce que vous transmettez réellement à votre fonction

SELECT 'select id from  [dbo].[CSVToTable] ('[email protected]+')';

qui reviendra (et c'est ce que vous essayez vraiment d'exécuter)

select id from  [dbo].[CSVToTable] (5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61)

au lieu de (ce dont vous avez besoin)

SELECT 'select id from  [dbo].[CSVToTable] ('''[email protected]+''')';
  • Ok, mais pourquoi sp_executesql est meilleur que exec ?

Simplement, EXEC vous obligera à concaténer toutes vos variables en une seule chaîne, c'est le pire, et cela rend votre code entièrement ouvert à l'injection SQL . Voir Bad Habits to Kick : Using EXEC() instead of sp_executesql , cela ne signifie pas que sp_executesql est 100 % sécurisé, mais il permet de paramétrer les déclarations tandis que EXEC() pas, donc c'est plus sûr que EXEC en termes d'injection SQL .

Enfin, puisque vous taguez et que vous ne précisez pas la version, je vous suggère d'utiliser SPLIT_STRING() fonction (2016+) plutôt que la vôtre, et si vous n'avez pas la version 2016+, créez la vôtre sans utiliser WHILE boucle pour obtenir plus de bonnes performances, cause WHILE la boucle s'exécutera lentement, vous devez donc l'éviter.

Exemples :