你能在sql server预编译语句中参数化排序顺序吗?

时间:2009-01-21 21:13:22

标签: sql-server ado.net prepared-statement

我有一个带有VB.Net前端的.Net网络系统,通过ADO.Net与SQL Server 2005后端通信。基本上,我想要做的是:

Dim command As SqlCommand = New SqlCommand("", connection)
command.CommandText = "SELECT * FROM someTable ORDER BY orderValue @SortOrder"
Dim sortParam As SqlParameter = New SqlParameter("@SortOrder", SqlDbType.varChar, 3)
sortParam.Value = "ASC"
command.Parameters.Add(sortParam)
command.Prepare()
reader = command.ExecuteReader()

排序顺序将通过查询字符串或其他类型传递。此代码抛出“@SortOrder'附近的语法错误。无法准备语句。”

这是否可能,或者我有一些非常愚蠢的语法错误我没有看到?

(而且,是的,客户端只运行.net 2.0,所以基于LINQ的解决方案无法正常工作。

谢谢,全部!

更新/回复:

嗯,这就是我的想法。感谢所有人的理智检查。 (对于某些上下文,命令字符串当前是动态构建的,但是我们正在以更准备的语句方向移动系统,这是我不知道的边缘情况之一。

再次感谢!

8 个答案:

答案 0 :(得分:5)

不,那不行。

有两种可能性,我可以想到你正在尝试做的事情:

  1. 动态构建SQL字符串
  2. 从查询中返回数据表,然后使用视图进行排序。

  3. 经过6年左右的经验(加上SQL Server版本),我有办法实现这一目标。

    DECLARE @SortByIdASC AS INT;
    SET @SortByIdASC = 1;
    WITH cte AS (
    SELECT Id, Foo, Bar
          , ROW_NUMBER() OVER (ORDER BY Id ASC) AS IdSortAsc
          , ROW_NUMBER() OVER (ORDER BY Id DESC) AS IdSortDesc 
       FROM MyTable
    )
    
    SELECT Id, Foo, Bar
       FROM cte 
       ORDER BY CASE WHEN @SortByIdASC = 1 THEN IdSortAsc
                     WHEN @SortByIdASC = 2 THEN IdSortDesc 
                     ELSE ''
                     END 
               , Foo, Bar 
    

    这也允许从给定的排序顺序中向上,向下或甚至排除该特定列。

答案 1 :(得分:2)

虽然可以更新排序中使用的列。请看以下示例:

declare @fname int,@lname int

select @fname=1,@lname=0

select * from [user]
order by case when @Fname=1 then firstname when @lname=1 then lastname end

我认为您不能使用此技术来修改排序顺序,但您至少可以更改排序列。至少当我尝试使用SQL 2005获取有关语法的投诉时

答案 2 :(得分:2)

您可以采用与现有帖子类似的方式。

declare @firstSortField int, @secondSortField int
set @firstSortField = 1
set @secondSortField = 3

select firstName, lastName, phoneNumber
from customers
order by 
    case @firstSortField when 1 then firstName when 2 then lastName when 3 then phoneNumber else null end, 
    case @secondSortField when 1 then firstName when 2 then lastName when 3 then phoneNumber else null end

答案 3 :(得分:1)

我认为不可能,只能准备参数值。

答案 4 :(得分:1)

不,你需要每次都将它构建到SQL查询中,或者如果你有一组排序顺序,请为这些命令缓存命令对象并重新用作套件。

问题的简短回答是“否”

答案 5 :(得分:1)

这完全符合您的要求,并且绝不会将用户输入的字符串放在数据库附近的任何位置。

//get the requested order from the query string
string sortOrderRequest = request["SortOrder"].ToUpper();
string sortParam = "";
if ( sortOrderRequest.Equals("ASC"))
  sortParam = " order by ordervalue ASC ";
else if (sortOrderRequest.Equals("DESC"))
  sortParam = " order by ordervalue DESC ";

Dim command As SqlCommand = New SqlCommand("", connection)
command.CommandText = "SELECT * FROM someTable " + sortParam;
command.Prepare()
reader = command.ExecuteReader()

答案 6 :(得分:1)

当然可以。创建两个别名列,SortASC和SortDESC,用你想要的任何东西填充它们,并对它们进行排序。

-- Testcase setup
DECLARE @OrderASC bit
SET @OrderASC = 0

-- Statement required
SELECT
    Users.*,
    CASE @OrderASC WHEN 1 THEN Users.Alias ELSE null END AS _SortASC,
    CASE @OrderASC WHEN 0 THEN Users.Alias ELSE null END AS _SortDESC
FROM Users
ORDER BY _SortASC, _SortDESC DESC

答案 7 :(得分:0)

我扩展了接受的答案,以找到一种有效的解决方案,用于在SQL查询中参数化参数子句。这是一个示例代码:

DECLARE @Sorting VARCHAR(200) = 'CreationTime ASC'

SELECT v.*, 
CASE WHEN @Sorting = 'CreationTime ASC' THEN ROW_NUMBER() OVER (ORDER BY v.CreationTime ASC) 
     WHEN @Sorting = 'CreationTime DESC' THEN ROW_NUMBER() OVER (ORDER BY v.CreationTime DESC) 
                                         ELSE ROW_NUMBER() OVER (ORDER BY v.Id ASC) END AS rownum

FROM Vehicles v ORDER BY rownum