Oracle AI 数据库 JavaScript 开发者学习指南
本文档旨在为使用 Oracle AI 数据库多语言引擎 (MLE) 的 JavaScript 开发者提供一份全面的学习指南。内容包括核心概念总结、关键代码案例、自我测验及答案解析,以及一个常用术语表,所有信息均提炼自官方开发者指南。
核心概念总结
Oracle AI 数据库通过其多语言引擎 (MLE) 将 JavaScript 的强大功能直接引入数据库层。这种“智能数据库 (Smart-DB)”方法将应用逻辑与数据并置,从而提升性能、增强安全性并简化数据处理模式。
1. 在数据库中调用 JavaScript
在数据库中执行 JavaScript 代码主要有两种方式:
- 动态执行 (Dynamic Execution):通过
DBMS_MLEPL/SQL 包执行匿名的 JavaScript 代码片段。这种方式无需在数据库中持久化存储代码,适用于一次性或动态生成的脚本。工作流程包括创建执行上下文、提供 JavaScript 源代码 (作为 CLOB 或 VARCHAR2)、执行代码,最后销毁上下文。 - MLE 模块调用 (MLE Module Calls):将 JavaScript 代码创建为持久化的数据库模式对象,即 MLE 模块。通过为模块中导出的函数创建调用规范 (Call Specification),可以使这些 JavaScript 函数像普通的 PL/SQL 过程或函数一样被 SQL 和 PL/SQL 调用。这是构建可重用、模块化业务逻辑的首选方法。
2. MLE 模块与环境
- MLE 模块 (MLE Modules):
- 它们是存储在数据库中的模式对象,包含遵循 ECMAScript 6 (ES6) 模块标准的 JavaScript 代码。
- 使用
CREATE MLE MODULEDDL 语句进行创建。 - 模块内的函数、类或变量必须使用
export关键字导出,才能被外部调用或被其他模块导入。 - 未导出的标识符被视为模块私有。
- MLE 环境 (MLE Environments):
- 它们是补充 MLE 模块的模式对象,用于自定义 JavaScript 运行时。
- 主要功能包括:
- 名称解析:在
import语句中,将导入名称映射到具体的 MLE 模块。这是实现模块化代码的关键。 - 设置语言选项:例如,通过设置
'js.strict=true'来强制执行 JavaScript 的严格模式。
- 名称解析:在
3. 调用规范 (Call Specifications)
调用规范是连接 PL/SQL/SQL 世界与 JavaScript 世界的桥梁。它将一个 PL/SQL 过程或函数映射到一个 JavaScript 函数。
- 模块调用规范:
- 语法为
CREATE ... AS MLE MODULE module_name SIGNATURE 'js_function_name(types)'。 MODULE子句指定目标 MLE 模块。SIGNATURE子句指定要调用的已导出 JavaScript 函数的名称及其参数类型。
- 语法为
- 内联调用规范:
- 语法为
CREATE ... AS MLE LANGUAGE JAVASCRIPT {{ ... }}。 - 允许将 JavaScript 函数体直接嵌入 DDL 语句中,无需创建单独的 MLE 模块。
- 适用于实现简单的、非重用的功能。
- 内联代码无法导入其他 MLE 模块,但可以通过全局变量访问内置模块的功能。
- 语法为
4. 从 JavaScript 调用 SQL 与 PL/SQL
MLE 提供了一套强大的 API,使 JavaScript 代码能够无缝地与数据库交互。
- MLE JavaScript SQL 驱动 (
mle-js-oracledb):- 这是一个内置模块,其 API 设计与流行的 Node.js 驱动
node-oracledb高度相似,但核心区别在于mle-js-oracledb默认以同步方式运行。 - 常用的对象如
oracledb(驱动对象) 和session(默认连接对象) 可作为全局变量直接使用,简化了代码。 - 通过
session.execute()方法执行 SQL 查询、DML 和 PL/SQL 匿名块。
- 这是一个内置模块,其 API 设计与流行的 Node.js 驱动
- 绑定变量 (Bind Variables):
- 强烈推荐使用绑定变量(而非字符串拼接)来构建 SQL 语句,这对于提升性能和防止 SQL 注入至关重要。
- 支持按名称绑定(使用 JavaScript 对象)和按位置绑定(使用数组)。
- 外部函数接口 (FFI - Foreign Function Interface):
- 由
mle-js-plsql-ffi模块提供,它允许将 PL/SQL 包、过程和函数作为 JavaScript 对象进行操作。 - 相比于通过
session.execute()调用 PL/SQL,FFI 提供了更自然、更简洁的 JavaScript 语法。
- 由
5. 使用 SODA 集合
- SODA (Simple Oracle Document Access) 是一套 NoSQL 风格的 API,用于在 Oracle 数据库中创建和管理文档集合,特别是 JSON 文档。
- 开发者无需了解 SQL 即可对文档执行创建、读取、更新和删除 (CRUD) 操作。
- 在 MLE JavaScript 中,可以通过全局的
soda对象(代表SodaDatabase)轻松访问 SODA 功能。 - 核心对象包括
SodaDatabase、SodaCollection(文档集合)和SodaDocument(单个文档)。
6. 安全性考量
- 受限执行上下文 (Restricted Execution Context):
- 通过在 MLE 环境或内联调用规范中指定
PURE关键字来启用。 - 在
PURE上下文中运行的 JavaScript 代码无法访问任何数据库状态,如读写表、调用存储过程等。它只能通过函数参数接收输入并通过返回值提供输出。 - 这为运行第三方库或执行纯计算任务提供了一个强大的安全沙箱,显著减小了供应链攻击的风险。
- 在
PURE模式下,mle-js-oracledb、mle-js-plsql-ffi和mle-js-fetch等与数据库状态交互的 API 均不可用。
- 通过在 MLE 环境或内联调用规范中指定
关键案例
以下案例展示了在 Oracle AI 数据库中使用 JavaScript 的常见模式。
案例 1:创建并使用 MLE 模块
此案例创建一个计算订单总价值的 MLE 模块,并为其创建一个 PL/SQL 函数调用规范。
-- 步骤 1: 创建一个 MLE 模块,导出一个函数
CREATE OR REPLACE MLE MODULE po_module LANGUAGE JAVASCRIPT AS
/**
* get the value of all line items in an order
* @param {array} lineItems - all the line items in a purchase order
* @returns {number} the total value of all line items in a purchase order
*/
export function orderValue(lineItems) {
return lineItems
.map(x => x.Part.UnitPrice * x.Quantity)
.reduce(
(accumulator, currentValue) => accumulator + currentValue, 0
);
}
/
-- 步骤 2: 为导出的 JavaScript 函数创建一个调用规范
CREATE OR REPLACE FUNCTION order_value(
p_line_items JSON
) RETURN NUMBER
AS MLE MODULE po_module
SIGNATURE 'orderValue';
/
-- 步骤 3: 在 SQL 中调用该函数 (假设存在 j_purchaseorder 表)
SELECT
po.po_document.PONumber,
order_value(po.po_document.LineItems[*]) AS total_value
FROM
j_purchaseorder po;
案例 2:创建内联调用规范
此案例展示了如何使用内联调用规范创建一个将时间戳转换为 Epoch 时间(自1970年1月1日以来的毫秒数)的函数。
CREATE OR REPLACE FUNCTION date_to_epoch(
"theDate" TIMESTAMP WITH TIME ZONE
) RETURN NUMBER
AS MLE LANGUAGE JAVASCRIPT {{
const d = new Date(theDate);
// 检查输入参数是否为有效日期
if (isNaN(d)){
throw new Error(`${theDate} is not a valid date`);
}
// Date.prototype.getTime() 返回毫秒数
return d.getTime();
}};
/
-- 在 SQL 中调用
SELECT date_to_epoch(SYSTIMESTAMP) FROM DUAL;

案例 3:使用 MLE JavaScript SQL 驱动查询数据
此案例使用简化的内联调用规范和全局 session 对象来查询 hr.departments 表。
CREATE OR REPLACE PROCEDURE js_sql_mod_simplified(
"managerID" number
) AS MLE LANGUAGE JAVASCRIPT {{
if (managerID === undefined || managerID === null) {
throw new Error(
"Parameter managerID has not been provided"
);
}
const result = session.execute(
`SELECT
manager_id,
department_id,
department_name
FROM
hr.departments
WHERE
manager_id = :id`,
[managerID] // 使用位置绑定
);
if (result.rows.length > 0) {
for (let row of result.rows) {
console.log(
`Found: manager_id: ${row.MANAGER_ID}, department_name: ${row.DEPARTMENT_NAME}`
);
}
} else {
console.log(`no data found for manager ID ${managerID}`);
}
}};
/
-- 执行该过程
SET SERVEROUTPUT ON;
EXEC js_sql_mod_simplified(100);
案例 4:SODA 基本工作流
此案例展示了使用 SODA 的完整流程:创建集合、插入 JSON 文档、查找并显示文档,最后清理。
CREATE OR REPLACE PROCEDURE intro_soda(
"dropCollection" BOOLEAN
) AUTHID CURRENT_USER AS MLE LANGUAGE JAVASCRIPT {{
// 使用全局 soda 对象创建或打开一个集合
const col = soda.createCollection("MyCollection");
// 创建一个 JSON 文档
const doc = {
"_id": 100,
"job_id": "AD_PRES",
"last_name": "King",
"first_name": "Steven"
};
// 将文档插入集合
col.insertOne(doc);
// 查找集合中的所有文档并打印
const c = col.find().getCursor();
let resultDoc;
while (resultDoc = c.getNext()) {
const content = resultDoc.getContent();
console.log(`Key: ${resultDoc.key}, Name: ${content.first_name} ${content.last_name}`);
}
c.close(); // 必须关闭游标
// 可选:删除集合
if (dropCollection) {
session.commit(); // 删除前必须提交事务
col.drop();
}
}};
/
-- 执行该过程
SET SERVEROUTPUT ON;
EXEC intro_soda(true);
自我测验
请根据以上内容和您的理解回答以下问题。
- 在 Oracle AI 数据库中执行 JavaScript 代码的两种主要方法是什么?
PURE关键字在创建 MLE 环境或内联调用规范时有什么作用?- 用于将 JavaScript 函数发布以便从 SQL 和 PL/SQL 调用的数据库对象是什么?
- 在 MLE JavaScript 中,哪个内置模块提供了用于执行 SQL 语句的驱动程序?
- 与客户端的
node-oracledb驱动程序相比,mle-js-oracledb驱动程序在执行模式上的主要区别是什么? - SODA 是什么?它主要用于处理哪种类型的数据?
- 在 MLE 模块中,如何使一个函数或变量可以被其他模块导入或通过调用规范使用?
- 什么是 MLE 环境 (MLE Environment)?它有两个主要功能是什么?
- 外部函数接口 (FFI) 的主要目的是什么?
- 当使用
session.execute()执行 DML 语句(如 INSERT、UPDATE)后,事务会自动提交吗?
--------------------------------------------------------------------------------
答案与解析
- 答案:动态执行 (通过
DBMS_MLE包) 和 MLE 模块调用 (通过创建持久化的 MLE 模块和调用规范)。 解析:动态执行适用于临时代码,而模块调用适用于构建可重用的、结构化的应用程序逻辑。 - 答案:它会创建一个受限的执行上下文,禁止 JavaScript 代码访问任何数据库状态(如表、过程、对象等),从而提供一个安全沙箱。 解析:
PURE是一个重要的安全特性,尤其适用于运行第三方库或执行纯计算逻辑,可以防止意外或恶意的数据库操作。 - 答案:调用规范 (Call Specification)。 解析:调用规范是 PL/SQL 过程或函数,其实现指向一个 MLE 模块中的 JavaScript 函数或直接内联了 JavaScript 代码。
- 答案:
mle-js-oracledb。 解析:该模块提供了与数据库交互的核心功能,如获取连接和执行 SQL 语句。 - 答案:
mle-js-oracledb默认是同步执行的,而node-oracledb是异步的(使用回调或 Promise/async/await)。 解析:由于mle-js-oracledb在数据库内部运行,不存在网络延迟,因此同步模型更直观、更简单。 - 答案:SODA (Simple Oracle Document Access) 是一套 NoSQL 风格的 API,主要用于处理数据库中存储的 JSON 文档。 解析:SODA 让开发者可以方便地对 JSON 文档集合执行 CRUD 操作,而无需编写 SQL。
- 答案:使用
export关键字。 解析:这遵循 ECMAScript 6 模块标准。只有被导出的标识符才能在模块外部被访问。 - 答案:MLE 环境是一个模式对象,其主要功能是:1) 为
import语句提供名称解析,将其映射到具体的 MLE 模块;2) 设置 JavaScript 运行时的语言选项。 解析:环境是组织和配置模块化 JavaScript 代码的关键组件。 - 答案:提供一种比执行原生 SQL 字符串更直接、更像原生 JavaScript 调用的方式来访问 PL/SQL 包、过程和函数。 解析:FFI (通过
mle-js-plsql-ffi模块) 减少了模板代码,使 PL/SQL 调用在 JavaScript 中看起来更自然。 - 答案:不会。 解析:
mle-js-oracledb驱动程序没有自动提交功能。事务管理与标准的 PL/SQL 行为一致,需要显式地通过session.commit()、session.rollback()或在调用方的 PL/SQL 代码中进行提交或回滚。
术语表
|
术语 |
中文 |
描述 |
|
MLE (Multilingual Engine) |
多语言引擎 |
Oracle AI 数据库的一项功能,允许在数据库内部直接执行多种编程语言的代码,如 JavaScript。 |
|
Dynamic Execution |
动态执行 |
通过 |
|
MLE Module |
MLE 模块 |
一个存储在数据库中的模式对象,包含可重用的 JavaScript (ECMAScript 6) 代码。 |
|
MLE Environment |
MLE 环境 |
一个模式对象,用于配置 MLE 模块的运行时行为,主要是为了模块导入的名称解析和设置语言选项。 |
|
Call Specification |
调用规范 |
一个 PL/SQL 过程或函数,其定义链接到一个 JavaScript 函数,使其可以从 SQL 或 PL/SQL 中调用。 |
|
|
SIGNATURE 子句 |
在调用规范中,用于指定要调用的 JavaScript 函数名称及其参数类型的子句。 |
|
|
- |
MLE 内置的 JavaScript SQL 驱动程序,用于从 JavaScript 代码中执行 SQL 和 PL/SQL。 |
|
FFI (Foreign Function Interface) |
外部函数接口 |
一种 API ( |
|
SODA (Simple Oracle Document Access) |
简单 Oracle 文档访问 |
一套 NoSQL 风格的 API,用于在 Oracle 数据库中管理 JSON 文档集合。 |
|
Restricted / |
受限 / |
一种安全的执行环境,通过 |
|
Bind Variables |
绑定变量 |
在 SQL 语句中使用的占位符,用于安全、高效地传递数据。可以防止 SQL 注入并提高性能。 |
浙公网安备 33010602011771号