如何在 H2 嵌入式数据库中获取序列的下一个值?

7

背景

我使用Oracle作为数据库,并在集成测试中使用H2嵌入式内存数据库。

我已经在H2中创建了一些表格,并能够获得插入的数据。但是,我无法检索在H2中创建的序列的当前序列值。

我知道Oracle和H2不同,使用类似但不同的语法。我也知道你可以在H2内存数据库中定义一些别名,并嵌入Java代码来代替Oracle SQL函数。这提醒我,在H2数据库上使用Oracle的语法检索序列值必须有一种解决方法。

问题

如何使Oracle用于选择序列当前值的语法适用于H2?我需要创建别名并编写嵌入式Java代码来代替Oracle的语法吗?我的选择是什么?

待测试的代码使用以下假设但类似的SQL:

select myschema.mysequence.nextval from dual

但是我收到了以下错误信息:

org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "nextval" not found [42122-199]

显然,由于语法差异,这种方法不起作用。我正在寻找一种解决办法,而不必更改使用 Oracle 语法的测试代码。

更新

我正在使用 Spring JDBC 的 EmbeddedDatabaseBuilder,这意味着我没有连接到一个独立的 H2 数据库实例,而是连接到一个动态创建的实例中,在其中包括用于创建数据库对象的 DDL 脚本。

以下帖子及其接受的答案有助于解决问题。

Spring 嵌入式数据库支持不同的 SQL 方言吗?

1个回答

8

H2实际上支持Oracle风格的表达式,包括版本1.4.199:

set mode Oracle;
create schema myschema;
create sequence myschema.mysequence;
select myschema.mysequence.nextval from dual;
> 1
select myschema.mysequence.nextval from dual;
> 2

如果您希望,可以在H2中使用SQL标准的语法,但Oracle不支持此语法:

VALUES NEXT VALUE FOR myschema.mysequence;

我不知道你在SQL中是如何得到Column "nextval" not found的错误信息的;如果模式或序列不存在,异常将会不同。

你需要更新你的问题,并提供你真正的查询语句或在一个单独的问题中发布它,因为这个问题已经包含了答案:你自己的样例查询对于H2来说是有效的。


我举的例子与实际情况并无区别。我注意到你有一个“set mode Oracle”的语句。在创建内存数据库实例时,我在我的脚本中包含了它,但却不起作用。也许你的语句对嵌入式H2数据库不适用? - supertonsky
我在我的脚本myDDL.sql中使用了你的set mode Oracle;,代码如下:new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("myDDL.sql").build()但似乎并没有起到作用,我仍然得到相同的错误提示。 - supertonsky
我认为我需要让“设置模式Oracle”在我的安装中工作,这可能会完整回答我的问题。 - supertonsky
1
H2 1.4.199版本在正常模式下也支持Oracle风格的命令(但是为了更好的兼容性,你应该在你的情况下使用Oracle兼容模式,你可以在JDBC URL后面简单地添加;MODE=Oracle)。 - Evgenij Ryazanov
看起来你的某个地方有一个流浪的 nextval,因为 H2 在这种错误消息中报告了列的全名。 - Evgenij Ryazanov
1
找到了问题所在。nextval是代码期望查询将用作输出的列名,但H2使用NEXT VALUE FOR MYSCHEMA.MYSEQUENCE作为列名。为了解决这个问题,我不得不创建一个别名select myschema.mysequence.nextval nextval from dual。实际上需要一个迷失的nextval - supertonsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接