Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come faccio a passare una variabile che contiene un elenco a una query SQL dinamica?

Semplicemente

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

Oppure, qual è il modo migliore

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;
  • Perché ricevo questo errore?

Poiché passi davvero troppi parametri, più del necessario, per capirlo esegui questa query e vedi cosa sei veramente passa alla tua funzione

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

che tornerà (e questo è ciò che stai veramente cercando di eseguire)

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

invece di (che è quello che ti serve)

SELECT 'select id from  [dbo].[CSVToTable] ('''[email protected]+''')';
  • Ok, ma perché sp_executesql è meglio di exec ?

Semplicemente, EXEC ti costringerà a concatenare tutte le tue variabili in un'unica stringa, questa è la cosa peggiore, e questo rende il tuo codice completamente aperto a SQL injection . Vedi Bad Habits to Kick : Using EXEC() instead of sp_executesql , questo non significa che sp_executesql è sicuro al 100%, ma consente di parametrizzare le istruzioni mentre EXEC() no, quindi è più sicuro di EXEC in termini di SQL injection .

Infine, poiché tagghi e non specifichi la versione, ti suggerisco di utilizzare SPLIT_STRING() funzione (2016+) piuttosto che la tua, e se non hai la versione 2016+, creane una tua senza usare WHILE loop per ottenere prestazioni migliori, causa WHILE loop funzionerà lentamente, quindi dovresti evitarlo.

Esempi: