Консолидированный: SQL Pass запятые значения в SP для фильтрации - PullRequest
1 голос
/ 02 ноября 2009

Я здесь, чтобы поделиться консолидированным анализом по следующему сценарию:

У меня есть таблица «Item», и у меня есть SP для поиска. Я хочу иметь возможность поиска нескольких ItemCodes вроде:

- Table structure : Item(Id INT, ItemCode nvarchar(20))
- Filter query format: SELECT * FROM Item WHERE ItemCode IN ('xx','yy','zz')

Я хочу сделать это динамически, используя хранимую процедуру. Я передам параметр @ItemCodes, который будет иметь значения, разделенные запятыми (','), и поиск будет выполняться, как указано выше.


Ну, я уже побывал во многих постах \ форумах, и вот некоторые темы:

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

Также другие подходы, такие как XML и т. Д., Если они усложняют ситуацию, я не могу их использовать.

И, наконец, никаких дополнительных временных таблиц. Я должен управлять производительностью, а также сложностью.

http://www.sommarskog.se/arrays-in-sql-2005.html Это потребует, чтобы я 'объявил' тип параметра при передаче его SP, это искажает абстракцию (я не устанавливаю тип ни в одном из моих параметров, потому что каждый из них обрабатывается универсальным образом)

http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters Это структурированный подход, но он увеличивает сложность, требует изменения уровня структуры БД и не является абстрактным, как указано выше.

http://madprops.org/blog/splitting-text-into-words-in-sql-revisited/ Ну, это похоже на мои старые решения. Вот что я делал в прошлом -

I created an SQL function : [GetTableFromValues] (returns a temp table populated each item (one per row) from the comma separated @ItemCodes)

И вот как я использую его в своем фильтре WHERE caluse в SP -

SELECT * FROM Item WHERE ItemCode in (SELECT * FROM[dbo].[GetTableFromValues](@ItemCodes))

Этот многоразовый и выглядит простым и коротким (сравнительно, конечно). Все, что я пропустил, или любой эксперт с лучшим решением (очевидно, «в пределах» ограничений вышеупомянутых пунктов).

Спасибо.

1 Ответ

0 голосов
/ 21 ноября 2011

Я думаю, что использование динамического T-SQL будет прагматичным в этом сценарии. Если вы осторожны с дизайном, динамический SQL работает как шарм. Я использовал его в бесчисленных проектах, когда он подходил. С учетом сказанного позвольте мне решить две ваши основные проблемы - производительность и внедрение SQL.

Что касается производительности, прочитайте ссылку T-SQL на параметризованный динамический sql и sp_executesql (вместо sp_execute). Комбинация параметризованного sql и использования sp_executesql позволит вам выйти за пределы производительности, гарантируя повторное использование планов запросов и избежание sp_recompiles! Я использовал динамический sql даже в контекстах реального времени, и с этими двумя предметами он работает как шарм. Для вашего удовольствия вы можете запустить цикл из миллиона или около того обращений к sp с двумя оптимизациями и без них и использовать sql profiler для отслеживания событий sp_recompile.

Теперь по поводу SQL-инъекции. Это будет проблемой, если вы используете неправильный пользовательский виджет, такой как текстовое поле, чтобы позволить пользователю вводить коды элементов. В этом случае возможно, что хакер может написать операторы выбора и попытаться извлечь информацию о вашей системе. Вы можете написать код, чтобы предотвратить это, но я думаю, что идти по этому пути - ловушка. Вместо этого рассмотрите возможность использования соответствующего пользовательского виджета, такого как список (в зависимости от вашей платформы веб-интерфейса), который допускает множественный выбор. В этом случае пользователь просто выберет из списка «представленных предметов», а ваш код сгенерирует строку, содержащую соответствующие коды предметов. В основном вы не передаете пользовательский текст в динамический sql sp! Вы даже можете использовать скользящие виджеты выбора на основе JQuery, но суть в том, что пользователь не может набрать любой недопустимый текст, попадающий на ваш слой данных.

Далее вам просто нужна простая хранимая процедура в базе данных, которая принимает параметры для кодов элементов (например, '' 'xyz' '', '' 'abc' ''). Внутренне он должен использовать sp_executesql с параметризованным динамическим запросом.

Надеюсь, это поможет. -Tabrez

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