Вложенный оператор if в операторе SELECT хранимой процедуры SQL Server - PullRequest
0 голосов
/ 08 декабря 2009

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

Я пытаюсь создать хранимую процедуру (MS SQL Server 2005), которая принимает несколько переданных значений и фактически динамически создает SQL, как если бы это было с встроенным SQL.

Вот где я отклеился.

Мы имеем (несколько упрощенно для ясности):

@searchf1 varchar(100),   -- search filter 1
@searchr1 varchar(100),   -- search result 1
@searchf2 varchar(100),   -- search filter 2
@searchr2 varchar(100),   -- search result 2
@direction char(1),   -- direction to order results in
AS

set nocount on
set dateformat dmy

SELECT *
  FROM database.dbo.table T
 WHERE T.deleted = 'n'
ORDER BY CASE @direction
            WHEN 'A' THEN T.id
            WHEN 'D' THEN T.id DESC
         END

END

set nocount off

Я также пробовал строки из ORDER BY как:

IF @direction = 'N' THEN
     ORDER BY 
          T.id
ELSE
     ORDER BY
          T.id DESC

Оба подхода дают мне ошибку в следующем виде:

"Неверный синтаксис рядом с ключевым словом" DESC "." (который ссылается на идентификатор строки DESC после окончательного ORDER BY

Как часть этой хранимой процедуры, я также хочу попытаться указать совпадающие пары значений, которые ссылаются на поле для поиска и поле для сопоставления, они могут присутствовать или ''. Для этого мне нужно добавить в раздел SELECT код, подобный следующему:

WHERE 
     deleted = 'n'
     IF @searchf1 <> '' THEN
         AND fieldf1 = @searchf1 AND fieldr1 = @searchr1

Это, однако, приводит к ошибкам типа:

Неверный синтаксис рядом с ключевым словом «IF».

Я знаю, что динамический SQL этого типа не самый элегантный. И я знаю, что мог бы сделать это с помощью глобальных выражений IF ELSE, но если бы я это сделал, SP был бы длиной в тысячи строк; Всего будет 15 пар этих полей поиска, вместе с направлением и полем, чтобы упорядочить это направление.

(текущая версия этого SP использует переданный список идентификаторов для возврата, сгенерированного неким встроенным динамическим SQL, поэтому я пытаюсь уменьшить его до одного попадания для создания набора записей)

Любая помощь с благодарностью. Я очень упростил код в приведенном выше примере для ясности, так как я спрашиваю об общей концепции вложенного оператора IF с SELECT и ORDER BY.

Ответы [ 3 ]

2 голосов
/ 08 декабря 2009

Попробуйте так:

SELECT *  FROM database.dbo.table T WHERE T.deleted = 'n'
ORDER BY 
CASE WHEN @direction='A' THEN T.id END ASC,
CASE WHEN @direction='D' THEN T.id END DESC         

Источник статьи:
http://blog.sqlauthority.com/2007/07/17/sql-server-case-statement-in-order-by-clause-order-by-using-variable/

2 голосов
/ 08 декабря 2009

Для этого я бы попробовал перейти к более формальному решению на основе динамического SQL, что-то вроде следующего, учитывая ваши заданные входные параметры

DECLARE @SQL VARCHAR(MAX)

SET @SQL = '
SELECT

FROM
     database.dbo.table T
WHERE
     T.deleted = ''n'' '

--Do your conditional stuff here
IF @searchf1 <> '' THEN
    SET @SQL = @SQL + ' AND fieldf1 = ' + @searchf1 + ' AND fieldr1 = ' + @searchr1 + ''' '

--Finish the query
SET @SQL = @SQL + ' ORDER BY xxx'

EXEC(@SQL)

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Использование динамического SQL НЕ является чем-то, что не следует воспринимать легкомысленно, и при ВСЕХ обстоятельствах следует уделять должное внимание тому, чтобы вы не были открыты для внедрения SQL Атаки, однако, для некоторых операций динамического поиска это один из самых элегантных маршрутов.

0 голосов
/ 08 декабря 2009

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

ВЫБРАТЬ * FROM database.dbo.table T ГДЕ T.deleted = 'n' И fieldf1 = COALESCE (@ searchf1, fieldf1) И fieldr1 = COALESCE (@ searchr1, fieldr1) --ТАК ДАЛЕЕ ЗАКАЗАТЬ ПО fieldf1

Таким образом, вы не используете динамический SQL, и он достаточно читабелен, просто укажите переменную null, если вы хотите опустить данные.

ПРИМЕЧАНИЕ: Как я уже говорил, этот маршрут НЕ будет работать, если какой-либо из столбцов COALESCE содержит нулевые значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...