Как вставить/создать хранимые процедуры в MySQL из PHP?
-
14-10-2019 - |
Вопрос
У меня есть несколько сохраненных процедур, сделанных с помощью Workbench MySQL. Они работают отлично, когда используют MySQL Workbench, чтобы поместить их в мой тест DB.
Теперь я готовлю сценарии создания БД для развертывания, и это единственный, что дает мне проблемы. Когда я использую командную строку / оболочку MySQL, сценарий отлично работает. Только когда я использую интерфейс PHP MySQL (i) для выполнения скрипта - он не работает. Без комментариев.
Я использую сценарии создания процедуры, поскольку для меня генерирует Workbench MySQL; то есть у него есть этот шаблон:
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 Commandline. Но это не может ничего достичь, когда я выполняю его через интерфейс PHP MySQLI (выполняя его с помощью mysqli_multi_query, что прекрасно работает для других сценариев, создающих и заполняет DB). В интерфейсе нет ошибки, нет результатов (!). Все, что я получаю, это «ложь», и это все. Код ошибки составляет 0, нет сообщения об ошибке.
Это большой WTF для меня, и я надеюсь, что вы сможете указать мне в правильном направлении - как я могу исправить это и установить процедуры с PHP?
PS: Доступ к корнеу/администратору дается и проверяется (в конце концов, я только что создал DB с тем же соединением, создал пользователей, вставленные таблицы и т. Д.).
Решение
Я не тестировал, но я не удивлюсь mysqli_multi_query()
ожидая иметь одинаковый разделитель каждой запросы. Попробуйте упаковать сохраненную процедуру создания в один запрос, не используя модификатор разделителя?
Так что вместо
<?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');
И скажите нам, работает ли это :)
Другие советы
Подвести итог:
Разделитель реализован клиентской стороной, а не сервер.
Если у вас есть хороший водитель или API, это может позаботиться об этом. Php mysql / mysqli, на данный момент нет.
Если вам нужно использовать другой разделитель (например, потому что разделитель по умолчанию появляется внутри сценариев), вы должны кодировать/избежать SQL самостоятельно или разбить его, чтобы вам не нужно было менять разделитель. Нет помощи от PHP здесь.
Разделитель - это то, что на самом деле использует клиентское приложение MySQL. Я считаю, что клиентское заявление несет ответственность за нарушение запросов, которые оно отправляет в MySQL. Это то, что делает phpmyadmin, например.
Вместо того, чтобы проводить целую ночь, написав сценарий, чтобы разобрать MySQL в запросы, используйте код, который я написал. Вы найдете его в функции ScriptToqueries, здесь:
http://wush.net/svn/luckyapps/pie/trunk/framework/classes/db/mysql.php
НАСЛАЖДАТЬСЯ
Изменить: с момента написания этого ответа я перенес код в бесплатную платформу Q, в которой вы можете изучать код: https://github.com/egreg/platform/blob/master/platform/classes/db/mysql.php#l824