какие проблемы? никаких проблем! да ладно, я могу много чего представить )) неужели предыдущий пост так навязывает такое мнение? Просто эти все разговоры переходят в такой флейм, фактов нету. Конечно то что ты высказал свое мнение за это тебе плюс. Аргументы эти вполне имеют место. Но вот я попросил большего и всё, начинаются какие-то разборки с непонятными обвинениями о представлениях, а фактов опять же нет. Такое ощущение что я тут на всех кидаюсь и готов горло грызть за свою статью. На самом деле я хочу узнать правду. Я не могу проверить всё под нагрузкой, которая запрашивается вашими требованиями. У меня нет просто возможности либо я не знаю как. Я не знаю где прочитать про этот таинственный кешь подготовленных запросов, потому что там где я мог прочитать я это сделал, другие места я не нашел.
Ну я и не говорил что это сложность или невозможно. Но кол-во кода, которое нужно написать, что бы динамически составляемый запрос через prepared statments правильно составлялся далеко превышает собой те 5-7 строк линейного кода. А вам ведь нужно же ещё контролировать что есть int, что есть строка что бы данные правильно составлялись. Полагаться на типы переменных вы не можете по той простой причине, что из большинства внешних источников всё приходит как string, т.е. разметка на инты, флоаты и строки делается руками в любом случае. Я просто не вижу смысла городить кучу кода, когда это решается конкатенацией в пару строчек. Чем проще, тем лучше. KISS помните такой? Это как раз тот случай, когда идёт противоречие этому принципу. Можно конечно сейчас заморочиться, сделать пример с и без prepared statments, долго спорить. Только вот вопрос: зачем? Мне кажется у вас уже достаточно опыта что бы понимать ту очевидность, о которой я вам говорю. В конце концов если уж совсем не понимаете, то попробуйте на практике что-ли. Я попробовал. Получается дольше, громоздко и местами совсем не удобно. Это не голословное утверждение, это факт из документации по MySQL.
Они просто перпендикулярны сборке запроса. Сборка сама по себе, параметризированные запросы сами по себе. Именно поэтому данный факт - не аргумент. Костян Я не могу однозначно утверждать, что параметризированные запросы однозначно и всегда лучше. У меня просто нет этой информации, но я четко знаю - что все совсем не просто, и ты в своих тестах упустил многие важные моменты. Я более чем допускаю что в запросах вида getById никакой PS сильно не нужен и, возможно, во многом даже снижает производительность. Но вот у меня сейчас стоит на повестке дня вытащит данные из цепочки в 5ть таблиц. Да можно сделать 5ть разных запросов, а можно собрать и более сложную конструкцию и вот ни разу не очевидно - что будет быстрее в этом случае. Ты хочешь чего-то большего? Большего - это взять и провести тесты вместо тебя. Извини, но времени у меня на это пока нет. Да в честь чего? Для сборки нет никакой разницы между prepared statments и обязательным mysql_real_escape_string. Оверхедом будет биндинг массива параметров в размере целых 3 строк, включая закрывающую скобку цикла. Если оно прошло валидацию, то мне плевать в каком типе и под каким соусом оно пойдет в запрос. Дарю рабочий вариант [sql]SELECT * FROM offer WHERE offer_price > '1700.00';[/sql] 1700.00 - это decimal если что. И я пробовал и пришел к тому, о чем сейчас говорю - Сборка сама по себе, параметризированные запросы сами по себе. - они никак не зависят друг от друга. А разница в том, что пробовали мы сильно разные вещи. Вы просто не работали с действительно сложной логикой. Все ваши запросы это максимум join 2-3 таблиц для получения дерева. И можно сколько угодно рвать на груди тельняшку с хайлоадом... Но когда у вас десяток параметров в запросе (да и их число может быть переменным), то конкатенация это далеко не KISS. Поэтому я тоже во многом раньше не видел смысла, но со временем начинаешь смотреть на все несколько иначе, ну или не начинаешь... P.S. флоппик все же не зря поднимал тему Учимся думать
Что значит какую задачу решаю? Динамическая сборка запроса у меня служит для быстрого прототипирования, т.е. когда запросы еще не устоявшиеся и могут часто меняться. А до уровня PS я обычно не опускаюсь, это делается просто раз и навсегда в одном месте DBAL. Необходимости сверхоптимизации моих запросов у меня просто не возникало (если бы возникало, то у меня на руках уже были бы тесты с результатами с PS и без них в различных конфигурациях).
а что плохо, когда допустим у меня запросы собираются динамически, лучше сделать перебор всех возможных вариантов? или как...
не знаю чё вы завелись, я например и там и там использую плейсхолдеры... разница лишь в vsprintf и call_user_func_array, а то, что запрос динамически или не динамически собирается какая разница. В любом случае прейсхолдеры позволяют автоматом обработать параметры.
Что значит плохо? Что значит перебор всех возможных вариантов? В большинстве случаев запрос вполне конкретен и его можно записать одной строчкой. Дело в том, что на этапе разработки мне удобнее управлять всем кодом из одного места и меняя входящие параметры менять сразу и запрос и выводимые поля на форме и т.д. например Для меня это просто особенность работы в одиночку. Как видишь, некоторым удобнее конкатенировать строки. Что впрочем вполне логично, для запроса с 1-2 параметрами. Но это не является истиной в последней инстанции, как тут пытаются донести.
Simpliest ну тогда не надно говорить что параметризация живёт отдельно от запроса =) а значит нужно как-то решать эту задачу в целом а не разбивать на контексты
Называется слышал звон, да не знаю где он. Перечитай еще раз то, о чем я писал. Специально повторю Сборка сама по себе, параметризированные запросы сами по себе
Simpliest Вам говорят о запросах, которые динамически генерируются и для которых использование prepared statments получется усложнённым. Простой пример: SELECT * FROM table ORDER BY id DESC LIMIT 0, 20 Если передали ID, то в запрос добавляется WHERE SELECT * FROM table WHERE id = 25 ORDER BY id DESC LIMIT 0, 20 Как это будет выглядеть с prepared statments? С конкатенацией легко и просто.
Тему может и поднимал не зря, зато результаты близкие к нулевым. Psih, прости, но твой пример выдуман. Это разные запросы, и скорее всего будут выводится в разных местах. Это во первых. А во вторых - запрос будет собиратся так же. только вместо непосредственно значения 25 там будет плейсхолдер. Именно об этом и говорил Сергей, когда говорил что процесс сборки запроса и подстановки происходят паралельно.
ну так правильно. Сборка никак не связана с парамтризированными запросами. Можно собирать запрос с параметризированными запросами и без них. Обычная ситуация когда запрос имеет составляющие сборки: тип запроса, поля выборки, источник, соединения, условия, группировка, сортировака. Каждый кусок даёт свою часть строки запроса. В каждом куске могут быть переменные запроса, которые могут вставляться как через PS, так и обычной конкатенацией. Или вы конкатенацию производите в месте самой переменной? оО Дело не в этом, дело в том, что мы ищем до чего бы доебаться, а не правду
Psih PHP: <?php $_POST = array( 'brand' => 'KU\KU', 'lamp' => "Don't" ); // ключ - id входных данных с формы // значение - условие $allowed = array( 'brand' => 'brand = ?', 'lamp' => 'lamp = ?', 'status' => 'status = ?', 'supplier_id' => 'supplier_id = ?', 'product_id' => 'product_id NOT LIKE ?', 'location_id' => 'location_id LIKE ?', 'company_id' => 'company_id LIKE ?' ); $sql = 'SELECT * FROM table1'; // создаем массив условий только для тех значений которые у нас есть и во входных данных, и в массиве с критериями var_dump(_makeQuery($sql, $_POST, $allowed)); function _makeQuery($sql, $values, $allowed) { $clause = array(); foreach ($values as $key => $val) { if (array_key_exists($key, $allowed)) { if (null != $val) { $clause[$allowed[$key]] = $val; } } } if ($clause) { $sql .= ' WHERE '; // эскейпим и подставляем значения в плейсхолдеры array_walk($clause, create_function('&$value, $condition', '$value = str_replace("?", "\'" . mysql_real_escape_string($value) . "\'", $condition); return true;')); // итоговое условие $sql .= implode(' AND ', $clause); } return $sql; } С PS это будет выглядеть немного иначе. PHP: <?php $_POST = array( 'brand' => 'KU\KU', 'lamp' => "Don't" ); // ключ - id входных данных с формы // значение - условие $allowed = array( 'brand' => 'brand = ?', 'lamp' => 'lamp = ?', 'status' => 'status = ?', 'supplier_id' => 'supplier_id = ?', 'product_id' => 'product_id NOT LIKE ?', 'location_id' => 'location_id LIKE ?', 'company_id' => 'company_id LIKE ?' ); $sql = 'SELECT * FROM table1'; var_dump(_buildStmt($sql, $_POST, $allowed)); function _buildStmt($sql, $data, $allowed) { $mysqli = new mysqli('host', 'user', 'password', 'database'); $valuesToBind = array('typedefstring' => null); $clause = array(); foreach ($data as $key => &$val) { if (array_key_exists($key, $allowed)) { if (null != $val) { $clause[] = $allowed[$key]; $valuesToBind['typedefstring'] .= 's'; $valuesToBind[] = &$val; } } } if ($clause) { $sql .= ' WHERE '; $sql .= implode(' AND ', $clause); } if(($stmt = $mysqli->prepare($sql))) { if ($clause) { call_user_func_array(array($stmt, 'bind_param'),$valuesToBind); } } return $stmt; }
PHP: <? $db->Query("SELECT * FROM tbl WHERE ?arr",array_intersect_key($_POST,$allowed)); ?> ну или PHP: <? function sqlBind($arr,$del="AND"){ $res=array(); foreach($arr as $k=>$v){ $res[]="`".$k."`='".mysql_real_escape_string($v)."'"; } return implode(" ".$del,$res); } $db->Query("SELECT * FROM tbl WHERE ".sqlBind(array_intersect_key($_POST,$allowed))); ?>
Mr.M.I.T. На PHP: <?php $_POST = array('id' => ''); $allowed = array('id' => 'id = ?'); Исправляй ошибку у себя.
Simpliest это я к примеру. у меня для таких целей используется идея макросов Котерова хм, ты о какой ошибке?
PHP: <form method="post" action=""> <input type="text" name="id"/> <input type="submit"/> </form> <?php var_dump($_POST); Какого рода выполнится запрос у тебя? А форма поиска(например) была ведь пустая.