可用版本: 开发版 (3.21) | 最新版 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

存储过程和函数

适用于 ✅ 开源版   ✅ 专业版   ✅ 企业版

许多关系型数据库管理系统 (RDBMS) 都支持“例程”的概念,通常称之为过程和/或函数。这些概念在编程语言中已经存在了一段时间,也存在于数据库之外。区分过程和函数的著名语言有

  • Ada
  • BASIC
  • Pascal
  • 等等...

(存储)过程和(存储)函数之间的通用区别可以总结如下

过程

  • 使用 JDBC CallableStatement 调用
  • 没有返回值
  • 通常支持 OUT 参数

函数

  • 可在 SQL 语句中使用
  • 有返回值
  • 通常不支持 OUT 参数

规则的例外情况

  • DB2、H2 和 HSQLDB 在调用函数时不允许使用 JDBC 转义语法。函数必须在 SELECT 语句中使用
  • H2 只知道函数(没有 OUT 参数)
  • Oracle 函数可能带有 OUT 参数
  • Oracle 知道一些出于事务原因不能在 SQL 语句中使用的函数
  • Postgres 只知道函数(所有功能合并)。OUT 参数也可以被解释为返回值,这相当优雅/出人意料,取决于您的品味
  • Sybase jconn3 JDBC 驱动程序在使用函数上的 JDBC 转义语法时,无法正确处理 null 值

总的来说,可以说,即使 SQL:2008 标准规定得相当好,例程(过程/函数)领域在现代 RDBMS 中也远未标准化。每种数据库都有自己的方式,JDBC 仅在过程/函数实现的多样性上提供了很少的抽象,特别是在涉及游标/UDT/数组等高级数据类型时。

为了稍微简化一下,jOOQ 以相同的方式处理过程和函数,使用更通用的 org.jooq.Routine 类型。

使用 jOOQ 为存储过程和函数进行独立调用

如果您使用 jOOQ 的 代码生成器,它将为您生成 org.jooq.Routine 对象。让我们来看下面的例子

-- Check whether there is an author in AUTHOR by that name and get his ID
CREATE OR REPLACE PROCEDURE author_exists (author_name VARCHAR2, result OUT NUMBER, id OUT NUMBER);

生成的工件随后可以这样使用

// Make an explicit call to the generated procedure object:
AuthorExists procedure = new AuthorExists();

// All IN and IN OUT parameters generate setters
procedure.setAuthorName("Paulo");
procedure.execute(configuration);

// All OUT and IN OUT parameters generate getters
assertEquals(new BigDecimal("1"), procedure.getResult());
assertEquals(new BigDecimal("2"), procedure.getId();

但您也可以在全局 Routines 类中使用生成的便捷方法来调用该过程

// The generated Routines class contains static methods for every procedure.
// Results are also returned in a generated object, holding getters for every OUT or IN OUT parameter.
AuthorExists procedure = Routines.authorExists(configuration, "Paulo");

// All OUT and IN OUT parameters generate getters
assertEquals(new BigDecimal("1"), procedure.getResult());
assertEquals(new BigDecimal("2"), procedure.getId();

有关过程的 代码生成 的更多详细信息,请参阅手册中关于 过程和代码生成 的部分。

在 SQL 中内联存储函数引用

与过程不同,函数可以内联到 SQL 语句中,以生成 列表达式表表达式,如果您使用 解嵌套运算符。假设您有这样一个函数

-- Check whether there is an author in AUTHOR by that name and get his ID
CREATE OR REPLACE FUNCTION author_exists (author_name VARCHAR2) RETURN NUMBER;

生成的工件随后可以这样使用

-- This is the rendered SQL

SELECT AUTHOR_EXISTS('Paulo') FROM DUAL
// Use the static-imported method from Routines:
boolean exists =
create.select(authorExists("Paulo")).fetchOne(0, boolean.class);

有关在 SQL 语句中内联存储函数引用的更多信息,请参阅手册中关于 用户定义函数 的部分。

反馈

您对本页有什么反馈吗? 我们很乐意听取您的意见!

The jOOQ Logo