我们希望在使用Visual Studio DataSet Designer创建的查询或存储过程的“Order By”子句中使用参数。
示例:
FROM TableName
WHERE (Forename LIKE '%' + @SearchValue + '%') OR
(Surname LIKE '%' + @SearchValue + '%') OR
(@SearchValue = 'ALL')
ORDER BY @OrderByColumn
显示以下错误:
Variables are only allowed when ordering by an expression referencing
a column name.
答案 0 :(得分:40)
你应该可以这样做:
SELECT *
FROM
TableName
WHERE
(Forename LIKE '%' + @SearchValue + '%') OR
(Surname LIKE '%' + @SearchValue + '%') OR
(@SearchValue = 'ALL')
ORDER BY
CASE @OrderByColumn
WHEN 1 THEN Forename
WHEN 2 THEN Surname
END;
@OrderByColumn
以对Forename
进行排序。Surname
进行排序。虽然要注意性能。这些类型的构造可能会干扰查询优化器找到最佳执行计划的能力。例如,即使索引覆盖Forename
,查询仍可能需要完整排序,而不是仅按顺序遍历索引。
如果是这种情况,并且您无法忍受性能影响,则可能需要为每个可能的排序顺序提供单独的查询版本,这会使客户端的内容变得复杂。
答案 1 :(得分:1)
我知道我要晚些使用这种线程了,但是我只想发布此消息,以防其他人遇到类似的问题。
当您尝试直接对参数执行ORDER BY
时,似乎会出现此问题,因为SQL Server希望您提供一个数字(第一个字段为1,第二个字段为2,依此类推。 )或以标识符(MyField或“ MyField”)或字符串(“ MyField”)形式显示的列名。
例如:
DECLARE @ORDERBY AS NVARCHAR(20)
;
SELECT @ORDERBY = :Param1 --(Supposing that the user enters 'MyField')
;
SELECT TOP 1 *
FROM MyTable
ORDER BY @ORDERBY DESC
;
您收到以下错误:
由ORDER BY数字1标识的SELECT项包含一个 变量作为表示列位置的表达式的一部分。 仅在通过表达式引用进行排序时才允许使用变量 列名。 (SQLSTATE = 42000)(1008)(Severity = 16)
如果您以上述任何一种方式(使用标识符或字符串)手动写出查询,则不会出现错误。
SELECT TOP 1 *
FROM MyTable
ORDER BY MyField DESC
;
SELECT TOP 1 *
FROM MyTable
ORDER BY "MyField" DESC
;
SELECT TOP 1 *
FROM MyTable
ORDER BY 'MyField' DESC
;
因此,如果您对同一参数执行CAST()
,则其值将转换为字符串,并且查询将成功执行:
DECLARE @ORDERBY AS NVARCHAR(20)
;
SELECT @ORDERBY = :Param1 --(Supposing that the user enters the text 'MyField')
;
SELECT TOP 1 *
FROM MyTable
ORDER BY CAST(@ORDERBY AS NVARCHAR(20)) DESC
;
在这种情况下(同样,假设用户将字符串“ MyField”写为:Param1的值),正在执行的实际查询是:
SELECT TOP 1 *
FROM MyTable
ORDER BY 'MyField' DESC
;
此查询成功执行,没有错误,对性能没有明显影响,而无需将所有可能的用户输入枚举到CASE
语句中,该语句可能扩展到数百个值。
从2005年到2016年,我在Microsoft SQL Server中多次使用此解决方案,没有任何问题。
希望这对某人还是有帮助的。