2012-02-01 61 views
1

我们数据库中的模式名称是动态的。为什么不能继续工作?如何使用SqlCommand参数指定选择查询的模式名称

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(); 
     } 
    } 
} 

当命令执行时,参数值不被替换。这是SqlCommand参数的限制吗?

回答

4

不能做普通的SQL以下(所以忽略所有的ADO.Net开销):

DECLARE @SchemaName sysname 
SET @SchemaName = 'dbo' 
SELECT major FROM @SchemaName.[version] 

而且原因很简单。在FROM之后,SQL想要的是名称。你试图给它的是字符串。 SQL Server 不会在字符串内部随机地开始对齐以查看它们是否类似于其他构造。

对于您的卫生查询,假设您保持模式名称健全,只需在模式名称上使用简单的正则表达式,然后再信任它(例如^[A-Z][A-Z0-9]+$应该足够用于大多数用途)。确保您使用白名单(允许的字符)而不是黑名单。

+1

感谢Damien - 我对SQL的理解已经增长了,我现在看到我可以让我们的代码更加优雅,通过给DB用户运行时)DEFAULT_SCHEMA - 因为我们为每个模式创建一个匹配的唯一数据库用户 – GarethOwen 2012-02-02 09:53:02

+0

嗨 - 我希望我不要necro这个线程,但它是可行的只是检查@SchemaName对sys.schemas来验证它? – 2014-01-02 23:23:57

3

这是SqlCommand参数的限制吗?

是的,这是一个限制。在ADO.NET中,您不能使用模式参数(例如表名和列名)。你最好的选择是使用字符串连接,显然作为你自己的过滤注入。

+1

我认为这不是SqlCommandParameter的限制。他们不是为了这样的使用而设计的。 – 2012-02-01 10:44:03

+0

谢谢Darin。我想使用参数,以便我不必担心SQL注入。这个公共方法在一个库中供其他内部项目使用。有关如何“过滤注射”的任何建议? – GarethOwen 2012-02-01 10:44:47

+2

@GarethOwen,你可能想创建一个测试,通过模式名称是有效的。例如长度并且不应该包含[,],“,' – 2012-02-01 10:49:54

相关问题