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. Фанат, спасибо, наконец - то получил ответ на вопрос smile klass
а использовать нужно только при вводе данных в бд, или при выводе тоже?

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 smile
Да и лично у меня запросов в циклах не встречается)
<?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, он и должен быть быстрее, не злоупотребляйте, больший функционал шаблонов требует и большемвремени. Если оно не надо то и не используйтеsmile

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. Фанат, возвращает массив с данными, у меня вообще только рил квери используется во всех запросахsmile

Добавлено через 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]; 
    } 
} 
?>
мы или говорим о разном или банально я не пойму, о чем ты smile

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)
Я плюсану за тебя smile

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, дак тебе же самому удобнее будет работать с ооп стилем в самих классах smile

53. Atmas (08.08.2011 / 00:03)
В общем не знаю зачем, погонял процедурный стиль и ОО, разницы не заметил, а в моих условиях тем более ее не заметишь.
Сделаю на ОО, так как удобней smile

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;
    } 

чет не так делаю с будуна.... не могу понять что? obana
Помогите люди добрые

Добавлено через 04:38 сек.
class DataBase extends MySQLi {

URL: https://visavi.net/topics/23716