MLE JavaScript SQLドライバの概要

MLE JavaScriptドライバは、Node.js用のクライアント側Oracle SQLドライバであるnode-oracledbによく似たモデルとなっています。

サーバー側ドライバとクライアント側ドライバの間のこの密接な関係により、クライアント側のJavaScriptコードをNode.jsまたはDenoからデータベースに移植するために必要な労力が軽減されます。サーバー側の環境に適切にマップできない機能は、MLEおよびMLE JavaScriptドライバでは除外され、エラーをスローします。

これは、コードのどの部分に変更が必要かを識別するために役立ちます。さらに、MLE JavaScript実装は純粋なJavaScript実装です。ウィンドウ・オブジェクトおよびファイルとネットワークの直接I/Oなど、ECMAScript標準に含まれない特定の機能はMLEでは使用できません。

mle-js-oracledb SQLドライバは同期操作モデルにデフォルト設定され、async/awaitによる非同期実行を部分的にサポートしています。

ノート:

本番コードはエラー処理およびロギングに関する業界のベスト・プラクティスに準拠している必要がありますが、この章の例ではわかりやすくするために省略されています。また、読みやすいことから、ほとんどの例で同期実行モデルを採用しています。

ノート:

制限された実行コンテキストでJavaScriptコードを実行している場合、MLE JavaScript SQLドライバは使用できません。制限された実行コンテキストの詳細は、「制限された実行コンテキストについて」を参照してください。

関連項目:

トピック

MLE JavaScriptドライバの操作

MLE JavaScriptドライバを操作するための汎用的なワークフロー。

高レベルでは、MLE JavaScriptドライバの操作は、クライアント側のnode-oracledbドライバの使用によく似ています。つまり、次のようになります。

  1. 既存のデータベース・セッションへの接続ハンドルを取得します。
  2. その接続を使用してSQL文を実行します。
  3. 実行された文によって戻された結果オブジェクトと、発生した可能性のあるデータベース・エラーを確認します。
  4. select文の場合は、結果のカーソルを反復処理します。
  5. データを操作する文については、トランザクションをコミットするかロールバックするかを決定します。

クライアント側のNode.jsまたはDenoから移植されていないアプリケーションでは、グローバル・スコープで使用可能な頻繁に使用される多数の変数など、MLE JavaScript SQLドライバで使用可能なコーディング支援のメリットが得られます。これらの変数には、次のものが含まれます。

  • OracleDbドライバ・オブジェクトのoracledb
  • デフォルトの接続オブジェクトのsession
  • SodaDatabaseオブジェクトのsoda
  • 外部ファンクション・インタフェース(FFI)オブジェクトのplsffi

さらに、次の型も使用できます。

  • OracleNumber
  • OracleClob
  • OracleBlob
  • OracleTimestamp
  • OracleTimestampTZ
  • OracleDate
  • OracleIntervalDayToSecond
  • OracleIntervalYearToMonth

これらのオブジェクトをグローバル・スコープで使用できるため、ボイラープレート・コードを記述する必要性が少なくなります。MLE JavaScript SQLドライバで使用可能なグローバル・シンボルの詳細は、サーバー側のJavaScript APIドキュメントを参照してください。

MLE JavaScriptドライバの接続管理

MLE JavaScriptドライバの接続管理を処理する際の考慮事項。

MLE JavaScriptドライバの接続管理は、クライアント・ドライバと比較して大幅に簡素化されています。JavaScriptストアド・プロシージャが起動されると、データベース・セッションがすでに存在するため、接続、接続プールおよびセキュアな資格証明管理の確立や破棄その他多くのことについて心配する必要はありません。

mle-js-oracledbモジュールのgetDefaultConnection()メソッドに注意するか、グローバル・セッション・オブジェクトを使用することで済みます。

SQL文の実行の概要

Connectionクラスのexecute()メソッドによって、単一のSQLまたはPL/SQL文を実行できます。問合せ結果は、単一のJavaScript配列で戻すことも、ResultSetオブジェクトを使用してバッチでフェッチすることもできます。

ResultSetとしてフェッチすると、フェッチ操作をより詳細に制御できるのに対し、配列を使用すると、必要なコード行数が減り、戻されるデータ量が非常に多い場合を除き、パフォーマンス上の利点があります。

例7-1 MLE JavaScript SQLドライバの開始

次のコードは、MLE JavaScript SQLドライバを現行のモジュールのネームスペースにインポートする方法を示しています。この例は、node-oracledbのドキュメントNode.jsのSQL SELECT文に記載されている例に基づいています。

CREATE OR REPLACE MLE MODULE js_sql_mod LANGUAGE JAVASCRIPT AS

import oracledb from "mle-js-oracledb";

/**
 * Perform a lookup operation on the HR.DEPARTMENTS table to find all
 * departments managed by a given manager ID and print the result on
 * the console
 * @param {number} managerID the manager ID
*/

function queryExample(managerID) {

  if (managerID === undefined) {
    throw new Error (
        "Parameter managerID has not been provided to queryExample()"
    );
  }
  let connection;

  try {
    connection = oracledb.defaultConnection();

    const result = connection.execute(`
        SELECT manager_id, department_id, department_name
        FROM hr.departments
        WHERE manager_id = :id`,
        [
            managerID
        ], 
        {
            outFormat: oracledb.OUT_FORMAT_OBJECT
        }
    );
    if (result.rows.length > 0) {
        for (let row of result.rows) {
            console.log(`The query found a row:
                manager_id:      ${row.MANAGER_ID}
                department_id:   ${row.DEPARTMENT_ID}
                department_name: ${row.DEPARTMENT_NAME}`);
        }
    } else {
        console.log(`no data found for manager ID ${managerID}`);
    }

  } catch (err) {
    console.error(`an error occurred while processing the query: ${err.message}`);
  } 
}

export { queryExample };
/

モジュールに存在する唯一のファンクションであるqueryExample()は、connection.execute()をコールすることにより、バインド変数を使用してHR部門表から単一の行を選択します。バインド変数の値は、パラメータとしてファンクションに渡されます。connection.execute()に渡されるもう1つのパラメータは、問合せによって戻される各行をJavaScriptオブジェクトとして指定する必要があることを示します。

指定されたmanagerIDのデータが見つかった場合は、画面に出力されます。デフォルトでは、console.log()へのコールはDBMS_OUTPUTにリダイレクトされます。戻された行がない場合は、この事実を示すメッセージがコンソールに出力されます。

次のスニペットのコール仕様を使用すると、データベースでコードを起動できます。

CREATE OR REPLACE PROCEDURE p_js_sql_query_ex(
    p_manager_id number)
AS MLE MODULE js_sql_mod
SIGNATURE 'queryExample(number)';
/

デフォルトのままになっている場合、p_js_sql_query_exを起動すると、次のように表示されます。

SQL> set serveroutput on
SQL> EXEC p_js_sql_query_ex(103)
The query found a row:
manager_id:      103
department_id:   60
department_name: IT

関連項目:

mle-js-oracledbなどの組込みJavaScriptモジュールの詳細は、サーバー側JavaScript APIのドキュメントを参照してください

例7-2 グローバル変数を使用したSQL実行の簡略化

例7-1は、MLEで使用するために大幅に簡略化できます。グローバル・スコープに挿入された変数を参照できるため、mle-js-oracledbモジュールをインポートする必要がなくなります。さらに、モジュールには単一のファンクションしか定義されないため、インライン・コール仕様により入力がさらに節約されます。

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 to js_sql_mod_simplified()"
    );
}

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(
            `The query found a row:
             manager_id: ${row.MANAGER_ID}
             department_id: ${row.DEPARTMENT_ID}
             department_name: ${row.DEPARTMENT_NAME}`
        );
    }
} else {
    console.log(`no data found for manager ID ${managerID}`);
}
}};
/
js_sql_mod_simplifiedを起動すると、次のように出力されます:
SQL> set serveroutput on
SQL> exec js_sql_mod_simplified(100);

The query found a row:
manager_id:      100
department_id:   90
department_name: Executive

node-oracledbとmle-js-oracledbとの処理の比較

node-oracledbのドキュメントでは、async/awaitインタフェースの使用が推奨されています。クライアントとサーバーの対話の性質により、nodeとデータベースの間に含まれる処理の大部分が非同期的に実行されます。

MLE JavaScriptドライバは非同期処理を必要としません。PL/SQLドライバと同様に、これはデータベース内のドライバの場所によるものです。MLE JavaScriptドライバはasync/await構文を理解しますが、リクエストは内部で同期的に処理されます。

node-oracledbドライバとは異なり、MLE JavaScript SQLドライバは、ECMAScript 2023構文を使用すると、配列(oracledb.OUTFORMAT_ARRAY)ではなくオブジェクト(oracledb.OUT_FORMAT_OBJECT)として行を戻します。非推奨のrequire構文に依存しているコードは、行を配列として戻すことで下位互換性が維持されます。

ノート:

promiseベースのインタフェースは、MLE JavaScriptドライバには用意されていません。