Хранимые процедуры, MySQL и PHP

Вопрос довольно открытый. Я использую хранимые процедуры с MS SQLServer в течение некоторого времени с классическими ASP и ASP.net и люблю их, много.

У меня есть небольшой проект для хобби, над которым я работаю, и по разным причинам пошел по маршруту ЛАМП. Любые подсказки / трюки / ловушки или хорошие отправные точки для использования хранимых процедур с MySQL и PHP5? Моя версия MySQL поддерживает хранимые процедуры.

Забудьте о mysqli , его гораздо сложнее использовать, чем PDO, и его необходимо было удалить. Это правда, что он ввел огромные улучшения по сравнению с mysql, но для достижения такого же эффекта в mysqli иногда требуются огромные усилия над PDO, то есть ассоциативный fetchAll .

Вместо этого взгляните на PDO , специально подготовленные заявления и хранимые процедуры .

 $stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)"); $value = 'hello'; $stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000); // call the stored procedure $stmt->execute(); print "procedure returned $value\n"; 

@michal kralik – к сожалению, есть ошибка с MySQL C API, который использует PDO, что означает, что запуск вашего кода, как указано выше, с некоторыми версиями MySQL приводит к ошибке:

«Ошибка синтаксиса или нарушение доступа: 1414 OUT или INOUT аргумент $ parameter_number для рутинного $ procedure_name не является переменной или новой псевдо-переменной NEW».

Вы можете увидеть отчет об ошибке на bugs.mysql.com . Он исправлен для версии 5.5.3+ и 6.0.8+.

Чтобы обойти эту проблему, вам нужно будет разделить параметры ввода и вывода и использовать пользовательские переменные для сохранения результата следующим образом:

 $stmt = $dbh->prepare("CALL sp_takes_string_returns_string(:in_string, @out_string)"); $stmt->bindParam(':in_string', 'hello'); // call the stored procedure $stmt->execute(); // fetch the output $outputArray = $this->dbh->query("select @out_string")->fetch(PDO::FETCH_ASSOC); print "procedure returned " . $outputArray['@out_string'] . "\n"; 

На самом деле не обязательно использовать mysqli или PDO для вызова хранимых процедур в MySQL 5. Вы можете просто назвать их с помощью старых функций mysql_. Единственное, что вы не можете сделать, это вернуть несколько наборов результатов.

Я обнаружил, что возвращение нескольких наборов результатов в некоторой степени подвержено ошибкам; он работает в некоторых случаях, но только в том случае, если приложение помнит, что потребляет их все, в противном случае соединение остается в разбитом состоянии.

Вам нужно будет использовать MySQLI (MySQL Improved Extension) для вызова хранимых процедур. Вот как вы могли бы назвать SP :

 $mysqli = new MySQLI(user,pass,db); $result = $mysqli->query("CALL sp_mysp()"); 

При использовании SP вам нужно закрыть первый набор результатов или вы получите сообщение об ошибке. Вот еще информация:

http://blog.rvdavid.net/using-stored-procedures-mysqli-in-php-5/ (неработающая ссылка)

Кроме того, вы можете использовать подготовленные заявления , которые я считаю очень простыми:

  $stmt = $mysqli->prepare("SELECT Phone FROM MyTable WHERE Name=?"); $stmt->bind_param("s", $myName); $stmt->execute(); 

Документация MySQLI: http://no.php.net/manual/en/book.mysqli.php

Я использую ADODB, что отлично подходит для абстрагирования реальных команд, чтобы сделать его переносимым между различными серверами SQL (т.е. mysql to mssql). Однако Хранимые процедуры не поддерживаются напрямую. Это означает, что я запускал SQL-запрос, как если бы он был нормальным, но «вызывал» SP. Пример запроса:

 $query = "Call HeatMatchInsert('$mMatch', '$mOpponent', '$mDate', $mPlayers, $mRound, '$mMap', '$mServer', '$mPassword', '$mGame', $mSeason, $mMatchType)"; 

Это не учитывает возвращенные данные, что важно. Я предполагаю, что это будет сделано, установив @Var, чтобы вы могли выбрать себя как return @Variable.

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