Vou começar por dizer que o que o título diz é parvo, sim é parvo, não porque não dá jeito ou porque a ideia é parva, mas simplesmente porque não é possível fazer. Se quiser fazer algo como o que está em seguida é para esquecer não é possível fazer:
SELECT @column FROM @table
Agora há uma forma mais ou menos elegante de resolver este problema. O que queremos ao termos prepared statements é evitar sql injection, esse é o verdadeiro problema. Então a solução passa por validar se a tabela e a coluna existem na nossa base de dados, e assim até validamos se a query é válida.
Temos assim a garantia que tanto a tabela como a coluna existem, se não existirem a aplicação enviará uma excepção. No meu caso quis mesmo que a aplicação terminasse, mas podemos não ser tão radicais e simplesmente retornar um booleano indicando o sucesso. Basta agora fazer uma query normal sem haver a preocupação que haja sql injection.
private void AssertValidTableAndColumnName(SqlConnection connection,
SqlCommand cmd, string table, string column)
{
cmd.CommandText = "SELECT COUNT(*) FROM SYS.TABLES WHERE NAME = @table";
SqlParameter tab = new SqlParameter("table", SqlDbType.NVarChar, 500);
tab.Value = table;
cmd.Parameters.Add(tab);
cmd.Prepare();
int count = (int)(cmd.ExecuteScalar());
if (count == 0)
{
throw new ArgumentException("Invalid table name", table);
}
cmd.CommandText = @"SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table
AND COLUMN_NAME = @column";
SqlParameter col = new SqlParameter("column", SqlDbType.NVarChar, 500);
col.Value = column;
cmd.Parameters.Add(col);
cmd.Prepare();
count = (int)(cmd.ExecuteScalar());
if (count == 0)
{
throw new ArgumentException("Invalid column name", column);
}
}
Temos assim a garantia que tanto a tabela como a coluna existem, se não existirem a aplicação enviará uma excepção. No meu caso quis mesmo que a aplicação terminasse, mas podemos não ser tão radicais e simplesmente retornar um booleano indicando o sucesso. Basta agora fazer uma query normal sem haver a preocupação que haja sql injection.
[...]
AssertValidTableAndColumnName(connection, cmd, table, column);
cmd.CommandText = string.Format("SELECT id,{1} FROM {0}", table, column);
[...]










