Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

mysql - How to create a stored procedure containing a DELIMITER in PHP with PDO?

In my model I defined some procedures. The code (generated by MySQL Workbench) contains DELIMITER definitions, so the procedures look like:

-- schema
CREATE DATABASE ...
CREATE TABLE foo ...
-- procedures
DELIMITER $$
...
  BEGIN
    DECLARE ... ;
    OPEN ... ;
    SET ... ;
    ... ;
  END$$
DELIMITER ;

Now I need to "import" the SQL to the database via PDO. I tried to pass it as input for the PDO#exec(...), but noticed, that the execution stops on the line of the first DELIMITER definition.

I don't want remove the DELIMITER statements. So the the SQL code should remain the same.

How to use PDO to execute SQL code containing DELIMITER statements?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 cause mysql to pass the entire stored program definition to the server.

To redefine the mysql delimiter, use the delimiter 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 by mysql 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...