Я очень много нового для SQL и изо всех сил стараюсь учиться, поэтому я предупреждаю всех, что мои ошибки могут быть очевидными - не думайте, что я знаю, что я делаю ! Это находится в SQL Server 2005.SQL Server 2005 Dynamic Select
EDIT: приведенный ниже код случайно вводит в заблуждение; my_table - НЕ таблица, это вид. Упомянутая информация просмотра стежков вместе по двум схемам использует LEFT OUTER JOIN для одного из своих столбцов, использует материал ((SELECT .....)) для четырех из них, и когда я разместил это, не было столбца, для которого нет двух строк использовать одни и те же данные; С тех пор я изменил его, чтобы использовать SELECT DISTINCT.
Я пытаюсь написать функцию, которая принимает в качестве аргумента четыре части имени - первый, средний, последний и заголовок - и запускает выбор по данной таблице на основе этих 4 частей, используя LIKE. Этот наивный подход возвращает правильные результаты:
ALTER FUNCTION [my_schema].[my_table] (
@first NVARCHAR(max) = null
,@middle NVARCHAR(max) = null
,@last NVARCHAR(max) = null
,@title NVARCHAR(max) = null
)
RETURNS TABLE AS RETURN(
SELECT DISTINCT
l.foo,
l.bar,
l.spam
FROM my_database.my_schema.my_table l
WHERE
l.FirstName like ISNULL('%'[email protected]+'%', '%')
AND l.LastName like ISNULL('%'[email protected]+'%', '%')
AND l.MiddleName like ISNULL('%'[email protected]+'%', '%')
AND l.TitleName like ISNULL('%'[email protected]+'%', '%')
);
Проблема в том, что это невероятно медленно. Самая очевидная причина, по которой я могу видеть медленность, - это очень глупое поведение, когда сравниваются «%»; я бы хотел, чтобы SQL отвечал на NULL, не выполняя сравнения вообще. Мне еще предстоит разработать способ сделать это; каждое решение, которое я придумываю, запускается в стену, которая является синтаксисом SQL.
Мой вопрос: «Как избежать сравнения LIKE с«% », когда соответствующая переменная равна null?». Я как можно противник использовать EXEC в любом контексте, потому что я беру пользовательский ввод из дикой природы и возвращаю потенциально чувствительные данные, и я хотел бы быть как можно более параноидальным в отношении инъекций - эти четыре переменные - это дикий вход , и я хотел бы доверять им как можно меньше.
EDIT: Я сделал тесты скорости и с тех пор пришел к выводу, что избежать лишних LIKE не помогает ни в какой значимой степени. Я приветствую любые рекомендации по фактическому достижению ускорения и, скорее всего, вскоре опубликую новый вопрос по этим направлениям, как только я передумаю, как это происходит.
Это не NULL, это 'LIKE'. Утверждение типа '% anything%' гарантируется принудительным сканированием таблицы, даже если в текстовых полях указаны индексы. Вы запрашиваете строки с некоторым значением * в любом месте * в поле. Такие поиски, как 'something%', представляют собой поиск по диапазону, чтобы они могли использовать индексы. Если вы действительно хотите выполнять полнотекстовый поиск, вам лучше использовать функции полнотекстового поиска (http://technet.microsoft.com/en-us/library/ms142583.aspx), такие как CONTAINS и FREETEXT –
К сожалению, для этого требуется уникальный кластерный индекс в базовом представлении, и есть несколько причин, по которым SQL Server отказывается создавать его для меня, включая использование LEFT OUTER JOIN, использование трех отдельных подзапросов и использование DISTINCT. Я не уверен, как реорганизовать представление, чтобы избежать этих проблем, сохраняя при этом свою полезность. – quindraco
Какой вид? Является ли 'my_table' не таблицей? Если это таблица, * почему * вы не можете создать кластеризованный индекс, если его еще нет, потому что, например, ваш первичный ключ? * Почему * вы пытаетесь создать индекс FTS для представления вместо таблицы?Если вы не предоставите все детали, это невозможно. Во всяком случае, проблема * - это то, как вы используете 'LIKE', чтобы сделать по существу FTS –