【问题标题】:Flyway MySQL syntax errorFlyway MySQL 语法错误
【发布时间】:2012-10-14 08:44:36
【问题描述】:

我们使用 Flyway 1 个月以来没有遇到任何问题。

但是,今天我尝试添加一个很长(超过 1500 行)的新迁移脚本,遇到了一个奇怪的 MySQL 语法错误。

我在 MySQL Workbench 中打开了这个脚本,没有报告语法错误,脚本执行没有错误。

这个名为“V10012__insert-acceptance-testing-event-moment-passed.sql”的脚本包含以下说明。

  • 插入语句 1
  • 插入语句 2
  • ...
  • INSERT 语句 LAST - 1
  • 最后插入语句

MySQL报错如下:

[错误] 由 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 你有一个 SQL 语法错误;检查与您对应的手册 MySQL 服务器版本,用于在“INSERT INTO”附近使用正确的语法 video_feedback (id, youtube_video_id) 值 ( 1102, /* id */' 在第 232 行 [错误] com.googlecode.flyway.core.migration.MigrationException:迁移到 10012版本失败!请恢复备份并回滚数据库 和代码!

错误是在“INSERT statement LAST”语句中报告的。

但是,如果我在脚本中反转“INSERT statement LAST”和“INSERT statement LAST - 1”,则会在“INSERT statement LAST - 1”(现在位于文件末尾)上报告错误。所以我在“INSERT statement LAST”中没有错误,因为 Flyway 成功执行了它。

另外,如果现在我从脚本“V10012_insert-acceptance-testing-event-moment-passed.sql”中完全删除“INSERT statement LAST”语句,并将该语句放入一个名为“V10013”的新文件中_test.sql'flyway 成功执行了我所有的迁移脚本!

那么,我最初的“V10012__insert-acceptance-testing-event-moment-passed.sql”脚本中可能存在什么问题?

是否存在可能的脚本大小限制?

以下是关于我的环境的有用信息:

  • 我的脚本使用了很多 /* */ cmets
  • Flyway Maven 插件 1.7
  • Maven 2.0.3
  • mysql:mysql-connector-java:5.1.21
  • MySQL 5.5.X
  • Java JDK 1.7.0_09-b05
  • Windows 7

【问题讨论】:

    标签: mysql jdbc flyway


    【解决方案1】:

    我终于找到了问题的原因。

    在我的脚本中:

    ... 
    ...
    
    /* INSERT statement LAST - 1 */ 
    INSERT INTO `table_1` (`id`, `string_1`, `string_2`)
    VALUES (
        1, 
        'aaa',   /* COMMENT 1*/
        'bbb'    /* COMMENT 2*/
    );
    
    /* INSERT statement LAST */
    INSERT INTO `table_2` (`id`, `string_3`)
    VALUES (
        1,       /* COMMENT 3   */
        'cccc'   /* COMMENT 4    */
    );
    

    问题似乎出在 COMMENT 2 和 COMMENT 4。如果我删除主题 flyway 成功执行我的所有迁移脚本。

    例如,此脚本将起作用:

    ... 
    ...
    
    /* INSERT statement LAST - 1 */ 
    INSERT INTO `table_1` (`id`, `string_1`, `string_2`)
    VALUES (
        1, 
        'aaa',   /* COMMENT 1*/
        'bbb'    
    );
    
    /* INSERT statement LAST */
    INSERT INTO `table_2` (`id`, `string_3`)
    VALUES (
        1,   /* COMMENT 3   */
        'cccc'   
    );
    

    那么,也许这是 Flyway 解析器中的一个错误?

    我今天没有时间测试它,但似乎只有在以下情况下才会出现此错误:

    • 我们在 VARCHAR(或我想的其他字符串列类型)之后有注释
    • 此注释位于 ')' 字符之前

    这个问题似乎只有在一个 SQL 脚本中存在多个插入语句时才能重现。

    此外,我认为没有放在')'之前的 cmets 是正确的,例如:

    /* INSERT statement LAST */
    INSERT INTO `table_2` (`id`, `string_3`)
    VALUES (
        1,   /* COMMENT 3   */
        'cccc',  /* COMMENT 4   */
        'dddd'
    );
    

    COMMENT 3 和 COMMENT 4 在 Flyway 中通过,因为它们位于 ',' 之后和字符串值之前,但它们没有放在 ')' 字符之前。

    希望这会有所帮助;-)

    【讨论】:

    • 我遇到了类似的问题。你的 cmets 里面没有引号吗?
    【解决方案2】:

    由于飞行路线,这不太可能。这几乎肯定与 flyway 使用的 MySQL 驱动程序有关。使用 MySql 本机客户端,您自然会认为它可以处理任何合法语法。甚至是“可选”的评论块

    我知道在 MySql 的 jdbc 驱动程序中 SURE 的一个问题是它不能处理动态分隔符交换。因此,触发器和存储过程可能会成为一个问题,特别是如果它们是使用mysqldump 生成的,但随后您使用 Java 应用程序重新摄取。

    如果您查看here 并转到spring.datasource.separator,您会看到系统范围(基本上)设置为;

    现在想象一下当涉及到脚本中的这一行时它会如何表现:

    DELIMITER ;;
    CREATE FUNCTION `int2vancode`(id BIGINT(20)) RETURNS varchar(255)
    BEGIN
        DECLARE num VARCHAR(10);
        DECLARE length INT;
        SET num = conv(id, 10, 36);
        SET length = char_length(num);
    
        return CONCAT(conv(length -1 , 10, 36), num);
    END ;;
    DELIMITER ;
    

    Java 驱动程序很笨,不会解释任何这些语句,即使 DELIMITER 语句显然是针对客户端的

    我现在遇到一个问题,即本机客户端执行每个脚本都没有问题,但 flyway 说我有一个语法错误,即使 intellij 也看不到。

    ** 更新**

    我解决了我的问题,它或多或少地证实了我看到的问题: 我有一个创建表:

    CREATE TABLE `Position` (
      PositionID INT NOT NULL AUTO_INCREMENT,
      `Name` varchar(200) COLLATE utf8_unicode_ci NOT NULL
    );
    

    我不得不转义 NamePosition 才能让 flyway 接受它,即使我的 bash 脚本迭代执行这些脚本没有问题。

    也许我可以告诉 Java 驱动程序一些帮助?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-04
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多