【问题标题】:How to emulate ROWNUM of Oracle in H2如何在 H2 中模拟 Oracle 的 ROWNUM
【发布时间】:2019-05-24 10:24:30
【问题描述】:

我使用 H2 数据库进行测试,但我使用 Oracle 进行生产。我正在尝试使用以下查询。

SELECT ROWNUM as id, name, state FROM info;

以下配置

public class DatabaseConfiguration {

    private final static DriverManagerDataSource dataSource = initializeDataSource();

    @Bean
    @Profile("test")
    public DataSource dataSource() {

         return dataSource;
    }

    private static DriverManagerDataSource initializeDataSource() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;MODE=Oracle;");
        dataSource.setUsername("sa");
        dataSource.setPassword("sa");

        return dataSource;
    }
}

但我收到了java.util.NoSuchElementException。 H2 是否支持 ROWNUM?

【问题讨论】:

  • 您没有指定您打算如何使用行号,但由于 Oracle 中最常见的用法是分页查询,因此请注意 H2 为此目的支持 LIMITOFFSET .请参阅文档中的 SELECTResult Sets

标签: oracle spring-boot spring-data-jpa h2


【解决方案1】:

不,H2 不支持语法ROWNUM。它提供了ROWNUM()函数,可以用来达到相同的目的,但在语法或行为上并不完全相同。

我使用 H2 数据库进行测试,但我使用 Oracle 进行生产。

您问题的最佳答案是不要使用不同的 RDBMS 进行开发。使用 Oracle 进行开发的可能选项的非详尽、非详细列表:

  • 可能可以download 并在Oracle Technology Network License 下本地安装数据库。如果我没看错,您可以在不购买许可证的情况下将数据库用于开发目的,但您应该仔细检查我的理解。具体来说,它指出:

    Oracle 授予您非独占、不可转让、有限的许可,允许您在内部使用本程序,但须遵守本协议中规定的限制,仅用于开发、测试、原型设计和演示您的应用程序,并且仅在您的应用程序的有效期内未用于任何数据处理、业务、商业或生产目的,也未用于任何其他目的。

  • 在本地使用Oracle Express。它的功能并不完整(例如,它没有完整的 Oracle Spatial。),但如果您的使用仅限于可用功能,它可能就足够了。此外,目前似乎只有 11g 可用于 Windows 安装,这意味着您需要一个虚拟机来托管 18。
  • 设置Amazon RDS 实例仅用于开发。美国地区最便宜的实例每年不到 350 美元,如果您认真考虑使用内存数据库作为替代品,那么您可能能够很好地使用这些更便宜的实例。这几乎肯定比你每天工作 8 小时的工资要少。与在处理两个不同的 RDBMS 上浪费时间(甚至过度使用 Express 的局限性)相比,这可能是值得的。您的公司甚至可以通过让数据库在晚上脱机或其他方式来减少这种情况。
  • 在现有 Oracle 服务器上请求单独的数据库和实例,并将其专用于开发。这需要确保有足够的硬件可用,并确保配置了对处理和磁盘空间的硬限制,以防止它占用过多的资源。
  • 某种形式的开发者许可协议,但条款显然是really weird

如果项目还处于早期阶段,或者考虑切换到更好地支持开发的不同 RDBMS。 MS SQL Server 的 Express 版本在这方面绝对没问题,而 PostgreSQL 和 MySQL 则更好,因为它们在任何地方都是免费的。对于这些数据库,查找免费文档和帮助也比使用 Oracle 更容易

无论如何,找到一种方法,在开发和生产中实际使用相同的数据库技术。开发人员时间可能是贵公司最昂贵的资源之一,而构建/维护一个永远不会产生影响的 H2 数据库并不能很好地利用该资源(或 QA 资源或任何人的时间和精力)。

如果您的问题不完整,并且您实际上将 H2 用于开发以外的其他用途,则将您的代码设置为对每个 RDBMS 使用单独的查询。每个 RDBMS 都有自己的 SQL 方言。尝试对不同的 RDBMS 使用相同的查询是一个巨大的错误。即使语法在两者中都有效,它们也将具有不同的可用功能,并且除了最简单的查询之外,其他任何东西的性能特征都不太可能相同。使用单独的查询。

【讨论】:

    【解决方案2】:

    ROWID 一样,ROWNUM 仅适用于 Oracle。

    但是您可以使用以下方法获得相同的结果:

    SELECT rownum(), name, state FROM info
    

    rownum()是系统函数H2。 See it here

    【讨论】:

    • 问题是我从视图中选择并且即使我选择多个列作为键也没有唯一标识符。
    • 对不起,我没听清楚。您是否建议使用 ROWID 而不是 ROWNUM?如果是这样,那么我不能使用 ROWID,因为我是从视图中选择的。
    • 我查看了文档,发现它支持 ROWNUM() 函数,但它与 Oracle 中的 ROWNUM 不太一样。所以,我想知道H2是否支持它。
    • 我不确定它是否特定于 Oracle,但可以肯定它不存在于 MySQL 或 PostgreSQL 中。 ROWNUM 是伪列。我可以在这里使用 ROWNUM,因为我所要做的就是选择不更新或插入。
    • 使用rownum()函数有什么问题?
    【解决方案3】:

    在 h2 版本 1.4.200 中,ROWNUM 开箱即用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-06
      • 2015-10-03
      • 1970-01-01
      • 2012-02-26
      相关资源
      最近更新 更多