Mysqli. Подготовленные выражения
1.
KOZZ (01.08.2011 / 07:52)
Салют.
В общем хочу освоить все это дело, но после прочтения мануалов все равно остались некоторые вопросы.
1) Их нужно использовать только при записи в БД, или при select запросах тоже?
2) Будет ли работать эта штука, если я пользуюсь таким синтаксисом insert запросов:
$db->query("insert into `table` set `field`='value',`field2`='value2';")
Заранее спасибо, по ходу появятся еще вопросы, пока что прошу вашей помощи с этими
2.
KOZZ (02.08.2011 / 22:15)
Чего - то вообще глухо
3.
Александр (03.08.2011 / 19:50)
попал в нужную тему )) именно подготовленные выражения ))
возник вопрос.
function query( $sql )
{
$rez = $this->prepare( $sql );
if ( $this->error )
error( 'Ошибка: ' . $this->error );
$rez->execute();
return $stmt;
}
эта функция не выполняется и я не могу понять почему.
сразу скажу что это паблик функция расширенного класса mysqli
в pdo это работает а тут почемуто не выполняется
4.
Виталий (03.08.2011 / 20:04)
3.
rastoman,
<?php
function query( $sql )
{
$stmt = $this->prepare( $sql );
if ( $this->error )
error( 'Ошибка: ' . $this->error );
$stmt->execute();
return $stmt;
}
?>
5.
Виталий (03.08.2011 / 20:15)
у меня так
6.
Валерий (03.08.2011 / 21:14)
1. Подготовительные запросы лучше везде использовать, где в строку запроса переменные вставляются.
Единственное где у меня почему то не работают они это после слова LIMIT в запросе..
Т.е. не могу написать так
... LIMIT ?,?;
Фиг знает почему.. Поэтому вставляю переменные в запрос по старинке.. Использую pdo
Кто знает в чем касяк ответьте.
7.
KOZZ (03.08.2011 / 21:22)
6.
valerik, я просто не дорубаю немного эти подг.выражения, это типа фильтр чтоли такой новый от inj изобрели, или что?
что сделает с кавычками например эта фишка, заслэшит чтоли?
8.
Александр (03.08.2011 / 22:47)
6.
valerik, у всех так. И в роторе тоже.
9.
delete (04.08.2011 / 01:03)
7.
eGo Отвертка в ухе, фишка не только в безопасности, а еще в том что можно проводить операции на уровне сервера. Ну собственно эт я сужу по аналогии с pdo
Добавлено через 01:51 сек.
а безопасно ибо ты прописуешь строгий сценарий, и вставить в запрос например левый скул запрос уже нельзя, ты изначально скомпилировал весь sql сценарий.
10.
ramzes (04.08.2011 / 02:15)
eGo Отвертка в ухе (3 Августа 2011 / 21:22)
6. valerik, я просто не дорубаю немного эти подг.выражения, это типа фильтр чтоли такой новый от inj изобрели, или что?
что сделает с кавычками например эта фишка, заслэшит чтоли?
сначала уходит запрос, анализируется и сохраняется, потом данные к нему, выполнение.
повторная отправка уже идет без запроса, только данные, экономия времени и трафика мускул, снижение нагрузки, (при неверном подходе можно добиться обратного эффекта), а фильтрация это только дополнительная плюшка
11.
KOZZ (04.08.2011 / 08:22)
10.
ramzes, ясно с этим.
а что входит в фильтрацию: просто прослэшатся данные, или будет что - то еще?
12.
Atmas (05.08.2011 / 01:46)
В общем-то подготовительные выражения нужно использовать при записе в БД, а не на выводе. У меня получился такой вердикт или я ошибаюсь?
Кстати, имеется поле `text`, его не выводит...
13.
Петр (05.08.2011 / 15:57)
Хоть где. А вообще их имеет смысл использовать, по-моему, если запрос выполняется несколько раз.
14.
Андрей (05.08.2011 / 16:24)
Данные вроде не слешатся, так и записывает. Но инъекции не проходят. Просто выводит так как есть.
15.
KOZZ (05.08.2011 / 16:40)
14.
Фанат, спасибо, наконец - то получил ответ на вопрос
а использовать нужно только при вводе данных в бд, или при выводе тоже?
16.
Atmas (05.08.2011 / 16:44)
13. Да нет, вот как раз таки при выводе думаю не стоит оно того.
Фанат верно сказал, инъекции не будет, а вот при выводе возможна xss. То есть прийдется все равно фильтровать вывод.
Да и просто query() + фильтрация будет побыстрей prepare(), execute() + фильтрация...
17.
KOZZ (05.08.2011 / 16:51)
16.
Atmas, фильтрация это не единственный плюс
18.
Atmas (05.08.2011 / 16:57)
eGo Мистер Винтаж (5 Августа 2011 / 16:51)
16. Atmas, фильтрация это не единственный плюс
это понятно) но все же для вывода ИМХО не подходит.
Или я заблуждаюсь?
19.
KOZZ (05.08.2011 / 17:01)
18.
Atmas, почему нет?
20.
Валерий (05.08.2011 / 17:05)
Причём здесь ввод или вывод? Хоть где имеет смысл использовать.. например
<?php
$res=$db->prepare("SELECT FROM table1 WHERE id=?;");
while(какой то цикл)
{
$id=какое то число;
$res->execute(Array($id));
}
?>
ИЛИ
<?php
while(какой то цикл)
{
$id=какое то число;
$res=$db->query("SELECT FROM table1 WHERE id='$id';");
}
?>
В первом случае выражение подготавливается один раз, а потом просто отсылаются данные, без самого запроса.
Во втором случае каждый раз формируется запрос заново.
21.
delete (05.08.2011 / 17:17)
чет я не пойму, как это вы не нашли нормальной инфы по этому вопросу, набираю в поиске, и первая ж ссылка все доступно обьясняет, и про виды подготовленых выражений, и как оно работает и зачем нужно.
http://phpclub.ru/detail/article/mysqli
22.
KOZZ (05.08.2011 / 17:19)
21.
Денис Одинец, я видел эту статью, хочется больше практических советов
23.
delete (05.08.2011 / 17:28)
22.
eGo Мистер Винтаж, а PDO интерисуешся? я вот чет уже не пойму, можит нафиг её, раз в MySQLi все есть + те фишки что и в pdo, да и скорости одинаковые. А если юзать только один вид баз данных, то все остальные фишки и ненужны. Запросы тем болие не подойдут к SQLite, там свои ограничения.
24.
KOZZ (05.08.2011 / 17:29)
23.
Денис Одинец, PDO не интересуюсь, достаточно и mysqli, да как - то и проще это для меня.
25.
Titov (05.08.2011 / 20:42)
я так понимаю что сервер mysql тот же что и для обычного мускула, всё mysqli заключаеться в правильном построении запроса в эту самую бд, и вот хотелось бы на примере чтоб кто-то продемонстрировал плюсы обработки сервером бд запросов с mysqli по сравнению с обычным mysql, касаеться только тех кому это сделать не в лом будет, выглядеть примерно должно так:
строите запрос для создания бд с таблицами с некоторыми даными, можно просто с рядом чисел от 1 до 10000 далее формируем запрос на обычном мускуле и на другой странице на мускуле лайт, ставите генерацию обоих страниц, выкладываете коды и таблицу в архиве чтоб каждый мог сам это дело обсосать. Повторюсь кому не в лом.
26.
Atmas (05.08.2011 / 21:37)
20.
valerik, $res->execute(Array($id)); PDO
Да и лично у меня запросов в циклах не встречается)
<?php
$mysqli = new mysqli('localhost', 'user', 'pass', 'world');
if (mysqli_connect_errno()) {
printf("Ошибка соединения: %s\n", mysqli_connect_error());
exit();
}
//prepare, execute
$start_array = explode(" ",microtime());
$start_time = $start_array['1'] + $start_array['0'];
$res = $mysqli->prepare("SELECT name FROM users WHERE id=?;");
for($i=1;$i<501;$i++) {
$id = $i;
$res->bind_param('i', $id);
$res->execute();
$res->bind_result($name);
$res->fetch();
echo $i.') ', $name, '<br/>';
}
$end_time = microtime(); $end_array = explode(" ",$end_time);
echo round((($end_array['1'] + $end_array['0']) - $start_time),4).'сек.<hr />';
//query
$start_array2 = explode(" ",microtime());
$start_time2 = $start_array2['1'] + $start_array2['0'];
for($i=1;$i<501;$i++) {
$id = $i;
$res = $mysqli->query("SELECT name FROM users WHERE id=$id")->fetch_assoc();
echo $i.') ', $res['name'], '<br/>';
}
$end_time2 = microtime(); $end_array2 = explode(" ",$end_time2);
echo round((($end_array2['1'] + $end_array2['0']) - $start_time2),4).'сек.<hr />';
?>
почему то, второй выходит быстрее...
27.
ramzes (05.08.2011 / 22:12)
26.
Atmas, он и должен быть быстрее, не злоупотребляйте, больший функционал шаблонов требует и большемвремени. Если оно не надо то и не используйте
28.
Atmas (05.08.2011 / 22:33)
27.
ramzes, я только если на ввод инфы использовать буду, пока надобности на выводе не нашел.
Кстати, как я понял, ты подготовленные выражения не используешь? Или же нет?
Мне б просто узреть пример грамотного использования хехе
Ну за исключением
$res = $mysqli->prepare("INSERT INTO table SET field=?;");
$a = 'trololo';
$res->bind_param('s', $a);
$res->execute();
$a = 'ololo';
$res->bind_param('s', $a);
$res->execute();
То в мануалах не нашел.
На ПДО видел побольше и поинтересней примерчеги...
29.
Titov (05.08.2011 / 22:51)
26 у меня первый быстрее всех
<?php
list($msec, $sec) = explode(chr(32), microtime());
$headtime = $sec + $msec;
define("MYSQLHOST", "localhost");
define("DBNAME", "world");
define("DBUSER", "root");
define("DBPASS", "");
@$dbcnx = mysql_connect(MYSQLHOST, DBUSER, DBPASS);
if (!$dbcnx)
{
$mysql_error = mysql_error();
exit();
}
for($i=1;$i<501;$i++) {
$id = $i;
$q = mysql_query("SELECT `name` FROM `users` WHERE `id` = ?;");
@$fsize = mysql_result($q,0,'name');
echo $i.') ', $name, '<br/>';
}
list($msec, $sec) = explode(chr(32), microtime());
echo "[".round(($sec+$msec)-$headtime,5)."] sec<br/>\n";
/////////////////
$mysqli = new mysqli('localhost', 'root', '', 'world');
if (mysqli_connect_errno()) {
printf("Ошибка соединения: %s\n", mysqli_connect_error());
exit();
}
//prepare, execute
$start_array = explode(" ",microtime());
$start_time = $start_array['1'] + $start_array['0'];
$res = $mysqli->prepare("SELECT name FROM users WHERE id=?;");
for($i=1;$i<501;$i++) {
$id = $i;
$res->bind_param('i', $id);
$res->execute();
$res->bind_result($name);
$res->fetch();
echo $i.') ', $name, '<br/>';
}
$end_time = microtime(); $end_array = explode(" ",$end_time);
echo round((($end_array['1'] + $end_array['0']) - $start_time),4).'сек.<hr />';
//query
$start_array2 = explode(" ",microtime());
$start_time2 = $start_array2['1'] + $start_array2['0'];
for($i=1;$i<501;$i++) {
$id = $i;
$res = $mysqli->query("SELECT name FROM users WHERE id=$id")->fetch_assoc();
echo $i.') ', $res['name'], '<br/>';
}
$end_time2 = microtime(); $end_array2 = explode(" ",$end_time2);
echo round((($end_array2['1'] + $end_array2['0']) - $start_time2),4).'сек.<hr />';
?>
30.
Titov (05.08.2011 / 23:04)
на 30000 запросов в бд пробовал
1 - 5.19068 сек
2 - 8.0344 сек.
3 - 9.1922 сек.
31.
ramzes (05.08.2011 / 23:59)
29.
Тitov, я просто скопировал твой код не глядя, как ты тестировал если он не рабочий?%)
32.
ramzes (06.08.2011 / 00:15)
mysql_query: [0.54703] sec
mysqli prepare: [0.4834сек.]
mysqli_query: [0.5797сек.]
5000 запросов, в итоге, 1 и 3 это полные 5к запросов, а 2 это лишь 5к отправок параметров одного и того же запроса, не вижу вообще прироста.. мизер, с учетом что в "живом" коде 5к запросов вообще не может быть =)
33.
Александр (06.08.2011 / 00:27)
32.
ramzes,
ну не все дело в скорости. а если 100человек на сайте да по 5тыш запросов? не ляжет сервер? а так всего 100 запросов
34.
delete (06.08.2011 / 00:56)
33.
rastoman, методов увеличения живучести серверов кучи. Эт не вопрос к кодерам, это вопрос к сис.админам. Там свои технологии. Не только все завязано на оптимизации запросов к базам данных. Есть еще кучи факторов, мож даж и куда болие важных.
35.
ramzes (06.08.2011 / 00:58)
33.
rastoman, что бы 100 человек генерировало 5к запросов, надо так на***кодить что бы на всех страницах было по 50 запросов%) и шаблоны тут помогут не сильно, во первых (см на результаты) экономия грошовая что то, а во вторых, все 50 запросов должны быть под одним шаблоном, иначе разница станет еще меньше, а то и вовсе проигрыш пойдет;)
_______
примерно по этому я их не использую, не нашел им применения, или я что то упустил изучая их
___________
кстати не ляжет)) я два раза в день гоняю 10к запросов на одной странице =) 2-4 сек, в зависимости от настроения сервака (не денвер, живой сайт)
36.
ramzes (06.08.2011 / 01:40)
mysql_query: [0.56801] sec
mysqli_query: [0.5701сек.]
mysqli prepare: [0.504сек.]
mysqli_real_query: [0.5536сек.] <- предпочитаю этот метод
mysql_query: [0.56453] sec
mysqli_query: [0.58сек.]
mysqli prepare: [0.5074сек.]
mysqli_real_query: [0.5439сек.]
mysql_query: [0.5806] sec
mysqli_query: [0.6018сек.]
mysqli prepare: [0.4837сек.]
mysqli_real_query: [0.594сек.]
mysql_query: [0.88555] sec
mysqli_query: [0.9968сек.]
mysqli prepare: [0.8079сек.]
mysqli_real_query:
[0.731сек.] <- и даже вот так бывает
37.
KOZZ (06.08.2011 / 08:49)
36.
ramzes, что - то я не дорубаю, в чем разница между mysqli_query и mysqli_real_query ?
38.
Андрей (06.08.2011 / 10:10)
Разница в возвращаемых данных. mysqli_real_query вернет просто булев тип - try или false. А mysqli_query
вернет результат в зависимости от запроса.
mysqli_real_query стоит использовать если не нужно использовать результат, а просто узнать условие
выполнено или нет. Поэтому он и часто быстрее.
39.
Atmas (06.08.2011 / 10:25)
Рам, на скольких записях тестил?
Я где-т читал и теперь склоняюсь к этому, что если больше записей то выигрыш получается у prepare, а если их мало то наоборот проигрыш..
40.
ramzes (06.08.2011 / 12:50)
38.
Фанат, возвращает массив с данными, у меня вообще только рил квери используется во всех запросах
Добавлено через 01:19 сек.
39.
Atmas, на 5000.
я же говорил уже в этой теме, неоправданное применение повлечет наоборот замедление скрипта
41.
Александр (06.08.2011 / 13:47)
ramzes (6 Августа 2011 / 11:50)
38. Фанат, возвращает массив с данными, у меня вообще только рил квери используется во всех запросах
Это видимо баг у разработчиков. В мануале написано что возвращает true или false
42.
ramzes (06.08.2011 / 13:59)
41.
rastoman, да, знаю =) но работает
в тесте тоже выводил имена из таблицы
43.
Atmas (06.08.2011 / 14:03)
в таблице 3002 записи.
цикл на 10:
mysql_query + mysql_result 0.003сек.
prepare 0.003сек.
mysqli_query 0.0027сек.
mysqli_real_query
0.0014сек.
___
Цикл на 500:
mysql_query + mysql_result 0.064сек.
prepare 0.0597сек.
mysqli_query 0.0598сек.
mysqli_real_query
0.0301сек.
немного пива, немного гоняю разные циклы и делаю выводы...
<?php
$start_array4 = explode(" ",microtime());
$start_time4 = $start_array4['1'] + $start_array4['0'];
for($i=1;$i<501;$i++) {
$res = $mysqli->real_query("SELECT name FROM users WHERE id=$i");
$res = $mysqli->store_result()->fetch_assoc();
echo $i.') ', $res['name'];
}
$end_time4 = microtime(); $end_array4 = explode(" ",$end_time4);
echo '<br/> mysqli_real_query ', round((($end_array4['1'] + $end_array4['0']) - $start_time4),4).'сек.<hr />';
?>
44.
ramzes (06.08.2011 / 14:24)
<?
class SQL extends MySQLi{
public function query($q){
$this->queryCount ++;
if($this->real_query($q)){
return new SQLResult($this);
}else{
return false;
}
}
}
?>
(далее уже не надо store_result() даже использовать =))
45.
Atmas (06.08.2011 / 19:09)
44.
ramzes, ну так в SQLResult {} он должен присутствовать=)
46.
ramzes (06.08.2011 / 19:13)
45.
Atmas, там нет ни чего такого
<?
class SQLResult extends MySQLi_Result{
function count(){
$return = $this->fetch_row();
return $return[0];
}
}
?>
47.
Atmas (06.08.2011 / 22:23)
не осилю...
<?
class SQL extends MySQLi{
public function query($q){
$this->queryCount ++;
if($this->real_query($q)) {
return new SQLResult($this); //для вызова count() разве не нужно писать SQLResult::count()? Что оно возвращает?
} else {
return false;
}
}
}
class SQLResult extends MySQLi_Result{
function count(){ //ведь это альтернатива mysql_result(), для SELECT COUNT()... причем тут это? ведь нужно получить массив со всем значениями, а как это сделать без store_result() я не пойму.
$return = $this->fetch_row();
return $return[0];
}
}
?>
мы или говорим о разном или банально я не пойму, о чем ты
48.
ramzes (07.08.2011 / 01:55)
не смотри на методы)) это я куски своего класса выдрал просто
<?
$mysqli = new SQL('host', 'user', 'pass', 'db');
$res = $mysqli->query("SELECT name FROM users WHERE id=$i")->fetch_assoc(); ?>
привычная конструкция но с рил квери внутри (если использовать класс который я выше описал
попробуй
49.
Atmas (07.08.2011 / 18:38)
48.
ramzes, благодарствую, жаль плюсег еще не могу ставить...
Судя по
описанию класса и если я не ошибаюсь, с запросом выполняется current_field()
А судя по описанию
current_field()
Процедурный стиль только: идентификатор результирующего набора, возвращаемого mysqli_query () , mysqli_store_result () или mysqli_use_result ()
Я прост думаю написать класс для работы с БД, а в нем использовать процедурный стиль, так как все навороты классов мне не нужны...
50.
Юрий (07.08.2011 / 18:43)
Я плюсану за тебя
51.
ramzes (07.08.2011 / 19:08)
да можно было и без плюса обойтись =)
а зачем писать свой класс когда в родном уже все есть?
<?
public function Oldquery($q){
$this->queryCount ++;
if(mysqli::query($q)){
return new SQLResult($this);
}else{
return false;
}
}
?>
до кучи, если вдруг понадобится чистый query()
52.
KOZZ (07.08.2011 / 19:23)
49.
Atmas, дак тебе же самому удобнее будет работать с ооп стилем в самих классах
53.
Atmas (08.08.2011 / 00:03)
В общем не знаю зачем, погонял процедурный стиль и ОО, разницы не заметил, а в моих условиях тем более ее не заметишь.
Сделаю на ОО, так как удобней
54.
ramzes (08.08.2011 / 01:27)
По поводу скорости.
было дело раньше тоже все гнался за сотыми и тысячными, со временем пришел к выводу, цель оправдывает средства, меньше 0.05 можно вообще не обращать внимания, пользователь не заметит результатов этой борьбы =)
55.
Titov (07.09.2011 / 17:56)
Этот код отказываеться работать, кто подскажет где ошибка?
<?
$result = $mysqli->query("SELECT * FROM `setting`");
while($setup=mysqli_fetch_array($result))
{
$setup['name'] = $setup['value'];
}
$result->close();
?>
56.
Wwwyd (07.09.2011 / 18:06)
Так попробуй
<?php
$result = $mysqli->query("SELECT * FROM `setting`");
while($setup=$result->fetch_array())
{
$setup['name'] = $setup['value'];
}
$result->close();
?>
57.
KOZZ (07.09.2011 / 18:11)
55.
Тitov, гк как минимум,и к теме не относится
не $result->close(); а $mysqli->close();
а вообще,делай так:
$setup = $mysqli->query("SELECT * FROM `setting`")->fetch_all(MYSQL_ASSOC);
58.
Wwwyd (07.09.2011 / 18:35)
Либо так
<?php
$setup = $mysqli->query("SELECT * FROM `setting`;")->fetch_assoc();
?>
59.
KOZZ (28.09.2011 / 04:22)
58.
Wwwyd, так ты только последнюю запись в массив занесешь
60.
KOZZ (29.09.2011 / 04:51)
60.
ZiGR, я думал ему это и нужно.
Для очистки памяти есть специальные функции.
Добавлено через 01:31 сек.
61.
ZiGR, че за велосипеды строим? Fetch_all есть,я указал пример выше
61.
JustZero (04.02.2012 / 22:56)
<?php
public function query($sql)
{
$querystart = microtime(true);
$result = @parent::query($sql);
$queryend = microtime(true);
$querytime = round($queryend - $querystart);
if ($this -> errno != 0) {
$this -> error($sql . PHP_EOL . $this -> error);
}
return $result;
}
чет не так делаю с будуна.... не могу понять что?
Помогите люди добрые
Добавлено через 04:38 сек.
class DataBase extends MySQLi {
URL:
https://visavi.net/topics/23716