Pull to refresh

Comments 26

Все логично. В Oracle тоже запрос с использованием динамических названий таблиц или других объектов сначала надо собрать в виде текста, а потом исполнить его в процедуре EXECUTE_IMMEDIATE.
Да я согласен, ничего хитрого тут нет, но такие вопросы возникают с завидной регулярностью, по-этому решил описать.
Создание динамических запросов оправдано только если они выполняются редко или вообще один раз. Иначе это неоправданная нагрузка на парсер. К тому же динамические запросы являются потенциальной дыркой для SQL injection.
Ну если инъекция добралась до автособираемого sql-я, то это дыра в разработчике.
Для MS SQL, например, это не так. Его оптимизатор позволяет сохранять планы даже для динамического SQL. План, грубо говоря — это распарсенное до атомарных операций выражение SQL, готовое к выполнению. После первого парсинга план помещается в кэш, после чего для его использования не нужно нагружать парсер, достаточно просто взять из кеша нужный запрос и подставить параметры.

Понятно, что параметризовать именем таблицы нельзя, зато можно держать планы для всех таблиц в БД (их редко бывает больше сотни-другой) для среднего проекта.

С другой стороны, наличие динамического sql, как правило, говорит о том, что что-то не так в датском королевстве вы используете БД не по назначению, заставляя ее выполнять задачи сервера приложений.
Вон оно как.

А я тупой думал, что когда из клиента запрос на сервер шлю — сервер его сначала парсит и только потом выполняет. И вообще сдуру думал, что любой запрос, если он не в хранимой процедуре, для сервера динамический и его парсить надо.

Спасибо за просветление.

Так все таки, вообще нельзя с клиента запросы слать или они пока до сервера доходят волшебным образом парсятся?
UFO just landed and posted this here
а то даже может и суффикс =)
> DECLARE template,archive_template VARCHAR(50);

тут надо archive_prefix вместо archive_template, опечатка вроде :)
и еще,
SET @archive_query:=CONCAT
(«CREATE TABLE »,template," ENGINE=ARCHIVE AS
(SELECT * FROM ",current_table," )");

Тут обязательно после CONCAT-а нужно поставить открывающую скобу на этой же строке, иначе mysql будет ругаться, что мол нет такой процедуры CONCAT
Народ, если не сложно, помогите плз разобраться как правильно сделать выборку, в инете своего случа не нашёл:

Рабочий пример:
SELECT column_name(s)
FROM table_name1
LEFT JOIN table_name2
ON table_name1.column_name = table_name2.column_name
WHERE table_name1.column_description LIKE table_name2.column_description2

Нада в LIKE добавить частичное включение, т.е. LIKE %table_name2.column_description2%
Если у нас таблички t1, t2 для наглядности их JOIN без условия
select name1,d1,name2,d2 from t1 left join t2 on t1.name1=t2.name2

+---------+------+---------+----------+
| name1   | d1   | name2   | d2       |
+---------+------+---------+----------+
| name1   | d1   | name1   | x_d2_x   |
| name11  | d11  | name11  | x_d11_x  |
| name111 | d111 | name111 | x_d111_x |
+---------+------+---------+----------+

То запрос будет выглядить так
select name1,d1,name2,d2 from t1 left join t2 on t1.name1=t2.name2 where LOCATE(d1,d2)

Логика тут такая LOCATE() возвращает позицию вхождения подстроки. Если внутри d2 содержится d1, то мы получим положительное число.
Получим соотвественно:
+---------+------+---------+----------+
| name11  | d11  | name11  | x_d11_x  |
| name111 | d111 | name111 | x_d111_x |
+---------+------+---------+----------+

То есть запись где было d2=x_d2_x была отброшена.
спасибо, наглядно и доходчиво)
Вот если бы результат исполнения хранимых процедур можно было бы использовать в том же запросе, которых их вызывает, в виде таблицы, например, то это было бы дело.

А так приходится использовать для сложной логики выборок хранимые функции, которые замедляют исполнение запросов примерно в 10 раз.
Можно дергать процедуру и выгружать данные в темповую таблицу, конечно не очень красиво, но вполне рабочий вариант.
А какие проблемы.
Если в результате выполнения запроса получается выборка с одним полем — GROPUP_CONCAT на него INTO myvar.
Дальше собрать запрос CONCAT'ом и выполнить.
Если одно значение просто его в переменную.
Если набор строк с несколькими полями, то IMHO лучше на клиента вернуть и там обработать, а по результатам новый запрос отправить. Тут нередко и кэш может помочь.

С темповой таблицей поаккуратнее, она ведь может и на диске образоваться, естественно в самый подходящий момент, в неподходящий, когда нагрузки нет — ей в оперативке места хватит. :)
UFO just landed and posted this here
Ну их нафиг такие извраты, я лучше в php напишу что нибудь вроде: query(«SELECT FROM ?t WHERE ....», $table) :) Всяко удобнее))
Действительно удобней. Но здесь задача стояла как такое сделать средствами MySQL
Так удобно, но все же надо стараться избавляться от динамических запросов. Их минус в том, что компилируются они при каждом вызове, тогда как обычные компилируются только при создании хранимой процедуры.
Ну почему же, они компилируются при PREPARE. Можно один раз PREPARE и кучу раз EXECUTE.

Сам по себе это — инструмент, который можно использовать. И хорошо, что он есть. А уж как его использовать — решать разработчику.
UFO just landed and posted this here
Sign up to leave a comment.

Articles