【发布时间】:2020-02-12 12:11:24
【问题描述】:
我有一个带有 Oracle SQL 数据库的 Spring CRUD 应用程序。
我有几个集成测试并使用@Sql 注释运行.sql 文件,这些文件在运行测试之前将数据库置于所需状态。到目前为止,我的任何 .sql 脚本都没有问题,尽管它们都是非常简单的 INSERT 和 DROP 语句。
我现在正在尝试设置一个场景,其中数据库在特定表中保存数千条记录。我不关心内容,只关心记录的数量。
为了复制这个场景,我编写了以下 SQL 脚本:
DECLARE
id integer := 1;
BEGIN
WHILE id <= 3000
LOOP
INSERT INTO USER (ID, FIRST_NAME, LAST_NAME, AGE)
VALUES (id, 'John', 'Smith', 32);
id := id + 1;
END LOOP;
END;
我已经使用 IntelliJ 运行了这个脚本,它按预期工作。
但是,当我将脚本放入@Sql 注释时,我遇到了以下错误:
org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of class path resource [sql/setUp.sql]: DECLARE id integer := 1; nested exception is java.sql.SQLException: ORA-06550: line 1, column 23:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
我不知道如何解决;我遇到过类似的问题,解决方案只是缺少分号,但这里似乎并非如此。 更令人费解的是,我尝试通过@Sql 注解运行以下脚本:
BEGIN
INSERT INTO USER (ID, FIRST_NAME, LAST_NAME, AGE)
VALUES (1, 'John', 'Smith', 32);
END;
这产生了以下错误,这更没有意义:
org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of class path resource [sql/test.sql]: BEGIN INSERT INTO USER (ID, FIRST_NAME, LAST_NAME, AGE) VALUES (1, 'John', 'Smith', 32); nested exception is java.sql.SQLException: ORA-06550: line 1, column 87:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
;
最值得注意的是删除 BEGIN 和 END 语句(只留下 INSERT INTO 语句)是可行的。
那么 Spring JDBC 是否根本不支持 BEGIN/END 块?我不知道的预测试 @Sql 注释是否有限制?还是我错过了一些非常明显的事情?
【问题讨论】:
-
请提供minimal reproducible example。问题似乎是,无论您在做什么都是在
;上拆分以发送单个语句(因为 JDBC 本身仅支持单个语句执行)。要执行这样的脚本,通常需要以某种方式切换或禁用语句终止符才能发送整个内容。这意味着您可能需要微调@Sql的@SqlConfig(例如separator的值)。 -
@MarkRotteveel:Oracle JDBC 驱动程序确实支持运行匿名 PL/SQL 块,因为它实际上是一条语句。可能是 Spring 试图将 看起来 的多个语句分开
-
@a_horse_with_no_name 是的,
@Sql的 default 将在;上拆分。所以就 Spring 而言,在遇到每个;之后,都会启动一个新语句。 -
不是答案,因为我不确定它是否正确,但您可以尝试在
END;语句之后添加另一行,第一列中只有一个/字符。 -
@MarkRotteveel 感谢您的建议,我找到了解决方案。非常感谢!
标签: java spring oracle jdbc plsql