Можете ли вы параметризировать порядок сортировки в подготовленном SQL-запросе? - PullRequest
3 голосов
/ 22 января 2009

У меня есть веб-система .Net с интерфейсом VB.Net, взаимодействующим с интерфейсом SQL Server 2005 через ADO.Net. По сути, я хочу сделать следующее:

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 ]

5 голосов
/ 22 января 2009

Нет, это не сработает.

Есть две возможности, о которых я могу сразу подумать, чтобы сделать то, что вы пытаетесь сделать:

  1. Динамическое построение строки SQL
  2. Верните таблицу данных из вашего запроса, а затем используйте View для выполнения сортировки.

Имея около 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 

Это также позволяет сортировать вверх, вниз или даже исключать этот конкретный столбец из заданного порядка сортировки.

2 голосов
/ 22 января 2009

Вы можете аналогично существующему сообщению.

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
2 голосов
/ 22 января 2009

Пока можно обновить столбцы, используемые в сортировке. Возьмите следующий пример:

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

1 голос
/ 28 мая 2009

Конечно, можно сделать. Создайте два столбца с псевдонимами, 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
1 голос
/ 28 мая 2009

Это делает именно то, что вы просили, и никогда не помещает введенные пользователем строки рядом с базой данных.

//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()
1 голос
/ 22 января 2009

Нет, вам нужно каждый раз встраивать его в SQL-запрос или, если у вас есть поднабор порядков сортировки, кэшировать объект команды для них и повторно использовать как наборы.

Краткий ответ на вопрос: "Нет"

1 голос
/ 22 января 2009

Я не думаю, что это возможно, можно подготовить только значения параметров.

0 голосов
/ 14 февраля 2019

Я расширил принятый ответ, чтобы найти эффективное решение для параметризации предложения порядка в запросе 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 
...