Flyway执行批处理脚本遇SQL Error 586:预准备语句句柄无效
结合你描述的情况——脚本本身可运行但后续执行失败、其他开发者环境正常、已显式设置ANSI_NULLS和QUOTED_IDENTIFIER,我来分享几个针对性的排查方向:
检查Flyway连接配置与连接池差异
其他开发者环境正常,说明问题大概率出在你的本地连接配置上。重点排查:- 连接字符串参数:是否包含
ApplicationIntent=ReadOnly这类可能改变会话行为的参数?或者是否开启了连接池的会话复用(比如HikariCP的autoCommit设置),导致前一个脚本的会话设置残留污染了后续执行? - 尝试临时禁用连接池,用单连接模式执行Flyway migrate,看是否能解决问题。
- 连接字符串参数:是否包含
验证脚本执行过程中的会话上下文一致性
虽然你在脚本开头和结尾显式设置了ANSI_NULLS和QUOTED_IDENTIFIER,但GO语句会分隔批处理,可能在批处理之间会话设置被意外修改。可以在每个GO前后添加查询语句,实时监控会话状态:SELECT SESSIONPROPERTY('ANSI_NULLS') AS ANSI_NULLS, SESSIONPROPERTY('QUOTED_IDENTIFIER') AS QUOTED_IDENTIFIER GO对比执行过程中这些值的变化,确认是否有批处理意外修改了设置。
检查数据库对象的定义设置
SQL Server中,对象(比如函数、视图)的定义会绑定创建/修改时的ANSI_NULLS和QUOTED_IDENTIFIER设置。如果你的环境中这些对象的原有设置和脚本中的设置不一致,可能导致ALTER操作触发会话冲突:
执行以下查询查看目标函数的绑定设置:SELECT uses_ansi_nulls, uses_quoted_identifier FROM sys.objects WHERE name = 'CalculateActionStatus' AND schema_id = SCHEMA_ID('dbo')如果查询结果和脚本中设置的
ON不一致,尝试先删除原有对象再重新创建,或者确保ALTER操作时的会话设置与对象绑定的设置匹配。排查Flyway或SQL驱动版本差异
确认你使用的Flyway版本、SQL Server驱动版本(比如JDBC驱动)是否和其他开发者一致。某些旧版本的驱动或Flyway可能存在批处理执行时的会话状态管理bug,尝试切换到和其他开发者相同的版本再测试。检查数据库服务器的会话初始设置
虽然你确认了默认设置一致,但可能你的会话初始设置存在差异。手动打开查询窗口连接到目标数据库,执行以下语句查看初始会话设置:SELECT SESSIONPROPERTY('ANSI_NULLS') AS Initial_ANSI_NULLS, SESSIONPROPERTY('QUOTED_IDENTIFIER') AS Initial_QUOTED_IDENTIFIER和其他开发者的结果对比,若有差异,检查连接字符串是否强制指定了相关参数,或者数据库用户的默认设置是否被修改。
简化脚本定位问题点
把有问题的脚本简化,比如先注释掉ALTER函数的逻辑,只保留CREATE语句和SET操作,看是否还会报错;或者去掉开头结尾的SET语句,用数据库默认设置执行。通过逐步缩小范围,定位是SET语句的问题、函数定义的问题,还是Flyway的批处理执行逻辑问题。
内容的提问来源于stack exchange,提问作者Abhi.Net

