3

我有一个带有 VB.Net 前端的 .Net Web 系统,它通过 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 的解决方案无法工作。

谢谢大家!

更新/回应:

嗯,我就是这么想的。谢谢大家的理智检查。(在某些情况下,命令字符串当前正在动态构建,但我们正在将系统向更准备好的语句方向移动,这是我不知道可能的边缘情况之一。

再次感谢!

4

8 回答 8

5

不,那行不通。

我可以立即想到两种可能性来做你想做的事情:

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

凭借另外 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 

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

于 2009-01-21T21:17:41.770 回答
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 的语法时

于 2009-01-21T21:25:59.757 回答
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
于 2009-01-21T21:37:06.177 回答
1

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

于 2009-01-21T21:14:19.437 回答
1

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

不过,这个问题的简短答案是“不”

于 2009-01-21T21:15:12.943 回答
1

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

//从查询字符串中获取请求的订单
字符串 sortOrderRequest = request["SortOrder"].ToUpper();
字符串排序参数 = "";
if (sortOrderRequest.Equals("ASC"))
  sortParam = " order by ordervalue ASC ";
否则 if (sortOrderRequest.Equals("DESC"))
  sortParam = " order by ordervalue DESC ";

暗淡命令 As SqlCommand = New SqlCommand("", connection)
command.CommandText = "SELECT * FROM someTable " + sortParam;
命令.准备()
reader = command.ExecuteReader()
于 2009-05-28T16:43:47.547 回答
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
于 2009-05-28T16:50:07.627 回答
0

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

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 
于 2019-02-14T17:50:51.503 回答