Подтвердить что ты не робот

Сохраненная процедура с дополнительными параметрами "ГДЕ"

У меня есть форма, в которой пользователи могут указывать различные параметры для обработки некоторых данных (статус, дата и т.д.).

Я могу создать запрос, который:

SELECT * FROM table WHERE:
status_id = 3
date = <some date>
other_parameter = <value>

и т.д.. Каждый WHERE является необязательным (я могу выбрать все строки с status = 3 или все строки с date = 10/10/1980 или все строки с status = 3 AND date = 10/10/1980 и т.д.).

Учитывая большое количество параметров, все необязательные, каков наилучший способ создания динамической хранимой процедуры?

Я работаю над различными БД, такими как: MySQL, Oracle и SQLServer.

4b9b3361

Ответ 1

Один из самых простых способов сделать это:

SELECT * FROM table 
WHERE ((@status_id is null) or (status_id = @status_id))
and ((@date is null) or ([date] = @date))
and ((@other_parameter is null) or (other_parameter = @other_parameter))

и т.д.. Это полностью исключает динамический sql и позволяет выполнять поиск по одному или нескольким полям. Исключив динамический sql, вы удалите еще одну проблему безопасности в отношении SQL-инъекции.

Ответ 2

Создайте свою процедуру следующим образом:

CREATE PROCEDURE [dbo].[spXXX]
    @fromDate datetime = null,
    @toDate datetime = null,
    @subCode int = null
as
begin
set NOCOUNT ON
/* NOCOUNT limits the server feedback on select results record count */
SELECT
    fields...
FROM
    source
WHERE
    1=1
--Dynamic where clause for various parameters which may or may not be passed in.
and ( @fromDate is null or [dateField] >= @fromDate)
and ( @toDate is null or [dateField] <= @toDate)
and ( @subCode is null or subCode= @leaveTypeSubCode)
order by fields...

Это позволит вам выполнить процедуру с 0 параметрами, всеми параметрами или любыми # параметрами.

Ответ 3

Это стиль, который я использую:

t-sql

SELECT    *        
FROM    table        
WHERE     
status_id    =    isnull(@status_id ,status_id)     
and    date    =    isnull(@date ,date )     
and    other_parameter    =    isnull(@other_parameter,other_parameter) 

оракул

SELECT    *        
FROM    table        
WHERE     
status_id    =    nval(p_status_id ,status_id)     
and    date    =    nval(p_date ,date )     
and    other_parameter    =    nval(p_other_parameter,other_parameter)

Ответ 4

Вы можете сделать что-то вроде

WHERE 
(
 ParameterA == 4 OR ParameterA IS NULL
)

AND
(
 ParameterB == 12 OR ParameterB IS NULL
)

Ответ 5

Если вы хотите избежать динамического наращивания строк SQL (чего часто лучше всего избегать), вы можете сделать это в хранимых процедурах, сравнивая каждый критерий в своем месте, где указано значение по умолчанию, которое равнозначно "игнорировать". Например:.

select * from Table where
   (@Col1 IS NULL OR Col1 = @Col1) /*If you don't want to filter in @col, pass in NULL*/
   AND
   (@Col2 IS NULL OR Col2 = @Col2)

Ответ 6

Читаемый и поддерживаемый способ сделать это (даже применимый с JOIN/APPLY):

where 
      (@parameter1 IS NULL OR your_condition1)
  and (@parameter2 IS NULL OR your_condition2) 
-- etc

Однако это плохая идея на большинстве больших таблиц (даже больше с использованием JOIN/APPLY), так как ваш план выполнения не будет игнорировать значения NULL и генерирует массивную лазейку производительности (например: сканирование всей таблицы, ищущей значения NULL).

Обходной путь в SQL Server - это использование параметров WITH (RECOMPILE) в вашем запросе (доступно с SQL Server 2008 SP1 CU5 (10.0.2746)).

Лучший способ реализовать это (разумный результат) - использовать блок IF... ELSE, по одному для каждой комбинации. Возможно, это изнурительно, но у вас будут лучшие результаты, и это не имеет значения для настроек вашей базы данных.

Если вам нужна дополнительная информация, вы можете найти KM. answer здесь.