У меня есть несколько хранимых процедур, сделанных с помощью MySQL Workbench. Они отлично работают, когда используют workbench MySQL, чтобы поместить их в тестовую БД.
Теперь я готовлю сценарии создания БД для развертывания, и это единственный, который дает мне проблемы. Когда я использую оболочку командной строки / mysql, скрипт отлично работает. Только когда я использую интерфейс mysql (i) PHP для выполнения скрипта – он терпит неудачу. Без комментариев.
Я использую сценарии создания процедур, поскольку MySQL workbench генерирует для меня; т. е. имеет такой шаблон:
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
в начале сценария, затем повторяя для каждой процедуры:
DELIMITER $$ USE `dbname`$$ CREATE PROCEDURE `procname`(IN inputparameters) BEGIN
… процедура идет здесь
; END$$ DELIMITER ;
Этот скрипт отлично работает при запуске из MySQL Workbench. Он также отлично работает, если я пытаюсь сделать то же самое из командной строки mysql. Но я ничего не могу выполнить, выполняя его через интерфейс PHP mysqli (выполняя его с помощью mysqli_multi_query, который отлично подходит для других скриптов, создающих и заполняющих БД). На интерфейсе нет ошибок, никаких результатов (!). Все, что я получаю, это «ложь», и все. код ошибки равен 0, нет сообщения об ошибке.
Для меня это большой WTF, и я надеюсь, что вы можете указать мне в правильном направлении – как я могу исправить это и установить процедуры с PHP?
PS: задан и проверен доступ root / admin (в конце концов, я только что создал БД с тем же соединением, созданными пользователями, вставленными таблицами и т. Д.).
Я не тестировал, но я не удивлюсь mysqli_multi_query()
ожидая иметь одинаковый разделитель для каждого запроса. Попробуйте упаковать создание хранимой процедуры в одном запросе без использования модификатора DELIMITER?
Поэтому вместо
<?php $results = mysqli_multi( 'DELIMITER $$ USE `dbname`$$ CREATE PROCEDURE `procname`(IN inputparameters) BEGIN ... procedure goes here ; END$$ DELIMITER ; '); ?>
Просто сделайте это
<?php $result = mysqli_query('CREATE PROCEDURE `procname`(IN inputparameters) BEGIN ...; END');
И скажите нам, если это работает 🙂
Подвести итог:
DELIMITER реализован на стороне клиента, а не на сервере.
Если у вас есть хороший драйвер или API, это может позаботиться об этом. PHP mysql / mysqli, на данный момент, нет.
Если вам нужно использовать другой разделитель (например, поскольку разделитель по умолчанию появляется внутри скриптов), вам необходимо самостоятельно закодировать / убрать свой SQL или разбить его, поэтому вам не нужно менять разделитель. Здесь нет помощи от PHP.
DELIMITER – это то, что фактически использует клиентское приложение mysql. Я считаю, что клиентское приложение отвечает за разблокирование запросов, которые он отправляет в Mysql. Например, это делает PHPMyAdmin.
Вместо того, чтобы всю ночь писать сценарий для анализа MySQL в запросах, используйте код, который я написал. Вы найдете его в функции scriptToQueries, здесь:
http://wush.net/svn/luckyapps/pie/trunk/framework/classes/Db/Mysql.php
НАСЛАЖДАТЬСЯ
EDIT: после написания этого ответа я портировал код на бесплатную платформу Q, в которой вы можете изучить код: https://github.com/EGreg/Platform/blob/master/platform/classes/Db/Mysql.php# L824