【问题标题】:How to check if MySQL query is valid without executing it?如何在不执行 MySQL 查询的情况下检查它是否有效?
【发布时间】:2008-12-18 13:47:18
【问题描述】:

我正在制作一个简单的工具,它将获取一串 MySQL 命令并运行它(在多个数据库服务器上依次运行)。我相信用户是明智的,但会发生错误,我正在寻找一种方法来防止基本的拼写错误:

有没有办法在运行时验证(相对简单的)MySQL 查询以查看它们在语法上是否正确?

我不是在寻找语义正确性,例如表名或连接适用性;就像 SQL 查询的拼写检查一样。

换句话说,

SELECT * FROM x;

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

将被标记为有效,而其中任何一个都不会:

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

对于SELECTs,我可以根据需要调整EXPLAIN - 运行EXPLAIN SELECT (...) 并注意错误,但有没有办法检查其他命令?

【问题讨论】:

    标签: mysql validation


    【解决方案1】:

    要验证查询,我使用 EXPLAIN 命令。您可以采用任何 SQL 查询并在其前面添加 EXPLAIN 并执行。 如果查询错误,将返回错误。

    例子:

    explain select * from users;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    |  1 | SIMPLE      | users | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    

    还有错误的查询

    explain select * from users2;
    ERROR 1146 (42S02): Table 'test.users2' doesn't exist
    

    附:解释也适用于插入、更新、删除。不仅选择

    【讨论】:

    • 这是正确答案。不知道为什么一个未回答被标记为正确答案,而正确答案在底部。
    • explain select * from users; MySQL 说ERROR 1146 (42S02): Table 'sakila.users' doesn't exist 现在select * from users; 给出ERROR 1146 (42S02): Table 'sakila.users' doesn't exist 那么怎么了?
    • 我认为表 'sakila.users' 不存在 :)
    【解决方案2】:

    不知道架构(例如,'x' 是表吗?)并编写 SQL 解析器。您的 MySQL 查询工具应该能够进行这种验证(如果您愿意,可以进行智能感知),但我从第一手经验知道,大多数(免费)MySQL 工具都很糟糕。

    “准备”查询可以满足您的要求,但它是运行时检查,而不是编译时检查 - 您似乎正在寻找编译时/离线解决方案。

    【讨论】:

    • 我正在寻找一种在脚本执行查询之前快速检查查询的方法。编写解析器会有些过火——如果它在第一台服务器上中断,它只会退出并出现错误(假设脚本用户(系统管理员)足够清醒,知道他们在做什么)。
    • +1 准备。据我所知,这是唯一的方法。
    • 似乎 MySQL 无法在空数据库上运行 PREPARE。并且一些语法错误没有显示出来,例如两个同名的字段。
    • 使用 phpMyAdmin,我将一些 SQL 复制到查询框中。我更改了参数以匹配我自己的架构,但需要通过添加 WHERE 子句来调整复制的查询以限制其效果。我没有注意到复制的查询末尾有一个;,所以它在整个表上执行。然后我从独立的WHERE 子句中收到一条错误消息。如果有办法在执行任何 SQL 语句之前检查它们的有效性,phpMyAdmin 可以在执行任何操作之前警告我错误。或者,也许 phpMyAdmin 可以将它们包装在一个事务中来解决这个问题!
    【解决方案3】:

    根据您的 MySQL 引擎和设置,您可以启动事务,尝试查询,然后进行回滚。假设脏读已关闭,那应该可以工作。

    【讨论】:

    • 哦,哇,我刚刚以同样的想法对 James Ogden 的回答发表了评论。我认为 phpMyAdmin 和任何其他允许多个查询的 RDMS 前端默认情况下应该自动将它们包含在事务中。
    【解决方案4】:

    您可以创建一个临时表来规避查询的副作用:

    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
    

    【讨论】:

      【解决方案5】:

      您可以使用您的代码和唯一名称临时创建一个存储过程。 然后你可以立即放下它。事务不能回滚 SP 创建。 但要小心,因为它只是语法验证,所以它不会检查一个对象(在你的查询中)是否存在。

      【讨论】:

        猜你喜欢
        • 2018-01-06
        • 1970-01-01
        • 2021-11-22
        • 2018-08-30
        • 1970-01-01
        • 1970-01-01
        • 2011-05-16
        • 2015-12-05
        • 1970-01-01
        相关资源
        最近更新 更多