Liquibase:MySQL 存储过程中的 SQL 语法错误
Posted
技术标签:
【中文标题】Liquibase:MySQL 存储过程中的 SQL 语法错误【英文标题】:Liquibase: SQL syntax error in a MySQL stored procedure 【发布时间】:2018-02-16 10:36:01 【问题描述】:我尝试通过 Liquibase 运行 mysql 存储过程 SQL 脚本,但没有成功。
db.storedprocedure.xml的内容:
<changeSet author="zzz" id="1" runOnChange="true" runInTransaction="true">
<sqlFile path="changelogs/change_03.sql"
relativeToChangelogFile="true"
endDelimiter="$$"
stripComments="false"
splitStatements="false"/>
</changeSet>
我的SQL文件change_03.sql的内容:
$$
CREATE PROCEDURE `liqui01`.`User_Search`(
INOUT id INT,
OUT name VARCHAR(50)
)
BEGIN
SET @sql = CONCAT("SELECT id, name FROM user WHERE da.MarketId = ", id );
PREPARE stmt from @sql;
EXECUTE stmt;
END$$
它显示如下错误:
运行 Liquibase 时出现意外错误:您的 SQL 中有错误 句法;检查与您的 MySQL 服务器版本相对应的手册 在 '$$ ...
附近使用正确的语法
我试过把“$$”改成其他的分隔符,或者把SQL放到XML文件的<sql>
标签里面,都不行。
任何建议将不胜感激!
更新 1
@Shadow 给出了正确答案(很遗憾我无法将其标记为答案,因为它在 cmets 中),从 sql 脚本中删除分隔线将使其工作,谢谢他!
现在的问题是:如何使用“endDelimiter”参数?
【问题讨论】:
为什么在存储过程的开头有一个 $$?这不是必需的。另请注意,此查询不需要准备好的语句(这与您收到的错误消息无关) @Shadow 嗨,伙计,你节省了我的时间!仍然想知道为什么“endDelimiter”不起作用,以及为什么他们提供这样的参数......我从其他存储过程中复制了脚本,并删除了一些其他部分,只是为了测试 liquibase,但忘记删除“prepare stmt”部分: ) 请参考完整程序-> ***.com/questions/1267172/mysql-delimiter-error/… 【参考方案1】:我在互联网上搜索了解决方案。看来 Liquibase 将在 update
命令上很好地创建存储过程。但是在 updateSQL
命令上崩溃了,因为它输出了无效的 SQL。
我的解决方案是将 cmets 添加到 changesets sql
标签。目的是使用正则表达式来清理输出 sql。
我正在使用的.sql
文件有一些 liquibase 不喜欢的关键字,例如DELIMITER
,所以我使用 <modifysql>
和 <regExpReplace>
对 .sql
文件进行 lint / sanitize。
这样,.sql
文件就可以被 liquibase 使用,并且可以在update
上成功运行而不会出现错误。
但是,我们仍然会在 updateSQL
上输出无效的 SQL。为了解决这个问题,我在无效的输出.sql
文件上使用另一个正则表达式搜索/替换来查找 cmets; -- DELIMITER $$
等
例子:
<changeSet id="Test1" author="author_name" context="master" runOnChange="true">
<validCheckSum>any</validCheckSum>
<sql><![CDATA[
DROP PROCEDURE IF EXISTS `sp_myProcedure`;
-- DELIMITER $$
]]></sql>
<createProcedure path="yourpath/procs/sp_myProcedure.sql" relativeToChangelogFile="true" />
<sql><![CDATA[
-- $$ DELIMITER;
]]></sql>
<modifySql>
<regExpReplace replace="[^]+CREATE PROCEDURE" with="CREATE PROCEDURE"/>
</modifySql>
<modifySql>
<regExpReplace replace="END\s*\$\$[^]*" with="END"/>
</modifySql>
</changeSet>
【讨论】:
【参考方案2】:liquibase 内部将delimiter
命令添加到命令开头,您必须删除或用$$
注释第一行:
-- $$
CREATE PROCEDURE `liqui01`.`User_Search`(
...
END$$
【讨论】:
感谢您的建议,但不幸的是它不起作用,错误消息有点不同:... use near '' at line 12 ... (not "near '$$' ...") 删除CREATE PROCEDURE
之前的所有字符并运行liquibase。
谢谢伊万,但这不起作用,它显示的错误与我之前的评论相同。以上是关于Liquibase:MySQL 存储过程中的 SQL 语法错误的主要内容,如果未能解决你的问题,请参考以下文章
Learning-MySQL:视图触发器存储过程函数流程控制
如何使 liquibase 的 LoadData 标签不区分大小写?