То, как вы сформулировали запрос в настоящее время, и ввод динамических списков параметров подразумевает, что вы значительно строите запрос в памяти и выполняете его, и в этом случае вам, вероятно, лучше всего использовать клиентский язык, который строит запрос, чтобы просто вставлять элементы, когда они вам нужны. Вы не можете вставить список напрямую через параметр или переменную SQL на любом диалекте, который я знаю, поэтому я бы не стал слишком усердствовать, чтобы избежать того, что вам в любом случае нужно делать.
Тем не менее, если вы хотите использовать более постоянную структуру запроса в том, как вы компилируете это - предположив, что у вас есть таблица CategoryBdocs с полем CategoryBdocID, объявленным как INT Identity (1,1), тогда вы могли бы получить что-то работающее вместе с строки вашего текущего запроса, выполнив
select *
from library
where libraryID in
(select distinct libraryID from categoryAdocs where categoryAdocID in (4))
or LibraryID in
(select distinct libraryID from categoryBdocs where categoryBdocID in (-1))
и соедините свой список категории B после -1 - это всегда ничего не вернет, так что это безопасно. Если бы год не входил в список, вы могли бы заставить его работать как необязательный параметр, используя что-то вроде
or Year in (COALESCE(2004, Year))
и когда он выходил с NULL вместо 2004, он совпадал с самим собой и возвращался. Однако вы не можете сделать это со списком, и я не могу придумать чистый способ сделать это в SQL с необязательным списком.
Все это основано на предположении, что вы создаете запрос в памяти и выполняете его, хотя, похоже, это то, что вы делаете. Вы сказали, что вам не нравится это делать, и я согласен - это не идеально эффективно, и передача списка для объединения в запрос делает вас более открытым для SQL-инъекций.
Чтобы обойти это, я бы предложил обернуть это в хранимую процедуру. Если вы затем передадите строки с разделителями, содержащие ваши идентификаторы для каждого из трех списков, вы можете разделить их на таблицы отдельных значений, объединив их с таблицей чисел/подсчета (подробности в другом из моих ответов - SQL выбирает из данных в запросе, где этих данных еще нет в базе данных?). Отсюда вы можете написать это по строкам
SELECT L.*
FROM Library L
INNER JOIN CategoryADocs A
ON L.LibraryID=A.LibraryID
INNER JOIN ([CategoryA Derived table]) ADocs
ON A.CategoryAdocID=ADocs.CategoryADocID
LEFT JOIN (SELECT B.* FROM CategoryBDocs B
INNER JOIN [CategoryB Derived Table] BDocs
ON B.CategoryBdocID=BDocs.CategoryBDocID) B
ON L.LibraryID=B.LibraryID
LEFT JOIN ([Years Derived table]) Y
ON L.Year=Y.Year
WHERE
COALESCE(B.LibraryID,-1)=CASE WHEN Len(@BIDs) > 1 THEN B.LibraryID ELSE -1
AND COALESCE(L.Year,-1)=CASE WHEN Len(@Years) > 1 THEN L.Year ELSE -1
Я признаю, что это дольше и сложнее, но позволяет вам поместить всю логику в SQL без необходимости построения динамических запросов. Считаете ли вы, что это стоит сложности, я оставляю на ваше усмотрение!
person
eftpotrm
schedule
06.04.2010