SQL: создание фильтра - это можно сделать без динамического SQL? - PullRequest
0 голосов
/ 03 марта 2011

Это то, что я вижу все время в списке, составленном нами. Нужно сделать фильтр для 2 столбцов (я взял более короткий пример, у нас есть списки с 50 столбцами, выглядит одинаково ...)

Мне было интересно, есть ли способ сделать это как-то иначе. Что вы, ребята, используете для фильтрации записей из таблицы?

    /* parameters */
@CostNumber = ...
@Description = ...
    /* parameters */

SET @strSQL = '
SELECT  [CostLevelId], [CostNumber], [Description]
FROM    [CostLevel]
WHERE   1 = 1 ' /* this looks weird, but we'll add the "WHERE" stuff easier */

IF (@CostNumber IS NOT NULL)
BEGIN
    SET @strSQL = @strSQL + ' AND [CostNumber] LIKE ''%' + REPLACE(@CostNumber,'''','''''') + '%'' '
END

IF (@Description IS NOT NULL)
BEGIN
    SET @strSQL = @strSQL + ' AND [Description] LIKE ''%' + REPLACE(@Description,'''','''''') + '%'' '
END

EXEC (@strSQL)

Ответы [ 4 ]

1 голос
/ 03 марта 2011

Почему бы не отказаться от подхода динамического SQL?

    /* parameters */
@CostNumber = ...
@Description = ...
    /* parameters */

SELECT  [CostLevelId], [CostNumber], [Description]
FROM    [CostLevel]
WHERE   [CostNumber] LIKE '%' + @CostNumber + '%'
AND [Description] LIKE '%' + @Description + '%'

Пара вещей, на которые следует обратить внимание - null s в параметрах @CostNumber и @Description - вы должны будете убедиться, что преобразовали их в пустые строки.

Еще одна вещь, которую вам нужно учитывать, это то, что @Description might содержит символ %, и вам придется избежать этого, чтобы LIKE работал правильно.

0 голосов
/ 03 марта 2011

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

Это сработает для утверждения типа.

SELECT  [CostLevelId], [CostNumber], [Description]
FROM    [CostLevel]
WHERE   
    (@CostNumber is null or [CostNumber] LIKE '%'+@CostNumber+'%')
    and
    (@Description is null or [Description] LIKE '%'+@Description+'%')

если это прямое сравнение на равенство, вы можете использовать coalesce для сравнения либо с заполненной переменной, либо, когда переменная имеет значение null, с самим собой.

SELECT  [CostLevelId], [CostNumber], [Description]
FROM    [CostLevel]
WHERE   
    [CostNumber] = coalesce(@CostNumber,[CostNumber])
    and
    [Description] = coalesce(@Description,[CostNumber])

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

0 голосов
/ 03 марта 2011

У меня нет способа проверить этот банкомат, но как насчет

SELECT  [CostLevelId], [CostNumber], [Description]
FROM [CostLevel]
WHERE (@CostNumber IS NOT NULL AND [CostNumber] LIKE ''%' + REPLACE(@CostNumber,'''','''''') + '%'')
OR
(@Description IS NOT NULL AND [Description] LIKE ''%' + REPLACE(@Description,'''','''''') + '%'')
GROUP BY [CostLevelId], [CostNumber], [Description]

Если это не удастся, вы можете попробовать UNION вместо OR (и группировки).

0 голосов
/ 03 марта 2011

Я не знаю, как это сделать, когда задействован оператор LIKE, когда я использую операторы сравнения, я использую значения по умолчанию, чтобы получить что-то вроде этого:

select *
from dbo.SomeTable a
where
(a.IntColumn = @IntColumnValue or @IntColumnValue = -1)
and (a.VarCharColumn = @VarCharValue or @VarCharValue = 'zzz')

Таким образом, если я не хочу применять определенный фильтр, я просто устанавливаю его на значение по умолчанию (в этом примере -1 или zzz), поэтому его проверка всегда возвращает true.

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

where (a.VarCharColumn like '%' + @VarCharValue + '%' or @VarCharValue = '§§§TheDefaultValue§§§')
...