Я создаю SQL- запрос на C #. Он будет отличаться в зависимости от некоторых условий, хранящихся в качестве переменных в коде.
string Query="SELECT * FROM Table1 WHERE 1=1 ";
if (condition1)
Query += "AND Col1=0 ";
if (condition2)
Query += "AND Col2=1 ";
if (condition3)
Query += "AND Col3=2 ";
Это работает, но проверка 1 = 1 не выглядит элегантной. Если бы я не использовал его, мне пришлось бы каждый раз запоминать и проверять, было ли уже добавлено ключевое слово «where» в запрос или нет.
Есть ли лучшее решение?
42 = 42
;-)Select 42
запросов, которые мы получали. (не забавно пытаться отследить источник)If I didn't use it, I would have to remember and check every time if "where" keyword was already added or not to the query
- Вот почему вы используете1 = 1
. Ядро базы данных все равно оптимизирует его, поэтому, хотя это может выглядеть некрасиво, это, безусловно, самый простой способ решить проблему.Ответы:
Сохраните условия в списке:
источник
ToArray()
.NET 4 нет необходимости, так как есть перегрузка, которая принимает любыеIEnumerable<string>
.Одно из решений - просто не писать запросы вручную, добавляя строки. Вы можете использовать ORM, например Entity Framework , а с LINQ to Entities использовать функции, предлагаемые языком и платформой:
источник
PrintResults(query)
запрос затем будет использоваться в dapper как запрос !!Небольшой перебор в этом простом случае, но я использовал код, похожий на этот, в прошлом.
Создать функцию
Используйте это так
Таким образом, если условия не найдены, вы даже не утруждаетесь загрузкой оператора where в запросе и сохраняете сервер sql микросекунду обработки предложения where нежелательной почты, когда он анализирует оператор sql.
источник
Есть еще одно решение, которое тоже может быть не изящным, но работает и решает проблему:
Для:
SELECT * FROM Table1
,SELECT * FROM Table1 WHERE cond1
AND condN
источник
WHERE
если нет предикатов; 1 = 1 существует специально, чтобы этого избежать.String query = "SELECT * FROM Table1";
иstring jointer = " WHERE ";
?WHERE
являютсяAND
ы быть помещены между условиями?string joiner
строку наstring joiner = " WHERE ";
и оставитьjoiner = " AND ";
строку в покое.Просто сделайте что-нибудь вроде этого:
Это безопасно для SQL-инъекций и, ИМХО , довольно чисто.
Remove()
Просто удаляет последнийAND
;Он работает как в том случае, если условия не были установлены, если одно из них было установлено, так и если было задано несколько условий.
источник
conditions != null
будет всегдаtrue
, когда вы инициализируете его""
(кроме C #"" == null
). Вероятно, это должен быть чек, еслиconditions
он не пустой… ;-)Просто добавьте две строчки сзади.
Например
станет
Пока
станет
=====================================
Спасибо, что указали на недостаток этого решения:
"Это может привести к сбою запроса, если по какой-либо причине одно из условий содержит текст" 1 = 1 И "или" WHERE 1 = 1 ". Это может иметь место, если условие содержит подзапрос или пытается проверить, есть ли столбец содержит этот текст, например. Возможно, в вашем случае это не проблема, но вы должны помнить об этом ... "
Чтобы избавиться от этой проблемы, нам нужно различать «основные» WHERE 1 = 1 и те, что из подзапроса, что очень просто:
Просто сделайте «главное» ГДЕ особенным: я бы добавил знак «$»
Затем еще добавьте две строки:
источник
"1=1 AND "
или" WHERE 1=1 "
. Это может быть в том случае, если условие содержит подзапрос или, например, пытается проверить, содержит ли какой-либо столбец этот текст. Может быть, в вашем случае это не проблема, но вы должны помнить об этом…Использовать это:
источник
QuerySub
мой взгляд, поиск по строкам не лучше и не хуже, чем использованиеwhere 1=1
хака. Но это продуманный вклад.... FROM SOMETABLE WHERE
; затемTrimEnd
фактически уменьшит это до... FROM SOMETABL
. Если бы это было на самом делеStringBuilder
(что должно быть, если у вас столько манипуляций со строками или больше), вы можете простоQuery.Length -= "WHERE ".Length;
.Если это SQL Server , вы можете сделать этот код намного чище.
Это также предполагает известное количество параметров, что может быть плохим предположением, когда я думаю о возможностях.
В C # вы должны использовать:
А затем на стороне SQL:
источник
Почему бы не использовать существующий построитель запросов? Что-то вроде Sql Kata .
Он поддерживает сложные условия, объединения и подзапросы.
он работает с Sql Server, MySql и PostgreSql.
источник
Самое быстрое буквальное решение вопроса, которое я могу придумать, это следующее:
Конечно, это не выглядит элегантным, и я бы отослал вас к рекомендации CodeCaster по использованию ORM. Но если вы подумаете о том, что это здесь делает, вы действительно не беспокоитесь о том, чтобы «тратить» 4 символа памяти, и компьютер действительно быстро переместит указатель на 4 позиции.
Если у вас есть время научиться использовать ORM, это действительно может окупиться. Но что касается этого, если вы пытаетесь предотвратить попадание этого дополнительного условия в базу данных SQL, это сделает это за вас.
источник
В зависимости от условия в запросе можно использовать логическую логику. Что-то вроде этого :
источник
Мне нравится свободный интерфейс конструктора строк, поэтому я сделал несколько ExtensionMethods.
источник
ИМХО, я считаю, что ваш подход неверен:
Запрос базы данных путем объединения строк НИКОГДА не является хорошей идеей (риск внедрения SQL и код может легко сломаться, если вы внесете какие-то изменения в другом месте).
Вы можете использовать ORM (я использую NHibernate ) или, по крайней мере, использовать
SqlCommand.Parameters
Если вы абсолютно хотите использовать конкатенацию строк, я бы использовал
StringBuilder
(это правильный объект для конкатенации строк):Как последняя мысль,
Where 1=1
это действительно некрасиво, но SQL Server все равно оптимизирует его.источник
SELECT * FROM Table1 WHERE AND Col1=0
не кажется правильным, и в этом весь смыслWHERE 1=1
.Dapper SqlBuilder - довольно хороший вариант. Он даже используется в производстве на StackOverflow.
Прочтите об этом в блоге Сэма .
Насколько мне известно, он не является частью какого-либо пакета Nuget, поэтому вам нужно скопировать и вставить его код в свой проект или загрузить исходный код Dapper и собрать проект SqlBuilder. В любом случае вам также потребуется ссылаться на Dapper для
DynamicParameters
класса.источник
Я вижу, что это все время используется в Oracle при создании динамического SQL в хранимых процедурах. . Я использую его в запросах при изучении проблем с данными, чтобы ускорить переключение между различными фильтрами данных ... Просто закомментируйте условие или легко добавьте его обратно.
Я считаю, что это довольно распространено и достаточно просто для понимания тем, кто просматривает ваш код.
источник
Реализация методами расширения.
источник
Используя
string
функцию, вы также можете сделать это следующим образом:Мне лично кажется, что в конце условный элемент (элементы) легко удалить, поскольку его положение легко предсказать.
источник
Я подумал о решении, которое, возможно, более читабельно:
Я просто не уверен, будет ли интерпретатор SQL также оптимизировать
Col1 = Col1
условие (печатается, когдаcondition1
ложно).источник
Вот более элегантный способ:
источник
Как уже было сказано, создание SQL путем конкатенации никогда не было хорошей идеей . Не только из-за SQL-инъекции. В основном потому, что он уродлив, сложен в обслуживании и совершенно не нужен . Вы должны запустить свою программу с трассировкой или отладкой, чтобы увидеть, какой SQL она генерирует. Если вы используете QueryFirst (отказ от ответственности: я написал), неприятный соблазн исчезнет , и вы сможете сразу приступить к выполнению этого в SQL.
На этой странице подробно описаны параметры TSQL для динамического добавления предикатов поиска. Следующая опция удобна в ситуациях, когда вы хотите оставить выбор комбинаций предикатов поиска своему пользователю.
QueryFirst дает вам C # null в db NULL, поэтому вы просто вызываете метод Execute () с нулевыми значениями, когда это необходимо, и все это просто работает. <Мнение> Почему разработчики C # так неохотно делают что-то на SQL, даже когда это проще? Уму непостижимо. </opinion>
источник
Многие говорят, что для более длительных этапов фильтрации лучше всего подходит StringBuilder.
в вашем случае я бы пошел с:
источник
Лаконично, элегантно и мило, как показано на изображении ниже.
источник