2012-06-13 2 views
2

В принципе, мне нужно создать список элементов из базы данных SQL, однако пользователь может выбрать фильтр для любой комбинации из 7 фильтров, а также выбрать колонку для заказа, а также порядок по указанию.Сложное сочетание сортировки, упорядочивания, фильтрации SQL Server

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

В моей хранимой процедуре до сих пор я пытался:

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

Я также попытался использовать набор операторов IF ELSE для запуска надлежащего параметризованного SQL, однако это быстро становится огромным деревом и будет кошмаром для поддержания.

Я не первый человек, который нуждался в таком решении, и должен быть лучший способ, чем выше? Кроме того, в качестве побочного вопроса есть хороший способ упорядочивать и упорядочивать по направлениям параметризованным образом, помимо выполнения множества IFs?

+0

Если вы можете уменьшить фильтры 'и (FLD1 = @ filter1 или @ filter1 является нулевым)' вы должны прочитать это http://www.sommarskog.se/dyn-search-2008.html –

ответ

1

Для фильтрации используйте фильтр COELSCE для фильтрации любых комбинаций условий.В хранимой процедуре была бы список всех параметров, которые пользователь будет выполнять поиск, то в запросе будет что-то вроде:

SELECT * 
FROM YourTable t 
WHERE 1 = 1 
AND t.FirstColumn = COALESCE(@FirstColumnParam, t.FirstColumn) 
AND t.SecodndColumn = COALESCE(@SecondColumnParam, t.SecondColumn) 
.... 

Если какие-либо из параметров имеет нулевое значение, то условие пропускается. и для 1=1, то есть в случае, если в ваш запрос не переданы никакие фильтры.

Для заказа: вы можете использовать CASE заявление на заказ любых Выбираются колонки:

ORDER BY (CASE WHEN @OrderByParam = 1 Then FirstColumn ELSE .... END) 
+0

Будет ли оптимизатор видеть это SARG и использовать индексы, если вы используете функцию COALESCE? – buckley

+0

@ buckley, Нет, я думаю, что он создаст индексы в случае, если он написан так, как вы написали 'AND (FirstColumn = @FirstColumnParam OR @FirstColumnParam is NULL)' –

+0

@MahmoudGamal очень благодарен, работает! Есть так много хороших ключевых слов SQL, о которых я узнаю каждый раз, а потом вот так! – radm4

1

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

Нет, если вы используете sp_executesql и передать свои параметры в качестве аргументов TOT, что sproc. Так как вы даете свои данные в качестве параметров не будет никакого SQL Injection

http://sqlinthewild.co.za/index.php/2009/04/03/dynamic-sql-and-sql-injection/

http://blogs.msdn.com/b/raulga/archive/2007/01/04/dynamic-sql-sql-injection.aspx

Я также попытался с помощью набора IF ELSE заявления для запуска правильного параметризованного SQL, однако это быстро становится огромным деревом и будет кошмар для поддержания.

Согласитесь, если вы используете IF ELSE, но есть также модель называется поймать все запросы

WHERE (ProductID = @Product Or @Product IS NULL) 
AND (ReferenceOrderID = @OrderID OR @OrderID Is NULL) 
... 

Подробнее здесь http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/

Обязательно укажите OPTION (RECOMPILE) в конце поскольку в противном случае ваши запросы могут пострадать за то, что называется параметр sniffing

Also as a side question is there a good way to do order by and order by direction in a parameterised way, besides doing lots of IFs? 

Возможной Дубликат Dynamic Sorting within SQL Stored Procedures

В конце концов, вы можете с sp_executesql или поймать все запросы (это общая проблема с этими 2 пыталось решение). Я обычно предпочитаю все запросы, но не забудьте указать опцию (перекомпилировать).

+0

Вы не можете передать предложение 'where' в качестве аргумента в' sp_executesql'. И если вы построите аргумент SQL в 'sp_executesql' динамически, это, конечно, открыто для SQL-инъекции., – Andomar

+0

@Andomar Я разъяснил ответ, что вы должны передать их в качестве аргументов для sproc. Я бы просто перекомпилировал опцию catch + +, которая также упростит динамический порядок – buckley

Смежные вопросы