Более точный SQL-запрос для обработки необязательных фильтров предложений WHERE - PullRequest
0 голосов
/ 12 октября 2011

Пожалуйста, смотрите оператор SQL ниже:

Есть ли лучший способ сделать это, исключив утверждения из дела?

select * from Customer 
where FirstName like ISNULL('ja','') + '%'  
AND [EmailId] LIKE ISNULL('jaisonshereen@gmail.com1','') 
    + CASE when 'jaisonshereen@gmail.com1' =  '' then '%' else ''  end

1 Ответ

1 голос
/ 12 октября 2011

Основываясь на наблюдениях @ Thor84no, я параметризовал ваш запрос (предполагая, что это сгенерированный код) и принял следующие требования:

  • И @Firstname, и @Email необязательны
  • Если @Firstname не является пустым или пустым, всегда ставьте суффикс с% и делайте подобное, в противном случае примените фиктивный фильтр (LIKE '%')
  • Если @Email не является пустым или пустым, сделайтеточный поиск (например, @EMAIL), в противном случае примените фиктивный фильтр (LIKE '%')

Таким образом, он имеет такие параметры:

DECLARE @FirstName NVARCHAR(100)
DECLARE @EmailId NVARCHAR(100)
SET @FirstName = 'ja'
SET @EmailId = 'jaisonshereen@gmail.com1'

select * from Customer 
where FirstName like ISNULL(@FirstName,'') + N'%'  
AND [EmailId] LIKE ISNULL(@EmailId, N'') 
    + CASE when @EmailId =  N'' then N'%' else N''  end

Я считаю, что есть случай, которыйоднако вы не обрабатываете, а именно, если @Email имеет значение NULL - вам нужно изменить последнюю строку на

+ CASE when IsNull(@EmailId, '') =  N'' then N'%' else N''  end

План запросов вашего кода довольно хороший - он всегда будет WHERE FirstName LIKE '..% 'AND EMailId Like' .. '(или EmailId Like'% ') - возможно, именно поэтому генератор кода делает это.

Хотя соблазнительно сделать приведенное ниже для удобства чтения,' ИЛИ'повреждает план запроса и обычно приводит к сканированию таблицы / индекса

select * from Customer 
WHERE 
(ISNULL(@FirstName, N'') = N'' OR FirstName LIKE @FirstName + N'%')
AND (ISNULL(@EmailId, N'') = N'' OR [EmailId] = @EmailId) -- Assuming ANSI Nulls are ON

Так что, хотя то, что у вас есть, выглядит беспорядочно, на самом деле оно вполне оптимально.

Из интереса динамический SQL, такой как генерируемый ORMS, такой как LINQ2SQL, EF и т. Д., Часто имеетпреимущество перед сохраненным процессом в случаях, когда большое количество параметров является необязательным.Используя параметризованный SQL, планы запросов все еще могут кэшироваться, и запрос защищен от атак SQL-инъекций.Сравните

DECLARE @FirstName NVARCHAR(100)
DECLARE @EmailId NVARCHAR(100)
SET @FirstName = 'ja'
SET @EmailId = 'jaisonshereen@gmail.com1'

DECLARE @SQL NVARCHAR(MAX)
SET @SQL = N'SELECT * FROM Customer '

IF ISNULL(@FirstName,'') <> N'' OR ISNULL(@EmailId, N'') <> N''
    SET @SQL = @SQL + N'WHERE ' -- Need to handle the case where neither param provided

IF ISNULL(@FirstName, N'') <> N''
    SET @SQL = @SQL + N' FirstName LIKE @FirstName + ''%'''

IF ISNULL(@FirstName,'') <> N'' AND ISNULL(@EmailId, N'') <> N''
    SET @SQL = @SQL + N' AND'

IF ISNULL(@EmailId,'') <> N''
    SET @SQL = @SQL + N' EmailId = @EmailId' -- Exact match

exec sp_ExecuteSQL @SQL, N'@FirstName NVARCHAR(100), @EmailId NVARCHAR(100)', @FirstName=@FirstName, @EmailId=@EmailId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...