tags:

views:

7162

answers:

4

So I have an SQL dump file that needs to be loaded using mysql_query(). Unfortunately, it's not possible to execute multiple queries with it.

-> It cannot be assumed that the mysql command-line client (mysql --help) is installed -- for loading the SQL file directly

-> It cannot be assumed that the mysqli extension is installed

/* contents of dump.sql, including comments */
DELETE FROM t3 WHERE body = 'some text; with semicolons; scattered; throughout';
DELETE FROM t2 WHERE name = 'hello';
DELETE FROM t1 WHERE id = 1;

The explode() below won't work because some of the dump content's values contain semicolons.

$sql = explode(';', file_get_contents('dump.sql'));
foreach ($sql as $key => $val) {
    mysql_query($val);
}

What's the best way to load the SQL without modifying the dump file?

+6  A: 

You have more problem cases than just semicolons within strings.

  • Script builtin commands that cannot be executed by mysql_query(), like USE.
  • Statements that are not terminated with a semicolon, like DELIMITER.
  • Statements that contain semicolons, but not inside quotes, like CREATE PROCEDURE.

See examples in my answer to the similar question "Loading .sql files from within PHP".

I don't know of an easy way to handle this task, without shelling out to the mysql command-line client. I realize you said you can't rely on that client being present, but without that client, you need a large amount of PHP code to parse the script and execute statements appropriately.

You may be able to find such code inside the phpMyAdmin product. However, that product is licensed under the GPL, so if you use any of the code, you must also license your own project under the GPL.

Bill Karwin
+1  A: 

Occam's razor strikes again.

The above explode() function wasn't going to work because there are semicolons in the values. However, what I failed to realize (and mention) is that semicolons always preceed newlines in the SQL dump file. Alas,

$sql = explode(";\n", file_get_contents('dump.sql'));
foreach ($sql as $key => $val) {
    mysql_query($val);
}

Also, thanks for your help, Bill.

Matt
You do have cases of semicolon at the end of a line, but it isn't the end of a statement, e.g. inside the body of a procedure or trigger definition. And statements like DELIMITER that don't end in a semicolon.
Bill Karwin
+1  A: 

There is a bigger issue here. You might have statements that rely on other statements. You can't just execute them linearly blindly.

FlySwat
Could always tell mysql to ignore unique checks and foreign key checks before running your list of queries which would resolve many issues with query order.
enobrev
Right, tell the database to ignore the sanity checks implemented to preserve data integrity, That's a sure fire way to succeed.
FlySwat
@enobrev: And what would happen if you turn sanity checking back on afterwards? exactly; more problems.
Kris
depending on what you're importing, turning off sanity checks isn't so dire. Sure if we're talking inserts, it's a problem but if all you're doing is altering the structure, then all those sanity checks are going to go bananas every time you try to remove a table that has incoming references.
enobrev
A: 

Thanks alot this solves my problem :)

CTO