Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como passo uma variável que contém uma lista para uma consulta SQL dinâmica?


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

Ou, qual é a melhor maneira
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;
  • Por que recebo este erro?

Porque você realmente passa parâmetros demais, mais do que o necessário, para entender isso execute essa consulta e veja o que você realmente está passando para sua função
SELECT 'select id from  [dbo].[CSVToTable] ('[email protected]+')';

que retornará (e é isso que você realmente está tentando executar)
select id from  [dbo].[CSVToTable] (5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61)

em vez de (que é o que você precisa)
SELECT 'select id from  [dbo].[CSVToTable] ('''[email protected]+''')';
  • Ok, mas por que sp_executesql é melhor que exec ?

Simplesmente, EXEC vai forçar você a concatenar todas as suas variáveis ​​em uma única string, essa é a pior coisa, e isso torna seu código totalmente aberto para injeção de SQL . Veja Bad Habits to Kick : Using EXEC() instead of sp_executesql , isso não significa que sp_executesql é 100% seguro, mas permite que as declarações sejam parametrizadas enquanto EXEC() não, portanto, é mais seguro que EXEC em termos de injeção de SQL .

Por fim, como você marca e você não especificar a versão, sugiro que você use SPLIT_STRING() função (2016+) em vez da sua, e se você não tiver a versão 2016+, crie a sua própria sem usar WHILE loop para obter um melhor desempenho, porque WHILE loop será lento, portanto, você deve evitá-lo.

Exemplos: