2

慢慢地为我雇主的三个主要模式之一构建一个起始 changeSet xml 文件。唯一的阻碍是合并了由 liquibase 管理的相当大的 MySQL 存储过程库。

一个 sproc 处理起来有点麻烦:前几个语句就像

use TargetSchema;
select "-- explanatory inline comment thats actually useful --" into vDummy;

set @@session.sql_mode='TRADITIONAL' ;

drop procedure if exists adm_delete_stats ;

delimiter $$

create procedure adm_delete_stats(
...rest of sproc

我删除了 use 语句,因为它会适得其反,但真正的问题是set @@session.sql_mode导致异常的语句,例如

 liquibase.exception.MigrationFailedException: Migration failed for change set ./foobarSchema/sprocs/adm_delete_stats.xml::1293560556-151::dward_autogen dward:
 Reason: liquibase.exception.DatabaseException: Error executing SQL ...

然后delimiter声明是另一个绊脚石。

做尽职调查时,我发现这个被拒绝的 MySQL 错误报告和这个 MySQL 论坛线程在这里更深入地解决了这个问题

无论如何我可以使用 Liquibase 目前存在的 sproc 脚本,还是我必须重新编写数百个存储过程?

我尝试过 createProcedure、sqlFile 和 sql liquibase 标签,但运气不佳,因为我认为核心问题是 set、delimiter 和类似的 SQL 命令在传递到服务器之前要由客户端解释器解释和执行.

4

2 回答 2

4

是的,我认为问题在于您的脚本假设它将通过 mysql 客户端运行,该客户端具有 JDBC 中不存在的附加功能。

Liquibase 将在分隔符上拆分您的语句(默认为 ; 但可以使用 delimiter 属性进行更改),然后将每个语句提供给数据库。如果您指定 $$ 作为分隔符,您可以删除 "delimiter $$" 行,但它之前的每一行都需要有 ; 替换为 $$。除此之外,还有其他特定于客户端的 SQL,例如 @@session 行。我认为如果不通过客户,这可能是不必要的,但我不完全确定它的作用。

您应该能够使您的程序正常工作,但这需要重新编写。

如果您不想重新编写所有程序,则可以使用类似executeCommand标记的东西,它允许您调用 mysql 客户端并输入现有脚本。你失去了 liquibase 给你的一些东西,比如 updateSQL 模式,你必须确保 mysql 客户端存在于你运行你的更新日志的任何地方,但这会让你不必重写你的脚本。

于 2010-12-31T01:50:58.430 回答
2

这对我有用: http ://comments.gmane.org/gmane.comp.db.liquibase.user/480

简而言之,它是这样说的:

<changeSet id="123321-4" author="ehrhardt">
  <sql>DROP PROCEDURE IF EXISTS curdemo;</sql>
  <sql splitStatements="false" stripComments="false">
    <![CDATA[ 
      CREATE PROCEDURE curdemo()
      BEGIN
        DECLARE done INT DEFAULT 0;
        blah..
        blah..
      END;
    ]]>
  </sql>
  <sql>call curdemo();</sql>
</changeSet>
于 2012-11-26T22:23:47.297 回答