In my model I defined some procedures. The code (generated by MySQL Workbench) contains DELIMITER
definitions, so the procedures look like:
-- s
From comments:
I don't want remove the
DELIMITER
statements. And actually I want to get it working without to execute every statement manually
That's not how it works.
To understand why, you need to understand how the mysql
CLI -- and any other program that can read and execute a dump file like this -- actually handles it.
DELIMITER
is not something the server understands.
DELIMITER
is used to tell the client-side parser what the current statement delimiter should be, so that the client-side parser can correctly split the statements and deliver one at a time to the server for execution.
From the docs. Note carefully that mysql
, every time it is used here, refers to the mysql
client utility -- not the server.
If you use the
mysql
client program to define a stored program containing semicolon characters, a problem arises. By default,mysql
itself recognizes the semicolon as a statement delimiter, so you must redefine the delimiter temporarily to causemysql
to pass the entire stored program definition to the server.
To redefine the
mysql
delimiter, use thedelimiter
command. [...] The delimiter is changed to//
to enable the entire definition to be passed to the server as a single statement, and then restored to;
before invoking the procedure. This enables the;
delimiter used in the procedure body to be passed through to the server rather than being interpreted bymysql
itself.
https://dev.mysql.com/doc/refman/5.7/en/stored-programs-defining.html
So, to handle such a file, you need a client-side parser that does the same thing mysql
does... and here, the code you are writing is (needs to be) the client-side statement parser. So you are the one that needs to write the logic to handle the delimiter.
To do what you want, you have to interpret the DELIMITER
statements, use them to keep track of the current statement delimiter, but do not send them to the server.
Then, you have to read through the input one line at a time, buffering what you've read, until you find the specified delimiter at the end of the line, and send the resulting statement to the server -- excluding the actual statement delimiter from what you send... so, for example, you would not send the ending $$
after the procedure body (unless the current statement delimiter is ;
, which you can either send or not send -- the server doesn't care.) Then empty the buffer and start reading again until you see another instance of a delimiter (and send the statement to the server) or match a DELIMITER
statement and set your code's current delimiter variable to match it so that you correctly identify the end of the next statement.
Delimiters is a thing that you don't need with PDO. You can just run your queries as is
$pdo->query("CREATE DATABASE ...");
$pdo->query("CREATE TABLE foo ...");
$pdo->query("BEGIN
DECLARE ... ;
OPEN ... ;
SET ... ;
... ;
END");
as simple as that
I met same problem with you when I tried with PostgreSQL. The problem seems PDO just allow you execute 1 query 1 time. As mentioned: PDO::exec() executes an SQL statement in a single function call, returning the number of rows affected by the statement
. In php manual
Could you try this:
$stmt = $db->prepare($sql);
$stmt->execute();
Or with mysqli
: multi_query
. php manual
Here my whole class: http://sandbox.onlinephpfunctions.com/code/f0528fda6d7bd097c3199f1f3c019805a163ae3a