views:

1764

answers:

3

I'm making a simple tool that will get a string of MySQL commands and run it on several DB servers sequentially. I trust the users to be sensible, but mistakes happen. I'm wondering:

Is there a way to validate, at runtime, (relatively simple) MySQL queries to see if they're syntactically correct?

In other words,

SELECT * FROM x;

or

INSERT INTO x SET id=1,bar="foo";

would be marked valid, whereas any of those would not:

SELECT FROM x;
SECLET * RFOM x;
ISNETR INTO x SET id=1;
HJBGYGCRYTCY;

For SELECTs, I could bend EXPLAIN to my needs - run EXPLAIN SELECT (...) and watch for errors, but is there a way to check for other commands as well? I'm searching MySQL docs and Google, so far no luck.

Thanks for any hints.

Edit: hopefully clarified a bit

+4  A: 

Not without knowledge of the schema (for example, is 'x' a table?) and writing a SQL parser. Your MySQL query tool should be able to do that kind of validation (intellisense if you like) but I know from first hand experience, most of the (free) MySQL tools are pretty abysmal.

'Preparing' the query would do what you want, but is a runtime check, not a compile time check - you seem to be looking for a compile time/offline solution.

James Ogden
I was looking for a quick way of checking the queries before the script executes them. Writing a parser would be way overboard - if it breaks on the first server, it'll just exit with an error (supposedly the script users (system admins) are sane enough to know what they're doing).
Piskvor
+1 For prepare. That's the only way to do it to my knowledge.
Abyss Knight
It seems that MySQL can't run PREPARE on an empty db. And some syntactical errors are not shown up, for example two field with the same name.
powtac
+3  A: 

You could create a temporary table to circumvent side effects of the query:

CREATE TEMPORARY TABLE users SELECT * FROM users;
INSERT INTO users(name) VALUES('UniqueName');
DROP TABLE users;
SELECT * FROM users WHERE name='UniqueName'; -- Should return 0 results
soulmerge
+3  A: 

Depending on your MySQL engine and settings, you could start a transaction, try the query, and then do a rollback. Assuming dirty reads are off, that should work.

Eli