Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Передать фильтр в хранимую процедуру  [new]
MAcKZloy
Member

Откуда:
Сообщений: 182
Что нужно: сделать фильтр по нескольким параметрам.
Что задумал сгенерировать блок WHERE и передать как параметр, в хранимке подставить вместо блока Where. Такое вообще можно реализовать?

Пример:
в программе
@Where = "Where a = 1 and b = 2 and c like 'de%'"

в хранимке

SELECT * FROM MyTable @WHERE
6 янв 10, 22:04    [8153347]     Ответить | Цитировать Сообщить модератору
 Re: Передать фильтр в хранимую процедуру  [new]
flexgen
Member

Откуда: Город на песке
Сообщений: 765
MAcKZloy,

Тебе придется всю SQL-команду генерировать, не только WHERE часть.
Что-то вроде
create procedure MyDynamicProc @WhereClause varchar(max)

as 

declare @SelectClause varchar(max)
declare @SQLStatement varchar(max)

set @SelectClause = 'SELECT * FROM MyTable'
set @SQLStatement = @SelectClause + space(1)+ @WhereClause

exec (@SQLStatement)

За точность не ручаюсь, может выдавать ошибки, предназначено для SQL 2005 и выше.
6 янв 10, 22:24    [8153406]     Ответить | Цитировать Сообщить модератору
 Re: Передать фильтр в хранимую процедуру  [new]
MAcKZloy
Member

Откуда:
Сообщений: 182
flexgen
MAcKZloy,

Тебе придется всю SQL-команду генерировать, не только WHERE часть.
Что-то вроде
create procedure MyDynamicProc @WhereClause varchar(max)

as 

declare @SelectClause varchar(max)
declare @SQLStatement varchar(max)

set @SelectClause = 'SELECT * FROM MyTable'
set @SQLStatement = @SelectClause + space(1)+ @WhereClause

exec (@SQLStatement)

За точность не ручаюсь, может выдавать ошибки, предназначено для SQL 2005 и выше.


Спасибо, у меня 2008.
6 янв 10, 22:30    [8153424]     Ответить | Цитировать Сообщить модератору
 Re: Передать фильтр в хранимую процедуру  [new]
Ray D
Member

Откуда: from the middle of nowhere
Сообщений: 3598
Блог
Прямая дорога к sql injection.
6 янв 10, 22:58    [8153470]     Ответить | Цитировать Сообщить модератору
 Re: Передать фильтр в хранимую процедуру  [new]
flexgen
Member

Откуда: Город на песке
Сообщений: 765
Ray D
Прямая дорога к sql injection.

Она самая, но иногда без нее не обойтись.
6 янв 10, 22:59    [8153474]     Ответить | Цитировать Сообщить модератору
 Re: Передать фильтр в хранимую процедуру  [new]
Senya_L
Member

Откуда: Москва
Сообщений: 5381
MAcKZloy,

Вы думаете, что в этом форуме уж точно подскажут "волшебное" решение? Напрасно Вы так думаете... :)
6 янв 10, 23:12    [8153492]     Ответить | Цитировать Сообщить модератору
 Re: Передать фильтр в хранимую процедуру  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
flexgen
Ray D
Прямая дорога к sql injection.

Она самая, но иногда без нее не обойтись.
Как правило, когда встает вопрос о "передаче в хранимку секции WHERE", динамика используется явно не по месту.

Вообще в таком случае непонятно, зачем использовать хранимые процедуры - проще уж формировать весь запрос на клиенте.
6 янв 10, 23:18    [8153504]     Ответить | Цитировать Сообщить модератору
 Re: Передать фильтр в хранимую процедуру  [new]
Sybex
Member

Откуда: Moscow
Сообщений: 109
Ray D
Прямая дорога к sql injection.

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

Лучше стараться избегать динамического формирования запросов (да, бывают ситуации когда без динамического запроса не обойтись, но они все же редки) и стараться обходиться обычными методами. Например, если параметров не много, то можно делать так (при этом NULL будет означать, что по параметру поиск не производится):
SELECT *
  FROM MyTable
 WHERE (@a IS NULL OR a = @a) AND
       (@b IS NULL OR b = @b) AND
       (@c IS NULL OR c LIKE @c)

Плюс, иногда можно передавать в параметрах XML и делать потом выборку из этого XML в условии WHERE, в случае когда параметр должен удовлетворять нескольким условиям:
SELECT *
  FROM MyTable
 WHERE @a IN (SELECT C.value('.','int')
                FROM @a.nodes('/root/a') T(C))
XML в параметре может быть таким:
<root>
    <a>1</a>
    <a>2</a>
    <a>3</a>
    <a>4</a>
</root>
Вариантов обработки нескольких параметров для фильтра может быть много, и динамическое формирование запроса должно быть ближе к концу, когда отсеются все остальные варианты ;)
6 янв 10, 23:48    [8153594]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить