你能只参数化where子句吗?

时间:2016-03-16 20:29:26

标签: c# sql sql-server

为了防止sql注入,我试图使用参数化查询。但是我不清楚我是否应该只调用where子句或查询的其他部分。例如,我正在尝试改进以下查询:

string strQ = @";WITH lstTable as (
                SELECT ROW_NUMBER() OVER(ORDER BY " + sort + @") AS RowNum, *
                FROM (
                SELECT *
                FROM SystemMessage
                WHERE Deleted = 0  ";`

此查询正在网格中使用,并根据用户的选择,它将按列名称排序。我需要使用paramaterize' sort'在这种情况下?

1 个答案:

答案 0 :(得分:4)

您是正确的,您不能直接使用参数用于此用例。但是,如果您需要使用参数,则取决于sort的填充方式。

如果它是硬编码的列名列表,并且用户只选择列表中的哪些索引将被选中,则无需担心参数化,用户在查询中没有直接输入所以他们不能把代码注入其中。

如果用户直接提供列名,则必须在传入之前清理用户输入,这样做的方法是使用sql函数QUOTENAME来清理输入。

string strQ = @"
declare @query nvarchar(max)
set @query = ';WITH lstTable as (
                SELECT ROW_NUMBER() OVER(ORDER BY' + QUOTENAME(@sortColumn) + ') AS RowNum, *
                FROM (
                SELECT *
                FROM SystemMessage
                WHERE Deleted = 0 '
exec sp_executesql @query";

这将会传递给@sortColumn的任何字符串,它会正确地将[ ]包裹在该字符串值周围。然后,它在动态生成的字符串中使用该excaped值,并使用sp_executesql运行该值。

一个重要的注意事项,此示例目前仅适用于单个列名称,您需要为要添加到查询中的每列添加QUOTENAME和新参数。如果您尝试传入FirstName, LastName,则会变为

;WITH lstTable as (
   SELECT ROW_NUMBER() OVER(ORDER BY [FirstName, LastName]) AS RowNum, *
       FROM (
       SELECT *
       FROM SystemMessage
       WHERE Deleted = 0

执行时会尝试查找名为“[FirstName, LastName]”的列,但会失败。