HSQLDB v2.7.2含复合语句的触发器在SQL工具中部署失败求助
问题概述
使用HSQLDB v2.7.2创建包含复合逻辑的BEFORE UPDATE触发器时,仅能在HyperSQL Database Manager中单独执行成功;但通过SQLTool或DBeaver(基于相同JDBC驱动)从SQL文件部署时会失败。根源是工具默认将*分号;*作为语句分隔符,触发器BEGIN ATOMIC...END块内的分号会被误判为整个CREATE TRIGGER语句的结束,导致语法报错。
报错信息
- SQLTool报错:
2023年12月1日 晚上8:00:10,SQLTool执行SQL文件时出错:org.hsqldb.cmdline.SqlTool objectMain 严重错误:在'file:my.sql'第4846行的SQL错误:"CREATE TRIGGER BCHS_BUPD_TRG BEFORE UPDATE ON PUBLIC.DMKR_ASLINE.BCHS REFERENCING NEW AS NEW FOR EACH ROW BEGIN ATOMIC SET NEW.BCHMODIFYTIME = CURRENT_TIMESTAMP" 意外的语句结束:需要分号;:第5行 org.hsqldb.cmdline.SqlTool$SqlToolException
- DBeaver报错:
SQL错误 [42590]: 意外的语句结束:需要分号;:第11行
解决方案
方案1:修改SQL文件适配SQLTool
在SQL文件开头添加SQLTool专属指令切换语句终止符,避免触发器内部分号被截断。修改后的SQL文件如下:
--#SET TERMINATOR @ DROP TABLE TEST2 IF EXISTS; CREATE TABLE TEST2 ( ID NUMERIC (38) NOT NULL GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1 ) , STATUS NUMERIC (10) DEFAULT 1 , STARTTIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP , MODIFYTIME TIMESTAMP, ENDTIME TIMESTAMP ); CREATE TRIGGER TEST2_BUPD_TRG BEFORE UPDATE ON TEST2 REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW BEGIN ATOMIC SET NEW.MODIFYTIME = CURRENT_TIMESTAMP; IF (NEW.STATUS = 9 AND (OLD.STATUS IS NULL OR OLD.STATUS <> NEW.STATUS)) THEN SET NEW.ENDTIME = CURRENT_TIMESTAMP; END IF; END@ --#SET TERMINATOR ;
说明:
--#SET TERMINATOR @:告诉SQLTool用@作为语句终止符,替代默认的分号- 触发器定义的结尾用
END@替代END; - 最后用
--#SET TERMINATOR ;把终止符改回默认值,不影响后续SQL执行
方案2:在DBeaver中临时切换语句分隔符
- 打开DBeaver的SQL编辑器,加载目标SQL文件
- 点击编辑器顶部的「语句分隔符」按钮(通常在运行按钮左侧,显示为
;) - 将分隔符改为
@ - 执行整个SQL脚本
- 执行完成后,再把分隔符改回
;即可
这样就能让DBeaver正确识别触发器的完整定义,不会提前截断语句。
内容的提问来源于stack exchange,提问作者Steven S.

