I have an issue in my site where I have to do a potentially large number of database updates -- something like this:
update foo set x = 1 where nid = 1
update foo set x = 17 where nid = 3
update foo set x = 3 where nid = 12
and so on, perhaps up to 100 calls or so. (The actual values in the calls would of course be computed by various bits of code; these are just the resulting MySQL calls that result.)
Rather than hitting the server repeatedly for each value of the calls, it seems prudent to concatenate all of them into a single string, which would presumably result in something like this:
db_query('update foo set x = 1 where nid = 1; update foo set x = 17 where nid = 3; update foo set x = 3 where nid = 12)
I've tried this, but it doesn't work -- I get a message something like:
user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ';update foo set x = 1 where nid = 1;update query: update foo set x = 17 where nid = 3;update foo set x = 3 where nid = 12; in /usr/sbin/httpd/htdocs/sunsetandgower/includes/database.mysql.inc on line 121.
MySQL is happy to accept multiple statements separated by a semicolon, but it looks like db_query is not.
So:
* Am I doing this the wrong way, or is db_query just not built to do stuff like this?
* Am I correct in worrying about the multiple trips to the server this code requires? I got into the habit of doing this sort of thing on a ColdFusion job, and it's seemed like a reasonable thing to do.
* Other advice? Thanks!
Comments
db_query can't do multi commands since PHP's mysql_query can't
db_query is Drupal's wrapper for mysql_query or mysqli_query (or whatever is appropriate for the selected database, such as pg_query for PostgreSQL database server).
Since the PHP functions mysql_query and mysqli_query can only execute one SQL statement, the db_query wrapper can also only execute one SQL statement.
("One SQL statement" means one statement regardless of line breaks..., It can optionally end with a semicolon, but cannot be more than one statement separated by semicolons).
If Drupal used mysqli_multi_query instead, then multiple SQL statements could be supported... but then this would require using PHP's "mysqli" instead of "mysql", and the Drupal wrapper would need to be able to return multiple result sets, thereby complicating the Drupal API. (Notice that while there is no pg_multi_query... it seems (according to PHP help) that pg_query DOES support multiple statements, though I have no PostgreSQL server to test with. )
This page http://drupal.org/node/119781 shows how to use multi_query, and you can mix it with the Drupal wrappers like this to make your own "my_multi_query", and use it similarly to db_query:
( Note two warnings, which are probably the reasons nothing like this is in "core":
1: Your $db_url in settings.php MUST be using "mysqli:", not "mysql:" or "pg:"
2: If returning large result sets, this function may not be practical since it stores all the results before returning. That is one major drawback of multi_query: You must deal with all the results before letting control get back to Drupal, since even a WatchDog call will cause a "sync" error, if you haven't finished retrieving all the result sets.
)