Без реальных примеров перед глазами, говорить бесполезно.
Итак, запрос из реального проекта, коих сейчас много:
PHP:
$queryCondition = '';
if ($tagWord!="") {
$listId = ClientTag::GetContentByTag($tagWord);
if (count($listId)>0) {
$queryCondition = " AND A.aId in (".implode(',', $listId).")";
}
}
if(isset($params['genre']) && trim($params['genre']) != '') {
$genres = htmlspecialchars(trim($params['genre']),ENT_QUOTES);
$genres = explode(';',$genres);
if(count($genres) > 0) {
$queryCondition .= ' AND (';
foreach($genres as $genre) {
if(trim($genre) != '')
$queryCondition .= "AG.GenreId = (SELECT gId FROM Genre WHERE gName = '" . $genre . "' LIMIT 1) OR ";
}
$queryCondition = substr($queryCondition,0,-3);
$queryCondition .= ') ';
}
}
$query = "SELECT COUNT(*) as cnt
FROM Artist A
LEFT JOIN ArtistGenre AG ON A.aId = AG.ArtistId
INNER JOIN Client C ON C.cId = A.ClientId AND C.cEnabled = 1 AND C.cActivated = 1
WHERE A.aEnabled=1 and A.aIsExpert=0
".( $queryCondition != '' ? $queryCondition : '' );
Это ещё не самый сложный вариант, есть и посложнее. И сложность эта не в самом запросе, а в его построении. Есть запросы с десятками условий, и не только в предложении "where", но и с подключением разных таблиц с агрегированными данными.
Итого, минусы работы с SQL запросом как со строкой:
1. сложно его вконце концов заставить работать, так как постоянно появляются ошибки синтаксиса при отрабатывании различных условий. Сработала другая ветвь условия, и появилась какая нибудь лишняя скобка, и начинаешь отслеживать весь запрос от начала до конца.
2. трудно разнести построение запроса на несколько логически разделённых метода (которые, кстати, могут использоваться для нескольких запросов). Приведенный выше пример занимает всего 30 строчек, но, чем больше условий построения запроса, тем больше разрастается метод. Выделить в таком методе логически независимые части, да ещё с учётом первого пункта, практически невозможно.
3. строчка WHERE gName = '" . $genre . "' говорит сама за себя. Нужно постоянно помнить о подготовке данных перед передачей их в запрос. В СКЛ билдере об этом можно не беспокоиться.
4. Кто назовёт это не лапшёй, пусть первый бросит в меня камнем
Мне приходилось работать с разными SQL билдерами. У большинства из них схожие принципы построения запроса. После первого из них, на освоение других у меня уходило не больше 3-4 написанных запроса.
А вот другой пример запроса, по сложности построения превосходящий предыдущий:
PHP:
$query = ezcDbInstance::get()->createSelectQuery();
$subquery = $query->subSelect();
$subquery->select($query->expr->count('*'))
->from('ClientDiscussion')
->where(
$query->expr->lAnd(
$query->expr->eq('cdObject', $query->bindValue('blog')),
$query->expr->eq('cdObjectId', 'bpId'),
$query->expr->eq('cdEnabled', 1),
$query->expr->eq('cdDeleted', 0)
)
);
$query->from('Client')
->innerJoin('Artist', 'Artist.ClientId', 'cId')
->innerJoin('ArtistBlog', 'aId', 'ArtistId')
->innerJoin('BlogPost', 'abId', 'BlogId');
if ('month' == $this->currentTab) {
$query->leftJoin('BlogPostRatingMonth', 'bpId', 'BlogPostId');
} elseif ('all' == $this->currentTab) {
$query->leftJoin('BlogPostRating', 'bpId', 'BlogPostId');
} else {
$query->leftJoin('BlogPostRatingWeek', 'bpId', 'BlogPostId');
}
$query->select('aId', 'bpId', 'aSite',
$query->alias('bpContent', 'text'),
$query->alias('bpTitle', 'title'),
$query->alias('bpCreatedAt', 'time'),
$query->alias('aName', 'nickname'),
$query->alias('aHasAvatar', 'avatara'),
$query->alias('BlogPostRatingNormalized', 'rate'),
$query->alias($subquery, 'comments')
)
->where(
$query->expr->lAnd(
$query->expr->eq('abEnabled', 1),
$query->expr->eq('bpEnabled', 1)
)
)
->orderBy('rate', ezcQuerySelect::DESC)
->limit(self::ITEMS_PER_PAGE);
Как вы могли заметить, здесь используется SQL билдер из библиотеки ezc. Надо сказать, не самый "немногословный" билдер, но даже на нём строить запросы легче.
А
это SQL билдер, которым я обычно пользуюсь, с более лаконичным синтаксисом.
у нас вообще нет "прямых" запросов к бд - весь "скл" в хранимых pl/sql-процедурах/функциях
Тоже вариант, но, блин, сопровождать такой код жутко неудобно. Да и строить запрос с учётом различных условий сложнее, это всё-таки не язык программирования.