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

Parametrizar uma cláusula SQL IN


Você pode parametrizar cada valor, então algo como:
string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";

string[] paramNames = tags.Select(
    (s, i) => "@tag" + i.ToString()
).ToArray();

string inClause = string.Join(", ", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
    for(int i = 0; i < paramNames.Length; i++) {
       cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
}

Que lhe dará:
cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0, @tag1, @tag2, @tag3)"
cmd.Parameters["@tag0"] = "ruby"
cmd.Parameters["@tag1"] = "rails"
cmd.Parameters["@tag2"] = "scruffy"
cmd.Parameters["@tag3"] = "rubyonrails"

Não, isso não está aberto à injeção de SQL. O único texto injetado no CommandText não é baseado na entrada do usuário. É baseado exclusivamente no prefixo "@tag" codificado e no índice de uma matriz. O índice sempre ser um número inteiro, não é gerado pelo usuário e é seguro.

Os valores inseridos pelo usuário ainda estão inseridos em parâmetros, portanto, não há vulnerabilidade lá.

Editar:

Deixando de lado as preocupações de injeção, observe que a construção do texto de comando para acomodar um número variável de parâmetros (como acima) impede a capacidade do servidor SQL de tirar proveito das consultas em cache. O resultado líquido é que você quase certamente perde o valor de usar parâmetros em primeiro lugar (em oposição a simplesmente inserir as strings de predicado no próprio SQL).

Não que os planos de consulta em cache não sejam valiosos, mas IMO essa consulta não é complicada o suficiente para ver muitos benefícios dela. Embora os custos de compilação possam se aproximar (ou até exceder) os custos de execução, você ainda está falando de milissegundos.

Se você tiver RAM suficiente, espero que o SQL Server provavelmente também armazene em cache um plano para as contagens comuns de parâmetros. Suponho que você sempre possa adicionar cinco parâmetros e deixar as tags não especificadas serem NULL - o plano de consulta deve ser o mesmo, mas parece muito feio para mim e não tenho certeza de que vale a pena a micro-otimização (embora, no Stack Overflow - pode valer a pena).

Além disso, o SQL Server 7 e versões posteriores parametrizarão consultas automaticamente, portanto, o uso de parâmetros não é realmente necessário do ponto de vista do desempenho. No entanto, é crítico do ponto de vista de segurança - especialmente com dados inseridos pelo usuário como este.