如何使用 H2 嵌入式数据库获取序列中的下一个值?
Posted
技术标签:
【中文标题】如何使用 H2 嵌入式数据库获取序列中的下一个值?【英文标题】:How to get nextvalue in a sequence using H2 Embedded Database? 【发布时间】:2020-04-22 06:44:55 【问题描述】:背景
我使用 Oralce 作为数据库,使用 H2 Embedded 内存数据库进行集成测试。
我在 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 脚本来创建 DB 对象。
以下帖子以及接受的答案帮助解决了这个问题。
Does Spring embedded database support different SQL dialects?
【问题讨论】:
【参考方案1】:这种Oracle风格的表达其实是H2支持的,包括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
声明。在创建内存数据库实例时执行我的 DDL 时,我已将它包含在我的脚本中,但这不起作用。也许您的不适用于嵌入式 H2 DB?
我在我的脚本myDDL.sql
中使用了你的set mode Oracle;
,并在下面的代码new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("myDDL.sql").build()
中使用了你的set mode Oracle;
,但这似乎没有什么不同,我仍然遇到同样的错误。
我想我需要让set mode Oracle
处理我的设置,这样才能完成我的问题的答案。
H2 1.4.199 在常规模式下也支持这种 Oracle 风格的命令(但您确实应该在您的情况下使用 Oracle 兼容模式以获得更好的兼容性,您可以简单地将其附加到 JDBC URL ;MODE=Oracle
)。
看起来你在某处有一个流浪的nextval
,因为H2在这样的错误信息中报告了列的全名。以上是关于如何使用 H2 嵌入式数据库获取序列中的下一个值?的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot、JPA、Hibernate 和 H2 DB 测试 - 序列不起作用 - 意外的代码路径”;SQL 语句:调用 seq_my_jobs [50000-193] 的下一个值