【问题标题】:Liquibase: <changeSet> with multiple SQL statements in <sql> using parametersLiquibase: <changeSet> 在 <sql> 中使用参数的多个 SQL 语句
【发布时间】:2021-05-28 03:32:11
【问题描述】:

我需要在 Liquibase 中运行准备好的语句:

<changeSet id="53" author="foo">
    <sql dbms="!h2, mysql" splitStatements="true">
        SET @table_name = 'AUDIT_EVENT';
        SET @column_name = 'ACTOR_ID';
        SET @constraint_name = (
        SELECT rc.CONSTRAINT_NAME
        FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS rc
        INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS kcu
        ON kcu.CONSTRAINT_CATALOG = rc.CONSTRAINT_CATALOG
        AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
        WHERE kcu.TABLE_NAME = @table_name
        AND kcu.COLUMN_NAME = @column_name
        );
        SET @s = concat('ALTER TABLE ', @table_name, ' DROP FOREIGN KEY ', @constraint_name);
        PREPARE stmt FROM @s;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt
    </sql>
</changeSet>

如果我将 splitStatements 设置为 true,那么我认为参数不会在语句中持续存在,所以可以理解的是,我收到一条错误消息,指出 @s 为 NULL:

Reason: liquibase.exception.DatabaseException: 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 'NULL' at line 1 [Failed SQL: PREPARE stmt FROM @s]

如果我将 splitStatements 设置为 false,并删除除前两个 SETs 之外的所有内容,以确保不是嵌套的 SELECT 导致问题,我会得到:

Reason: liquibase.exception.DatabaseException: 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 'SET @column_name = 'ACTOR_ID'' at line 2 [Failed SQL: SET @table_name = 'AUDIT_EVENT';
        SET @column_name = 'ACTOR_ID';]

我认为 endDelimiter 默认为 ; 的问题。所以我尝试了FOO

    <sql dbms="!h2, mysql" splitStatements="false" endDelimiter="FOO">
        SET @table_name = 'AUDIT_EVENT';
        SET @column_name = 'ACTOR_ID';
        FOO
    </sql>

我得到...

Reason: liquibase.exception.DatabaseException: 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 'SET @column_name = 'ACTOR_ID';
            FOO' at line 2 [Failed SQL: SET @table_name = 'AUDIT_EVENT';
            SET @column_name = 'ACTOR_ID';
            FOO]

我觉得我不明白发生了什么。我检查了 SQL 是否在 MySQL Workbench 中工作。有什么见解吗?

【问题讨论】:

    标签: mysql sql liquibase


    【解决方案1】:

    更新

    所以,我认为 splitStatements=false 让我摆脱了 NULL @s 错误,因此假设参数(或我现在知道的“用户/会话变量”)不能分裂时坚持。但这全错了。这些变量确实在语句中持续存在:在会话期间。

    splitStatements=false 只是用一个新错误掩盖了原始错误,这确实与 MySQL 不允许同时进行多个查询有关。当我使用 allowMultiQueries=true 解除阻塞 that 时,我收到了一个指向第 1 行的 new 错误,这最终让我修复了 原来的错误,是我的表名错误(大写而不是小写)。

    我从未意识到的是,错误的表名也导致 @s 最终为 NULL。


    旧的“解决方案”

    我没有意识到默认情况下 MySQL 不允许多个查询。我必须在 JDBC URL 中添加它作为查询参数:

    jdbc:mysql://%s:%d/%s?user=root&allowMultiQueries=true
    

    据我了解,这不是可移植路径。但由于我使用 Liquibase 来准确指定在哪个数据库上运行这些语句,所以我认为没关系。

    【讨论】:

      猜你喜欢
      • 2013-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-07
      相关资源
      最近更新 更多