The name of the Schema in our database is dynamic. Why won't the following work?
public void ReadVersion(string connString, string schemaName)
{
string selectCommand = "SELECT major FROM [@SchemaName].[version]");
using (SqlConnection sqlConn = new SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand(selectCommand, sqlConn))
{
sqlConn.Open();
cmd.Parameters.AddWithValue("@SchemaName", schemaName);
object result = cmd.ExecuteScalar();
}
}
}
When the command is executed, the parameter value is not substituted. Is this a limitation of the SqlCommand Parameters?
You can't do the following in plain SQL (so ignoring all of the ADO.Net overheads):
DECLARE @SchemaName sysname
SET @SchemaName = 'dbo'
SELECT major FROM @SchemaName.[version]
And the reason is simple. What SQL wants after FROM
is a name. What you're trying to give it is a string. SQL Server doesn't randomly start peering inside of strings to see if they resemble some other construct.
To your sanitation query, assuming that you're keeping the schema names sane, just use a simple regex on the schema name before you trust it (e.g. ^[A-Z][A-Z0-9]+$
should be enough for most uses). Make sure you use a whitelist (allowed characters) rather than a blacklist.
Is this a limitation of the SqlCommand Parameters?
Yes, it is a limitation. In ADO.NET you cannot use parameters for the schema (things like table and column names). Your best bet is to use string concatenation and obviously as a result your own filtering for injection.