是否有针对 JDBC w/liquibase 和 MySQL 会话变量的解决方法?客户端 SQL 指令

发布于 2024-10-09 18:33:58 字数 1183 浏览 3 评论 0原文

慢慢地为我的雇主的三个主要架构之一构建一个入门变更集 xml 文件。唯一的障碍是合并了由 liquibase 管理的相当大的 MySQL 存储过程库。

处理一个存储过程有点痛苦:前几条语句就像

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 命令在传递到服务器之前应由客户端解释器进行解释和操作。

Slowly building a starter changeSet xml file for one of three of my employer's primary schema's. The only show stopper has been incorporating the sizable library of MySQL stored procedures to be managed by liquibase.

One sproc has been somewhat of a pain to deal with: The first few statements go like

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

I cut out the use statement as its counter-productive, but real issue is the set @@session.sql_mode statement which causes an exception like

 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 ...

And then the delimiter statement is another stumbling block.

Doing do dilligence research I found this rejected MySQL bug report here and this MySQL forum thread that goes a little bit more in depth to the problem here.

Is there anyway I can use the sproc scripts that currently exist with Liquibase or would I have to re-write several hundred stored procedures?

I've tried createProcedure, sqlFile, and sql liquibase tags without much luck as I think the core issue is that set, delimiter, and similar SQL commands are meant to be interpreted and acted upon by the client side interpreter before being delivered to the server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不回头走下去 2024-10-16 18:33:58

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

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

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

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

Yes, I think the problem is that your script is assuming it will run through the mysql client which has additional capabilities not present in JDBC.

Liquibase will split your statements on the delimiter (defaults to ; but can be changed with the delimiter attribute) then feeds each statement to the database. If you specify $$ as the delimiter, you can remove the "delimiter $$" line, but each line before it will need to have the ; replaced with $$. Besides that, there is other client-specific SQL like the @@session line. I think that may be unnecessary without going through the client, but I am not completely sure what it does.

You should be able to get your procedures to work, but it will take some re-writing.

If you would rather not re-write all your procedures, you could use something like the executeCommand tag which would allow you to call the mysql client and feed in your existing script. You loose some things liquibase gives you like the updateSQL mode and you owuld have to make sure the mysql client exists everywhere you run your changelog from, but it would keep you from having to rewrite your scripts.

软甜啾 2024-10-16 18:33:58

这对我有用:
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>

This worked for me:
http://comments.gmane.org/gmane.comp.db.liquibase.user/480

In short it says this:

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文