Spec-Zone .ru
спецификации, руководства, описания, API

22.9.3.3. Руководство по быстрому старту

Copyright 1997-2012 PHP Documentation Group.

Это руководство по быстрому старту поможет с выбором и получением знакомства с API MySQL PHP.

Этот быстрый запуск дает краткий обзор mysqli расширения. Примеры кода обеспечиваются для всех главных аспектов API. Понятия базы данных объясняются градусу, необходимому для того, чтобы представить понятия, определенные для MySQL.

Требуемый: знакомство с языком программирования PHP, языком SQL, и элементарными знаниями сервера MySQL.

22.9.3.3.1. Двойной процедурный и объектно-ориентированный интерфейс

Copyright 1997-2012 PHP Documentation Group.

mysqli расширение обладает двойным интерфейсом. Это поддерживает парадигму процедурного и объектно-ориентированного программирования.

Пользователи, переходящие от старого mysql расширения, могут предпочесть процедурный интерфейс. Процедурный интерфейс подобен тому из старого mysql расширения. Во многих случаях имена функций отличаются только префиксом. Некоторые функции mysqli берут дескриптор соединения в качестве своего первого параметра, тогда как соответствующие функции в старом интерфейсе mysql берут его в качестве дополнительного последнего параметра.

Пример 22.77. Легкая миграция от старого mysql расширения

<?php$mysqli = mysqli_connect("example.com", "user", "password", "database");$res = mysqli_query($mysqli, "SELECT 'Please, do not use ' AS _msg FROM DUAL");$row = mysqli_fetch_assoc($res);echo $row['_msg'];$mysql = mysql_connect("localhost", "root", "");mysql_select_db("test");$res = mysql_query("SELECT 'the mysql extension for new developments.' AS _msg FROM DUAL", $mysql);$row = mysql_fetch_assoc($res);echo $row['_msg'];?>    

Вышеупомянутый пример выведет:

Please, do not use the mysql extension for new developments.

Объектно-ориентированный интерфейс

В дополнение к классическому процедурному интерфейсу пользователи могут хотеть использовать объектно-ориентированный интерфейс. Документация организуется, используя объектно-ориентированный интерфейс. Объектно-ориентированный интерфейс показывает функции, сгруппированные их целью, облегчая начинать. Ссылочный раздел дает примеры для обеих разновидностей синтаксиса.

Между двумя интерфейсами нет никаких существенных различий в производительности. Пользователи могут базировать свой выбор на персональном предпочтении.

Пример 22.78. Объектно-ориентированный и процедурный интерфейс

<?php$mysqli = mysqli_connect("example.com", "user", "password", "database");if (mysqli_connect_errno($mysqli)) {    echo "Failed to connect to MySQL: " . mysqli_connect_error();}$res = mysqli_query($mysqli, "SELECT 'A world full of ' AS _msg FROM DUAL");$row = mysqli_fetch_assoc($res);echo $row['_msg'];$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: " . $mysqli->connect_error;}$res = $mysqli->query("SELECT 'choices to please everybody.' AS _msg FROM DUAL");$row = $res->fetch_assoc();echo $row['_msg'];?>    

Вышеупомянутый пример выведет:

A world full of choices to please everybody.

Объектно-ориентированный интерфейс используется для быстрого запуска, потому что ссылочный раздел организуется тот путь.

Смешивание стилей

Возможно переключиться между стилями в любое время. Смешивание обоих стилей не рекомендуется для ясности кода и причин стиля кодирования.

Пример 22.79. Плохой стиль кодирования

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: " . $mysqli->connect_error;}$res = mysqli_query($mysqli, "SELECT 'Possible but bad style.' AS _msg FROM DUAL");if (!$res) {    echo "Failed to run query: (" . $mysqli->errno . ") " . $mysqli->error;}if ($row = $res->fetch_assoc()) {    echo $row['_msg'];}?>    

Вышеупомянутый пример выведет:

Possible but bad style.

См. также

mysqli::__construct
mysqli::query
mysqli_result::fetch_assoc
$mysqli:: connect_errno
$mysqli:: connect_error
$mysqli:: errno
$mysqli:: ошибка
Сводка Функции Расширения MySQLi

22.9.3.3.2. Соединения

Copyright 1997-2012 PHP Documentation Group.

Сервер MySQL поддерживает использование различных транспортных уровней для соединений. Соединения используют TCP/IP, сокеты домена Unix или именованные каналы Windows.

Имя узла localhost имеет особое значение. Это связывается с использованием сокетов домена Unix. Не возможно открыть соединение TCP/IP, используя имя узла localhost следует использовать 127.0.0.1 вместо этого.

Пример 22.80. Особое значение localhost

<?php$mysqli = new mysqli("localhost", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}echo $mysqli->host_info . "\n";$mysqli = new mysqli("127.0.0.1", "user", "password", "database", 3306);if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}echo $mysqli->host_info . "\n";?>    

Вышеупомянутый пример выведет:

Localhost via UNIX socket127.0.0.1 via TCP/IP

Значения по умолчанию параметра соединения

В зависимости от функции соединения могут быть опущены используемые, различные параметры. Если параметр не обеспечивается, то расширение пытается использовать значения по умолчанию, которые устанавливаются в конфигурационном файле PHP.

Пример 22.81. Установка значений по умолчанию

mysqli.default_host=192.168.2.27mysqli.default_user=rootmysqli.default_pw=""mysqli.default_port=3306mysqli.default_socket=/tmp/mysql.sock

Получающиеся значения параметра тогда передают к клиентской библиотеке, которой пользуется расширение. Если клиентская библиотека обнаруживает пустой или параметры сброса, то она может принять значение по умолчанию к библиотеке встроенные значения.

Встроенные значения по умолчанию библиотеки соединения

Если значение узла будет сброшено или пусто, то клиентская библиотека примет значение по умолчанию к сокетному соединению Unix на localhost. Если сокет сбрасывается или пуст, и сокетное соединение Unix требуют, то соединение с сокетом значения по умолчанию на /tmp/mysql.sock предпринимается.

На системах Windows, имени хоста . интерпретируется клиентской библиотекой как попытка открыть именованный канал Windows базируемое соединение. В этом случае параметр сокета интерпретируется как имя канала. Если не данный или пустой, то сокет (передают имя по каналу), значения по умолчанию к \\.\pipe\MySQL.

Если ни один сокет домена Unix, базируемый не, именованный канал Windows, которым должно быть базируемое соединение, не будет установлен, и значение параметра порта сбрасывается, то библиотека примет значение по умолчанию к порту 3306.

mysqlnd библиотека и MySQL Client Library (libmysqlclient) реализуют ту же самую логику для того, чтобы определить значения по умолчанию.

Опции соединения

Опции соединения доступны, например, набор init команды, которые выполняются на, соединяются, или для того, чтобы запросить использование определенного набора символов. Опции соединения должны быть установлены прежде, чем сетевое соединение устанавливается.

Для того, чтобы установить опцию соединения, соединить работа должна быть выполнена в трех шагах: создание соединения обрабатывает с mysqli_init, установка требуемого использования опций mysqli_options, и установление сетевого соединения с mysqli_real_connect.

Объединение в пул соединения

mysqli расширение поддерживает персистентные соединения с базой данных, которые являются специальным видом объединенных в пул соединений. По умолчанию каждое соединение с базой данных, открытое сценарием, или явно закрывается пользователем во время времени выполнения или выпускается автоматически в конце сценария. Персистентное соединение не. Вместо этого это помещается в пул для более позднего повторного использования, если соединение с тем же самым сервером, используя то же самое имя пользователя, пароль, сокет, порт и базу данных значения по умолчанию открывается. Повторное использование сохраняет издержки соединения.

Каждый процесс PHP использует свой собственный mysqli пул соединения. В зависимости от модели развертывания веб-сервера процесс PHP может служить один или многократные запросы. Поэтому, объединенное в пул соединение может использоваться одним или более сценариями впоследствии.

Персистентное соединение

Если неиспользованное персистентное соединение для данной комбинации узла, имени пользователя, пароля, сокета, порта и базы данных значения по умолчанию не может быть найдено в пуле соединения, то mysqli открывает новое соединение. Использование персистентных соединений может быть включено и отключило использование направляющего mysqli.allow_persistent PHP. Общее количество соединений, открытых сценарием, может быть ограничено с mysqli.max_links. Максимальное количество персистентных соединений на процесс PHP может быть ограничено с mysqli.max_persistent. Пожалуйста, отметьте, что веб-сервер может породить много процессов PHP.

Общее жалуется на персистентные соединения, то, что их состояние не сбрасывается перед повторным использованием. Например, открытые и незаконченные транзакции автоматически не откатываются., Но также и, изменения авторизации, которые произошли во время между помещением соединения в пул и многократным использованием этого, не отражаются. Это может быть замечено как нежелательный побочный эффект. Напротив, имя persistent может быть понят как обещание, что состояние сохраняется.

mysqli расширение поддерживает обе интерпретации персистентного соединения: состояние сохранилось, и сброс состояния перед повторным использованием. Значение по умолчанию сбрасывается. Прежде, чем персистентное соединение снова используется, mysqli расширение неявно вызывает mysqli_change_user сбрасывать состояние. Персистентное соединение появляется пользователю, как будто оно было только открыто. Никакие артефакты от предыдущих использований не видимы.

mysqli_change_user функция является дорогой работой. Для лучшей производительности пользователи могут хотеть перекомпилировать расширение с флагом компиляции MYSQLI_NO_CHANGE_USER_ON_PCONNECT быть установленным.

Это оставляют пользователю выбрать между безопасным поведением и лучшей производительностью. Оба - допустимые цели оптимизации. Для простоты использования безопасное поведение было сделано значением по умолчанию за счет максимальной производительности.

См. также

mysqli::__construct
mysqli::init
mysqli::options
mysqli::real_connect
mysqli::change_user
$mysqli:: host_info
Параметры конфигурации MySQLi
Персистентные Соединения с базой данных

22.9.3.3.3. Выполнение операторов

Copyright 1997-2012 PHP Documentation Group.

Операторы могут быть выполнены с mysqli_query, mysqli_real_query и mysqli_multi_query функции. mysqli_query функция наиболее распространена, и комбинирует выполняющийся оператор с буферизованной выборкой его набора результатов, если таковые вообще имеются, в одном вызове. Вызов mysqli_query идентично вызову mysqli_real_query сопровождаемый mysqli_store_result.

Пример 22.82. Соединение с MySQL

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT)") ||    !$mysqli->query("INSERT INTO test(id) VALUES (1)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}?>

Буферизованные наборы результатов

После того, как результаты выполнения оператора могут быть получены сразу, чтобы быть буферизованными клиентом или строкой чтения строкой. Клиентская буферизация набора результатов позволяет сервер бесплатным ресурсам, связанным с результатами оператора как можно раньше. Вообще говоря, клиенты являются медленными наборами результатов потребления. Поэтому, рекомендуется использовать буферизованные наборы результатов. mysqli_query комбинирует выполнение оператора и буферизацию набора результатов.

Приложения PHP могут переместиться свободно через буферизованные результаты. Навигация быстра, потому что наборы результатов сохранены в клиентской памяти. Пожалуйста, имейте в виду, что часто легче масштабироваться клиентом, чем это должно масштабировать сервер.

Пример 22.83. Навигация через буферизованные результаты

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT)") ||    !$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}$res = $mysqli->query("SELECT id FROM test ORDER BY id ASC");echo "Reverse order...\n";for ($row_no = $res->num_rows - 1; $row_no >= 0; $row_no--) {    $res->data_seek($row_no);    $row = $res->fetch_assoc();    echo " id = " . $row['id'] . "\n";}echo "Result set order...\n";$res->data_seek(0);while ($row = $res->fetch_assoc()) {    echo " id = " . $row['id'] . "\n";}?>    

Вышеупомянутый пример выведет:

Reverse order... id = 3 id = 2 id = 1Result set order... id = 1 id = 2 id = 3

Небуферизованные наборы результатов

Если клиентская память является коротким ресурсом, и ресурсы сервера освобождения как можно раньше, чтобы сохранить низкую загрузку сервера не необходим, небуферизованные результаты могут использоваться. Просматривание путем прокрутки небуферизованных результатов не возможно прежде, чем все строки были считаны.

Пример 22.84. Навигация через небуферизованные результаты

<?php$mysqli->real_query("SELECT id FROM test ORDER BY id ASC");$res = $mysqli->use_result();echo "Result set order...\n";while ($row = $res->fetch_assoc()) {    echo " id = " . $row['id'] . "\n";}?>

Набор результатов оценивает типы данных

mysqli_query, mysqli_real_query и mysqli_multi_query функции используются, чтобы выполнить неподготовленные операторы. На уровне MySQL Client Server Protocol, команды COM_QUERY и текстовый протокол используется для выполнения оператора. С текстовым протоколом сервер MySQL преобразовывает все данные наборы результатов в строки перед отправкой. Это преобразование делается независимо от типа данных столбца набора результатов SQL. mysql клиентские библиотеки получают все значения столбцов как строки. Никакой дальнейший клиентский кастинг не делается, чтобы преобразовать столбцы назад в их собственные типы. Вместо этого все значения обеспечиваются как строки PHP.

Пример 22.85. Текстовый протокол возвращает строки по умолчанию

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||    !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}$res = $mysqli->query("SELECT id, label FROM test WHERE id = 1");$row = $res->fetch_assoc();printf("id = %s (%s)\n", $row['id'], gettype($row['id']));printf("label = %s (%s)\n", $row['label'], gettype($row['label']));?>    

Вышеупомянутый пример выведет:

id = 1 (string)label = a (string)

Возможно преобразовать целочисленные и столбцы плавающие назад в числа PHP, устанавливая MYSQLI_OPT_INT_AND_FLOAT_NATIVE опция соединения, пользуясь mysqlnd библиотекой. Если установлено, mysqlnd библиотека проверит типы столбца метаданных набора результатов и преобразует числовые столбцы SQL в числа PHP, если диапазон значений типа данных PHP учтет ее. Таким образом, например столбцы INT SQL возвращаются как целые числа.

Пример 22.86. Собственные типы данных с mysqlnd и опцией соединения

<?php$mysqli = mysqli_init();$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1);$mysqli->real_connect("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||    !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}$res = $mysqli->query("SELECT id, label FROM test WHERE id = 1");$row = $res->fetch_assoc();printf("id = %s (%s)\n", $row['id'], gettype($row['id']));printf("label = %s (%s)\n", $row['label'], gettype($row['label']));?>    

Вышеупомянутый пример выведет:

id = 1 (integer)label = a (string)

См. также

mysqli::__construct
mysqli::init
mysqli::options
mysqli::real_connect
mysqli::query
mysqli::multi_query
mysqli::use_result
mysqli::store_result
mysqli_result::free

22.9.3.3.4. Готовые Операторы

Copyright 1997-2012 PHP Documentation Group.

База данных MySQL поддерживает подготовленные операторы. Готовый оператор или параметризованный оператор используются, чтобы неоднократно выполнять тот же самый оператор с высокой производительностью.

Основной поток операций

Готовое выполнение оператора состоит из двух этапов: подготовьтесь и выполнитесь. На подготовить этапе шаблон оператора, передаются к серверу базы данных. Сервер выполняет проверку синтаксиса и инициализирует сервер внутренние ресурсы для более позднего использования.

Сервер MySQL поддерживает использование анонимный, позиционный заполнитель с ?.

Пример 22.87. Первая стадия: подготовиться

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}/* Non-prepared statement */if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}/* Prepared statement, stage 1: prepare */if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) {    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;}?>

Подготовьтесь сопровождается, выполняются. Во время выполняются, клиент связывает значения параметра и отправляет им серверу. Сервер создает оператор из шаблона оператора и связанных значений, чтобы выполнить это использующий ранее создаваемые внутренние ресурсы.

Пример 22.88. Второй этап: свяжите и выполнитесь

<?php/* Prepared statement, stage 2: bind and execute */$id = 1;if (!$stmt->bind_param("i", $id)) {    echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;}if (!$stmt->execute()) {    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;}?>

Повторное выполнение

Готовый оператор может неоднократно выполняться. После каждого выполнения оценивается текущая стоимость связанной переменной, и передайтесь к серверу. Оператор не анализируется снова. Шаблон оператора не передается серверу снова.

Пример 22.89. ВСТАВЬТЕ подготовленный однажды, выполняемый многократно

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}/* Non-prepared statement */if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}/* Prepared statement, stage 1: prepare */if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) {     echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;}/* Prepared statement, stage 2: bind and execute */$id = 1;if (!$stmt->bind_param("i", $id)) {    echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;}if (!$stmt->execute()) {    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;}/* Prepared statement: repeated execution, only data transferred from client to server */for ($id = 2; $id < 5; $id++) {    if (!$stmt->execute()) {        echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;    }}/* explicit close recommended */$stmt->close();/* Non-prepared statement */$res = $mysqli->query("SELECT id FROM test");var_dump($res->fetch_all());?>    

Вышеупомянутый пример выведет:

array(4) {  [0]=>  array(1) {    [0]=>    string(1) "1"  }  [1]=>  array(1) {    [0]=>    string(1) "2"  }  [2]=>  array(1) {    [0]=>    string(1) "3"  }  [3]=>  array(1) {    [0]=>    string(1) "4"  }}

Каждый готовый оператор занимает ресурсы сервера. Операторы должны быть закрыты явно сразу после использования. Если не сделанный явно, оператор будет закрыт, когда дескриптор оператора будет освобожден PHP.

Используя готовый оператор не всегда самый эффективный способ выполнить оператор. Готовый оператор, выполняемый только однажды причины больше поездок туда и обратно клиент-сервер чем неготовый оператор. Это то, почему SELECT не выполняется как готовый оператор выше.

Кроме того, полагайте, что использование MySQL мультивставляет синтаксис SQL для ВСТАВОК. Для примера мультивставьте, требует меньшего количества поездок туда и обратно между сервером и клиентом чем готовый оператор, показанный выше.

Пример 22.90. Использование менее циклов обработки мультивставляет SQL

<?phpif (!$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3), (4)")) {    echo "Multi-INSERT failed: (" . $mysqli->errno . ") " . $mysqli->error;}?>

Набор результатов оценивает типы данных

MySQL Client Server Protocol определяет различный протокол передачи данных для готовых операторов и неподготовленных операторов. Готовые операторы используют так называемый протокол двоичной синхронной передачи данных. Сервер MySQL отправляет данные набора результатов, "как" в двоичном формате. Результаты не сериализируются в строки перед отправкой. Клиентские библиотеки не получают строки только. Вместо этого они получат двоичных данных и попытаются преобразовать значения в соответствующие типы данных PHP. Например, следует из SQL INT столбец будет обеспечен как целочисленные переменные PHP.

Пример 22.91. Собственные типы данных

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||    !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = 1");$stmt->execute();$res = $stmt->get_result();$row = $res->fetch_assoc();printf("id = %s (%s)\n", $row['id'], gettype($row['id']));printf("label = %s (%s)\n", $row['label'], gettype($row['label']));?>    

Вышеупомянутый пример выведет:

id = 1 (integer)label = a (string)

Это поведение отличается от неготовых операторов. По умолчанию неготовые операторы возвращают все результаты как строки. Это значение по умолчанию может быть изменено, используя опцию соединения. Если опция соединения используется, нет никаких различий.

Выборка результатов, используя связанные переменные

Следствия готовых операторов могут или быть получены, связывая выходные переменные, или запрашивая a mysqli_result объект.

Выходные переменные должны быть связаны после выполнения оператора. Одна переменная должна направиться в каждый столбец набора результатов операторов.

Пример 22.92. Выведите привязку переменной

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||    !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!($stmt = $mysqli->prepare("SELECT id, label FROM test"))) {    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$stmt->execute()) {    echo "Execute failed: (" . $mysqli->errno . ") " . $mysqli->error;}$out_id    = NULL;$out_label = NULL;if (!$stmt->bind_result($out_id, $out_label)) {    echo "Binding output parameters failed: (" . $stmt->errno . ") " . $stmt->error;}while ($stmt->fetch()) {    printf("id = %s (%s), label = %s (%s)\n", $out_id, gettype($out_id), $out_label, gettype($out_label));}?>    

Вышеупомянутый пример выведет:

id = 1 (integer), label = a (string)

Готовые операторы возвращают небуферизованные наборы результатов по умолчанию. Результаты оператора неявно не выбираются и передаются от сервера до клиента для клиентской буферизации. Набор результатов берет ресурсы сервера, пока все результаты не были выбраны клиентом. Таким образом рекомендуется использовать своевременные результаты. Если клиент не в состоянии выбрать все результаты, или клиент закрывает оператор, прежде выбрали все данные, данные должны быть выбраны неявно mysqli.

Также возможно буферизовать результаты готового использования оператора mysqli_stmt_store_result.

Выборка результатов, используя mysqli_result интерфейс

Вместо того, чтобы использовать связанные результаты, результаты могут также быть получены через интерфейс mysqli_result. mysqli_stmt_get_result возвращает буферизованный набор результатов.

Пример 22.93. Используя mysqli_result, чтобы выбрать результаты

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||    !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!($stmt = $mysqli->prepare("SELECT id, label FROM test ORDER BY id ASC"))) {    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$stmt->execute()) {     echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;}if (!($res = $stmt->get_result())) {    echo "Getting result set failed: (" . $stmt->errno . ") " . $stmt->error;}var_dump($res->fetch_all());?>    

Вышеупомянутый пример выведет:

array(1) {  [0]=>  array(2) {    [0]=>    int(1)    [1]=>    string(1) "a"  }}

Используя mysqli_result interface предлагает дополнительную выгоду гибкой клиентской навигации набора результатов.

Пример 22.94. Буферизованный набор результатов для гибкого чтения

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||    !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c')")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!($stmt = $mysqli->prepare("SELECT id, label FROM test"))) {    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$stmt->execute()) {     echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;}if (!($res = $stmt->get_result())) {    echo "Getting result set failed: (" . $stmt->errno . ") " . $stmt->error;}for ($row_no = ($res->num_rows - 1); $row_no >= 0; $row_no--) {    $res->data_seek($row_no);    var_dump($res->fetch_assoc());}$res->close();?>    

Вышеупомянутый пример выведет:

array(2) {  ["id"]=>  int(3)  ["label"]=>  string(1) "c"}array(2) {  ["id"]=>  int(2)  ["label"]=>  string(1) "b"}array(2) {  ["id"]=>  int(1)  ["label"]=>  string(1) "a"}

Выход и инжекция SQL

Связанных переменных оставит автоматически сервер. Сервер вставляет их оставленные значения в соответствующих местах в шаблон оператора перед выполнением. Подсказка должна быть обеспечена для сервера для типа связанной переменной, чтобы создать соответствующее преобразование. См. mysqli_stmt_bind_param функция для получения дополнительной информации.

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

Сторона клиента подготовленная эмуляция оператора

API не включает эмуляцию для стороны клиента подготовленная эмуляция оператора.

Быстрый подготовленный - неподготовленное сравнение оператора

Таблица ниже сравнивает сторону сервера подготовленные и неподготовленные операторы.

Таблица 22.42. Сравнение готовых и неготовых операторов

Готовый Оператор Неготовый оператор
Циклы обработки клиент-сервер, ВЫБЕРИТЕ, единственное выполнение 2 1
Строка оператора, переданная от клиента к серверу 1 1
Циклы обработки клиент-сервер, ИЗБРАННЫЕ, повторили (n) выполнение 1 + n n
Строка оператора, переданная от клиента к серверу 1 шаблон, n времена связанный параметр, если любой n времена вместе с параметром, если любой
Введите API привязки параметров Да, автоматический входной выход Нет, ручной входной выход
Выведите API привязки переменной Да Нет
Поддерживает использование mysqli_result API Да, используйте mysqli_stmt_get_result Да
Буферизованные наборы результатов Да, используйте mysqli_stmt_get_result или привязка с mysqli_stmt_store_result Да, значение по умолчанию mysqli_query
Небуферизованные наборы результатов Да, используйте вывод обязательный API Да, используйте mysqli_real_query сmysqli_use_result
Разновидность передачи данных протокола MySQL Client Server Протокол двоичной синхронной передачи данных Текстовый протокол
Набор результатов оценивает типы данных SQL Сохраненный, выбирая Преобразованный в строку или сохраненный, выбирая
Поддерживает все SQL-операторы Недавние версии MySQL поддерживают больше всего, но не все Да

См. также

mysqli::__construct
mysqli::query
mysqli::prepare
mysqli_stmt::prepare
mysqli_stmt::execute
mysqli_stmt::bind_param
mysqli_stmt::bind_result

22.9.3.3.5. Хранимые процедуры

Copyright 1997-2012 PHP Documentation Group.

База данных MySQL поддерживает хранимые процедуры. Хранимая процедура является подпрограммой, сохраненной в каталоге базы данных. Приложения могут вызвать и выполнить хранимую процедуру. CALL SQL-оператор используется, чтобы выполнить хранимую процедуру.

Параметр

Хранимые процедуры могут иметь IN, INOUT и OUT параметры, в зависимости от версии MySQL. У интерфейса mysqli нет никакого специального понятия для различных видов параметров.

В параметре

Входным параметрам предоставляют CALL оператор. Пожалуйста, удостоверьтесь, что значений оставляют правильно.

Пример 22.95. Вызов хранимой процедуры

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||    !$mysqli->query("CREATE PROCEDURE p(IN id_val INT) BEGIN INSERT INTO test(id) VALUES(id_val); END;")) {    echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$mysqli->query("CALL p(1)")) {    echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!($res = $mysqli->query("SELECT id FROM test"))) {    echo "SELECT failed: (" . $mysqli->errno . ") " . $mysqli->error;}var_dump($res->fetch_assoc());?>    

Вышеупомянутый пример выведет:

array(1) {  ["id"]=>  string(1) "1"}

Параметр INOUT/OUT

Значения INOUT/OUT к параметрам получают доступ, используя переменные сеанса.

Пример 22.96. Используя переменные сеанса

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||    !$mysqli->query('CREATE PROCEDURE p(OUT msg VARCHAR(50)) BEGIN SELECT "Hi!" INTO msg; END;')) {    echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$mysqli->query("SET @msg = ''") || !$mysqli->query("CALL p(@msg)")) {    echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!($res = $mysqli->query("SELECT @msg as _p_out"))) {    echo "Fetch failed: (" . $mysqli->errno . ") " . $mysqli->error;}$row = $res->fetch_assoc();echo $row['_p_out'];?>    

Вышеупомянутый пример выведет:

Hi!

Приложение и разработчики платформы могут быть в состоянии обеспечить более удобный API, используя соединение переменных сеанса и databased контроля каталога. Однако, пожалуйста, отметьте возможное воздействие производительности пользовательского решения, основанного на контроле каталога.

Обработка наборов результатов

Хранимые процедуры могут возвратить наборы результатов. Наборы результатов, возвращенные из хранимой процедуры, не могут быть выбраны, правильно используя mysqli_query. mysqli_query функция комбинирует выполнение оператора и выборку первого набора результатов в буферизованный набор результатов, если любой. Однако, есть дополнительные наборы результатов хранимой процедуры, скрытые от пользователя, которые вызывают mysqli_query приводить возврат к сбою пользователя ожидаемые наборы результатов.

Наборы результатов, возвращенные из хранимой процедуры, выбираются, используя mysqli_real_query или mysqli_multi_query. Обе функции позволяют выбирать любое число наборов результатов, возвращенных оператором, такой как CALL. То, чтобы быть не в состоянии выбрать все наборы результатов, возвращенные хранимой процедурой, вызывает ошибку.

Пример 22.97. Выборка следствий хранимых процедур

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT)") ||    !$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||    !$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;')) {    echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$mysqli->multi_query("CALL p()")) {    echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;}do {    if ($res = $mysqli->store_result()) {        printf("---\n");        var_dump($res->fetch_all());        $res->free();    } else {        if ($mysqli->errno) {            echo "Store failed: (" . $mysqli->errno . ") " . $mysqli->error;        }    }} while ($mysqli->more_results() && $mysqli->next_result());?>    

Вышеупомянутый пример выведет:

---array(3) {  [0]=>  array(1) {    [0]=>    string(1) "1"  }  [1]=>  array(1) {    [0]=>    string(1) "2"  }  [2]=>  array(1) {    [0]=>    string(1) "3"  }}---array(3) {  [0]=>  array(1) {    [0]=>    string(1) "2"  }  [1]=>  array(1) {    [0]=>    string(1) "3"  }  [2]=>  array(1) {    [0]=>    string(1) "4"  }}

Использование готовых операторов

Никакая специальная обработка не требуется при использовании готового интерфейса оператора для того, чтобы выбрать следствия той же самой хранимой процедуры как выше. Готовый оператор и неподготовленные интерфейсы оператора подобны. Пожалуйста, отметьте, это не, каждая версия сервера MYSQL может поддерживать подготовку CALL SQL-оператор.

Пример 22.98. Хранимые процедуры и Готовые Операторы

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") ||    !$mysqli->query("CREATE TABLE test(id INT)") ||    !$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||    !$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;')) {    echo "Stored procedure creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!($stmt = $mysqli->prepare("CALL p()"))) {    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$stmt->execute()) {    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;}do {    if ($res = $stmt->get_result()) {        printf("---\n");        var_dump(mysqli_fetch_all($res));        mysqli_free_result($res);    } else {        if ($stmt->errno) {            echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;        }    }} while ($stmt->more_results() && $stmt->next_result());?>

Конечно, использование связывать API для того, чтобы выбрать поддерживается также.

Пример 22.99. Хранимые процедуры и Готовое использование Операторов связывают API

<?phpif (!($stmt = $mysqli->prepare("CALL p()"))) {    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;}if (!$stmt->execute()) {    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;}do {    $id_out = NULL;    if (!$stmt->bind_result($id_out)) {        echo "Bind failed: (" . $stmt->errno . ") " . $stmt->error;    }     while ($stmt->fetch()) {        echo "id = $id_out\n";    }} while ($stmt->more_results() && $stmt->next_result());?>

См. также

mysqli::query
mysqli::multi_query
mysqli_result::next-result
mysqli_result::more-results

22.9.3.3.6. Многократные Операторы

Copyright 1997-2012 PHP Documentation Group.

MySQL дополнительно позволяет иметь многократные операторы в одной строке оператора. Отправка многократных операторов сразу уменьшает циклы обработки клиент-сервер, но требует специальной обработки.

Многократные операторы или много запросы должны быть выполнены с mysqli_multi_query. Отдельные операторы строки оператора разделяются точкой с запятой. Затем, все наборы результатов, возвращенные выполняемыми операторами, должны быть выбраны.

Сервер MySQL позволяет иметь операторы, которые действительно возвращают наборы результатов и операторы, которые не возвращают наборы результатов в одном многократном операторе.

Пример 22.100. Многократные Операторы

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {    echo "Table creation failed: (" . $mysqli->errno . ") " . $mysqli->error;}$sql = "SELECT COUNT(*) AS _num FROM test; ";$sql.= "INSERT INTO test(id) VALUES (1); ";$sql.= "SELECT COUNT(*) AS _num FROM test; ";if (!$mysqli->multi_query($sql)) {    echo "Multi query failed: (" . $mysqli->errno . ") " . $mysqli->error;}do {    if ($res = $mysqli->store_result()) {        var_dump($res->fetch_all(MYSQLI_ASSOC));        $res->free();    }} while ($mysqli->more_results() && $mysqli->next_result());?>    

Вышеупомянутый пример выведет:

array(1) {  [0]=>  array(1) {    ["_num"]=>    string(1) "0"  }}array(1) {  [0]=>  array(1) {    ["_num"]=>    string(1) "1"  }}

Соображения безопасности

API-функции mysqli_query и mysqli_real_query не устанавливайте флаг соединения, необходимый для того, чтобы активировать много запросы в сервере. Дополнительный вызов API используется для многократных операторов, чтобы уменьшить вероятность случайных атак с использованием кода на SQL. Атакующий может попытаться добавить операторы такой как ; DROP DATABASE mysql или ; SELECT SLEEP(999). Если атакующий преуспевает в том, чтобы добавить SQL к строке оператора, но mysqli_multi_query не используется, сервер не будет выполнять второй, введенный и злонамеренный SQL-оператор.

Пример 22.101. Инжекция SQL

<?php$mysqli = new mysqli("example.com", "user", "password", "database");$res    = $mysqli->query("SELECT 1; DROP TABLE mysql.user");if (!$res) {    echo "Error executing query: (" . $mysqli->errno . ") " . $mysqli->error;}?>    

Вышеупомянутый пример выведет:

Error executing query: (1064) You have an error in your SQL syntax;check the manual that corresponds to your MySQL server version for the right syntax to use near 'DROP TABLE mysql.user' at line 1

Готовые операторы

Использование многократного оператора с готовыми операторами не поддерживается.

См. также

mysqli::query
mysqli::multi_query
mysqli_result::next-result
mysqli_result::more-results

22.9.3.3.7. Поддержка API транзакций

Copyright 1997-2012 PHP Documentation Group.

Сервер MySQL поддерживает транзакции в зависимости от используемого механизма хранения. Начиная с MySQL 5.5 механизмом хранения значения по умолчанию является InnoDB. У InnoDB есть полная поддержка транзакции ACID.

Транзакциями можно или управлять, используя SQL или вызовы API. Рекомендуется использовать вызовы API включения и отключения автоматического режима фиксации и фиксации и отката транзакций.

Пример 22.102. Установка автоматического режима фиксации с SQL и через API

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}/* Recommended: using API to control transactional settings */$mysqli->autocommit(false);/* Won't be monitored and recognized by the replication and the load balancing plugin */if (!$mysqli->query('SET AUTOCOMMIT = 0')) {    echo "Query failed: (" . $mysqli->errno . ") " . $mysqli->error;}?>

Пакеты дополнительной функции, такие как плагин репликации и выравнивания нагрузки, могут легко контролировать вызовы API. Плагин репликации предлагает транзакции осведомленное выравнивание нагрузки, если транзакциями управляют с вызовами API. Осведомленное выравнивание нагрузки транзакции не доступно, если SQL-операторы используются для того, чтобы установить автоматический режим фиксации, фиксируя или откатывая транзакцию.

Пример 22.103. Фиксация и откат

<?php$mysqli = new mysqli("example.com", "user", "password", "database");$mysqli->autocommit(false);$mysqli->query("INSERT INTO test(id) VALUES (1)");$mysqli->rollback();$mysqli->query("INSERT INTO test(id) VALUES (2)");$mysqli->commit();?>

Пожалуйста, отметьте, что сервер MySQL не может откатывать все операторы. Некоторой причиной операторов является неявная фиксация.

См. также

mysqli::autocommit
mysqli_result::commit
mysqli_result::rollback

22.9.3.3.8. Метаданные

Copyright 1997-2012 PHP Documentation Group.

Набор результатов MySQL содержит метаданные. Метаданные описывают столбцы, найденные в наборе результатов. Все метаданные передаются MySQL, доступно через mysqli интерфейс. Расширение не выполняет или незначительных изменений к информации, которую оно получает. Различия между версиями сервера MySQL не выровненные.

Метаданные являются доступом через mysqli_result интерфейс.

Пример 22.104. Доступ к метаданным набора результатов

<?php$mysqli = new mysqli("example.com", "user", "password", "database");if ($mysqli->connect_errno) {    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;}$res = $mysqli->query("SELECT 1 AS _one, 'Hello' AS _two FROM DUAL");var_dump($res->fetch_fields());?>    

Вышеупомянутый пример выведет:

array(2) {  [0]=>  object(stdClass)#3 (13) {    ["name"]=>    string(4) "_one"    ["orgname"]=>    string(0) ""    ["table"]=>    string(0) ""    ["orgtable"]=>    string(0) ""    ["def"]=>    string(0) ""    ["db"]=>    string(0) ""    ["catalog"]=>    string(3) "def"    ["max_length"]=>    int(1)    ["length"]=>    int(1)    ["charsetnr"]=>    int(63)    ["flags"]=>    int(32897)    ["type"]=>    int(8)    ["decimals"]=>    int(0)  }  [1]=>  object(stdClass)#4 (13) {    ["name"]=>    string(4) "_two"    ["orgname"]=>    string(0) ""    ["table"]=>    string(0) ""    ["orgtable"]=>    string(0) ""    ["def"]=>    string(0) ""    ["db"]=>    string(0) ""    ["catalog"]=>    string(3) "def"    ["max_length"]=>    int(5)    ["length"]=>    int(5)    ["charsetnr"]=>    int(8)    ["flags"]=>    int(1)    ["type"]=>    int(253)    ["decimals"]=>    int(31)  }}

Готовые операторы

К метаданным наборов результатов, создаваемых, используя подготовленные операторы, получают доступ тот же самый путь. Подходящее mysqli_result дескриптор возвращается mysqli_stmt_result_metadata.

Пример 22.105. Готовые метаданные операторов

<?php$stmt = $mysqli->prepare("SELECT 1 AS _one, 'Hello' AS _two FROM DUAL");$stmt->execute();$res = $stmt->result_metadata();var_dump($res->fetch_fields());?>

См. также

mysqli::query
mysqli_result::fetch_fields