はじめに
この記事では認証認可に関する情報は記載しておりません。
Okta の Auth0 との連携について後日記事を投稿する予定ですが、REST API を外部に公開する際はネットワーク制限やセキュリティを強固にするための設定などを考慮した上でご検討ください。
Oracle Autonomous AI Database には、データベース上のデータや PL/SQL 処理を HTTPS の REST API として公開するための Oracle REST Data Services (ORDS) がデフォルトで用意されています。
ORDS を使うと、アプリケーション側から Oracle Database に直接接続するのではなく、以下のような REST API 経由でデータを取得できます。
curl https://<adb-host>/ords/<schema>/v1/customers/
本記事では、Autonomous AI Database 上に保存されている構造化データを、REST API で取得出来るようにする手順を紹介します。
ORDS とは
ORDS (Oracle REST Data Services) は、Oracle Database の HTTP(S) Web ゲートウェイです。
Oracle Database に ORDS を導入することで、Oracle Database Actions やデータベース用の REST API が使えるようになります。
この記事では主に REST API を使う機能にフォーカスします。
ORDS は HTTP(S) の GET、POST、PUT、DELETE などのリクエストを受け取り、事前に定義した Module、Template、Handler のルーティングをもとに適切な処理を実行します。
Handler では SQL や PL/SQL を実行でき、SQL の結果は JSON として返せるため、React や Vue、Angular のようなフロントエンドアプリケーションから扱いやすくなります。
たとえば、以下のような使い方ができます。
- テーブルやビューの内容を REST API として公開する
- SQL の検索結果を JSON として返す
- PL/SQL パッケージを REST API から呼び出す
OCI や Azure、GCP、AWS などで提供されている Autonomous AI Database には、既定で ORDS が導入されています。
そのため、通常の Oracle Database に ORDS を自前でインストールする場合とは異なり、ORDS 本体のインストール作業は不要です。
参考:
- About Oracle REST Data Services in Autonomous AI Database
- Oracle REST Data Services PL/SQL Package Reference
今回作るもの
今回は、以下のような読み取り専用 API を作成します。
データは検証用のものを用意します。
テーブルを作成する DDL やテストデータを INSERT する SQL クエリは後述します。
| Method | Path | 内容 |
|---|---|---|
| GET | /ords/<schema>/v1/customers/ |
顧客属性の一覧を取得 |
| GET | /ords/<schema>/v1/purchase-history/ |
購買履歴の一覧を取得 |
| GET | /ords/<schema>/v1/customer-voices/ |
顧客フィードバックの一覧を取得 |
レスポンスは ORDS の collection feed 形式で返ります。
典型的には以下のような JSON になります。
{
"items": [
{
"id": 1,
"customerId": "C-123456",
"membershipRank": "Gold",
"hasApp": "Y",
"favoriteSports": "Running",
"areaName": "Tokyo"
}
],
"hasMore": false,
"limit": 100,
"offset": 0
}
ORDS の構成要素
ORDS の REST API を PL/SQL で定義する場合、主に以下の 3 つを作成します。
Module
Module は、REST API のまとまりです。
たとえば、今回の API では simple_data_api.v1 という module を作り、base path を /v1/ にしています。
ORDS.DEFINE_MODULE(
p_module_name => 'simple_data_api.v1',
p_base_path => '/v1/',
p_items_per_page => 100,
p_status => 'PUBLISHED',
p_comments => 'Simple read-only data API'
);
この定義により、以下のような URL の土台ができます。
https://<adb-host>/ords/<schema>/v1/
Template
Template は、Module 配下の URL パスを定義するものです。
たとえば customers/ という template を定義すると、以下の URL に対応できます。
https://<adb-host>/ords/<schema>/v1/customers/
定義は以下のようになります。
ORDS.DEFINE_TEMPLATE(
p_module_name => 'simple_data_api.v1',
p_pattern => 'customers/',
p_comments => 'Customer attribute list without names'
);
Handler
Handler は、HTTP メソッドと実行する SQL / PL/SQL を紐づけるものです。
たとえば、GET /customers/ に対して SELECT ... FROM demo_customer_master を実行したい場合は、以下のように書きます。
ORDS.DEFINE_HANDLER(
p_module_name => 'simple_data_api.v1',
p_pattern => 'customers/',
p_method => 'GET',
p_source_type => ORDS.source_type_collection_feed,
p_items_per_page => 100,
p_comments => 'Get customer attributes',
p_source => q'~
SELECT id AS "id",
membership_rank AS "membershipRank",
has_app AS "hasApp",
favorite_sports AS "favoriteSports",
area_name AS "areaName"
FROM demo_customer_master
ORDER BY id
~'
);
ここで重要なのは p_source_type です。
今回のように複数行の SELECT 結果を JSON 配列として返す場合は、ORDS.source_type_collection_feed を使います。
1 件だけ返す詳細 API であれば、ORDS.source_type_collection_item を使うことが多いです。
PL/SQL の処理を実行してレスポンスを自分で組み立てたい場合は、ORDS.source_type_plsql を使います。
実際に試す
サンプルテーブルの作成
ここからは、実際に ORDS で公開するためのサンプルテーブルを作成します。
今回使用するテーブルは以下の 3 つです。
| テーブル名 | 内容 |
|---|---|
DEMO_CUSTOMER_MASTER |
顧客属性 |
DEMO_PURCHASE_HISTORY |
購買履歴 |
DEMO_CUSTOMER_VOICES |
顧客フィードバック |
既に手元に公開したいテーブルがある場合は、この DDL は不要です。
その場合は、後続の ORDS 定義 SQL の SELECT を実テーブルに合わせて変更してください。
CREATE TABLE demo_customer_master (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
cust_id VARCHAR2(30) NOT NULL UNIQUE,
membership_rank VARCHAR2(30),
has_app VARCHAR2(1) CHECK (has_app IN ('Y', 'N')),
favorite_sports VARCHAR2(100),
area_name VARCHAR2(100)
);
CREATE TABLE demo_purchase_history (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
purchase_id NUMBER NOT NULL UNIQUE,
cust_id VARCHAR2(30) NOT NULL,
purchase_date DATE NOT NULL,
purchase_amount NUMBER(12, 0) NOT NULL,
item_count NUMBER(6, 0) NOT NULL,
store_name VARCHAR2(100),
area_name VARCHAR2(100),
CONSTRAINT demo_purchase_history_customer_fk
FOREIGN KEY (cust_id) REFERENCES demo_customer_master (cust_id)
);
CREATE TABLE demo_customer_voices (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
voice_id VARCHAR2(30) NOT NULL UNIQUE,
cust_id VARCHAR2(30) NOT NULL,
post_date DATE NOT NULL,
category VARCHAR2(50),
sentiment_score NUMBER(1, 0) CHECK (sentiment_score BETWEEN 1 AND 5),
feedback_text VARCHAR2(1000),
CONSTRAINT demo_customer_voices_customer_fk
FOREIGN KEY (cust_id) REFERENCES demo_customer_master (cust_id)
);
テストデータの投入
次に、動作確認用のデータを INSERT します。
この記事では REST API の作り方にフォーカスしたいため、データは少なめにしています。
INSERT INTO demo_customer_master (
cust_id,
membership_rank,
has_app,
favorite_sports,
area_name
) VALUES (
'CUST-001',
'Gold',
'Y',
'Running',
'Tokyo'
);
INSERT INTO demo_customer_master (
cust_id,
membership_rank,
has_app,
favorite_sports,
area_name
) VALUES (
'CUST-002',
'Regular',
'N',
'Baseball',
'Osaka'
);
INSERT INTO demo_customer_master (
cust_id,
membership_rank,
has_app,
favorite_sports,
area_name
) VALUES (
'CUST-003',
'Platinum',
'Y',
'Football',
'Kanagawa'
);
INSERT INTO demo_purchase_history (
purchase_id,
cust_id,
purchase_date,
purchase_amount,
item_count,
store_name,
area_name
) VALUES (
10001,
'CUST-001',
DATE '2026-04-01',
12800,
2,
'Online Store',
'Tokyo'
);
INSERT INTO demo_purchase_history (
purchase_id,
cust_id,
purchase_date,
purchase_amount,
item_count,
store_name,
area_name
) VALUES (
10002,
'CUST-002',
DATE '2026-04-03',
7600,
1,
'Retail Store',
'Osaka'
);
INSERT INTO demo_purchase_history (
purchase_id,
cust_id,
purchase_date,
purchase_amount,
item_count,
store_name,
area_name
) VALUES (
10003,
'CUST-003',
DATE '2026-04-06',
21400,
3,
'Online Store',
'Kanagawa'
);
INSERT INTO demo_customer_voices (
voice_id,
cust_id,
post_date,
category,
sentiment_score,
feedback_text
) VALUES (
'VOICE-001',
'CUST-001',
DATE '2026-04-02',
'Shoes',
5,
'The product was comfortable and easy to use.'
);
INSERT INTO demo_customer_voices (
voice_id,
cust_id,
post_date,
category,
sentiment_score,
feedback_text
) VALUES (
'VOICE-002',
'CUST-002',
DATE '2026-04-05',
'Wear',
4,
'The size and fabric were good.'
);
INSERT INTO demo_customer_voices (
voice_id,
cust_id,
post_date,
category,
sentiment_score,
feedback_text
) VALUES (
'VOICE-003',
'CUST-003',
DATE '2026-04-08',
'Gear',
3,
'It was useful, but I would like more options.'
);
COMMIT;
このあと作成する ORDS API では、store_name や feedback_text はレスポンスに含めません。
REST API ではテーブルの全列を公開する必要はなく、用途に応じて返す列を絞ることができます。
ORDS の定義を作成する
以下が、今回作成した ORDS 定義 SQL です。
こちらを対象のスキーマにて実行することで、外部に公開する REST API が作成可能です。
この SQL は、REST API の定義だけを作成します。
テーブル作成とテストデータ投入は、前のセクションで実行済みである前提です。
SET DEFINE ON
DEFINE CORS_ALLOWED_ORIGINS = 'http://localhost:5173,http://127.0.0.1:5173'
-- 新規スキーマで ORDS が未有効の場合だけ使用してください。
-- 既に ORDS が有効なスキーマで実行すると ORA-20049 になる場合があります。
--
-- BEGIN
-- ORDS.ENABLE_SCHEMA(
-- p_enabled => TRUE,
-- p_schema => USER,
-- p_url_mapping_type => 'BASE_PATH',
-- p_url_mapping_pattern => LOWER(USER),
-- p_auto_rest_auth => FALSE
-- );
-- END;
-- /
BEGIN
ORDS.DEFINE_MODULE(
p_module_name => 'simple_data_api.v1',
p_base_path => '/v1/',
p_items_per_page => 100,
p_status => 'PUBLISHED',
p_comments => 'Simple read-only data API'
);
-- ORDS 23c 以降では、モジュール単位の CORS 許可 Origin を設定できます。
-- 利用中の ORDS バージョンにこの API がない場合は、
-- ORDS 管理設定またはリバースプロキシで同等の CORS 設定を行ってください。
ORDS.SET_MODULE_ORIGINS_ALLOWED(
p_module_name => 'simple_data_api.v1',
p_origins_allowed => '&&CORS_ALLOWED_ORIGINS'
);
ORDS.DEFINE_TEMPLATE(
p_module_name => 'simple_data_api.v1',
p_pattern => 'customers/',
p_comments => 'Customer attribute list without names'
);
ORDS.DEFINE_TEMPLATE(
p_module_name => 'simple_data_api.v1',
p_pattern => 'purchase-history/',
p_comments => 'Purchase history list without store names'
);
ORDS.DEFINE_TEMPLATE(
p_module_name => 'simple_data_api.v1',
p_pattern => 'customer-voices/',
p_comments => 'Customer feedback list without free text'
);
END;
/
BEGIN
ORDS.DEFINE_HANDLER(
p_module_name => 'simple_data_api.v1',
p_pattern => 'customers/',
p_method => 'GET',
p_source_type => ORDS.source_type_collection_feed,
p_items_per_page => 100,
p_comments => 'Get customer attributes',
p_source => q'~
SELECT id AS "id",
'C-' || LPAD(TO_CHAR(ORA_HASH(cust_id, 999999)), 6, '0') AS "customerId",
membership_rank AS "membershipRank",
has_app AS "hasApp",
favorite_sports AS "favoriteSports",
area_name AS "areaName"
FROM demo_customer_master
ORDER BY id
~'
);
ORDS.DEFINE_HANDLER(
p_module_name => 'simple_data_api.v1',
p_pattern => 'purchase-history/',
p_method => 'GET',
p_source_type => ORDS.source_type_collection_feed,
p_items_per_page => 100,
p_comments => 'Get purchase history',
p_source => q'~
SELECT id AS "id",
purchase_id AS "purchaseId",
'C-' || LPAD(TO_CHAR(ORA_HASH(cust_id, 999999)), 6, '0') AS "customerId",
TO_CHAR(purchase_date, 'YYYY-MM-DD') AS "purchaseDate",
purchase_amount AS "purchaseAmount",
item_count AS "itemCount",
area_name AS "areaName"
FROM demo_purchase_history
ORDER BY purchase_date DESC, id DESC
~'
);
ORDS.DEFINE_HANDLER(
p_module_name => 'simple_data_api.v1',
p_pattern => 'customer-voices/',
p_method => 'GET',
p_source_type => ORDS.source_type_collection_feed,
p_items_per_page => 100,
p_comments => 'Get customer feedback attributes',
p_source => q'~
SELECT id AS "id",
voice_id AS "voiceId",
'C-' || LPAD(TO_CHAR(ORA_HASH(cust_id, 999999)), 6, '0') AS "customerId",
TO_CHAR(post_date, 'YYYY-MM-DD') AS "postDate",
category AS "category",
sentiment_score AS "sentimentScore"
FROM demo_customer_voices
ORDER BY post_date DESC, id DESC
~'
);
END;
/
COMMIT;
SQL のポイント
レスポンスに出す列を絞る
REST API では、テーブルの全列をそのまま公開する必要はありません。
今回の例では、画面表示に必要な項目だけを SELECT しています。
SELECT id AS "id",
membership_rank AS "membershipRank",
has_app AS "hasApp",
favorite_sports AS "favoriteSports",
area_name AS "areaName"
FROM demo_customer_master
画面で扱いやすい JSON 名にする
SQL の alias を使って、JSON のフィールド名を画面側で扱いやすい名前にしています。
membership_rank AS "membershipRank"
curl で動作確認する
ORDS 定義が完了したら、curl で API を呼び出します。
API の URL は、Database Actions の "REST" ページから、対象の Module を選択することで確認可能です。
下図のように、Module に紐づいた各 Template の URL が確認可能です。
確認した URL を CURL コマンドで実行すると、下図のとおり期待どおり JSON が取得出来ました。
その他
作成した API ですが、Database Actions から Swagger っぽい UI で チェックすることが出来ます。
Database Actions の REST ページから作成した Module のページへ移動。
作成したモジュールから "OpenAPI View" をクリック。
すると見覚えのあるデザインの画面が表示されます。
もちろんここから実行も可能です。

また、"Export Module - OpenAPI" をクリックすることで、OpenAPI Specification の JSON データをダウンロードすることが可能です。
そのためここから OpenAPI の JSON をダウンロードし、それを利用して例えば OCI の API Gateway を簡単に作ることが出来たり、その他ベンダーの API 管理システムと便利に統合が可能です。
クライアントと ADB の間にゲートウェイを構築したい場合に便利ですね。
まとめ
ORDS を使うと、Oracle Database 上の SQL や PL/SQL を REST API として公開できます。
Autonomous Database では ORDS が事前構成済みのため、ORDS 本体のインストールは不要です。
必要な作業は、スキーマを REST Enabled にし、Module、Template、Handler を定義することです。
まずは SELECT 結果を返すだけの小さな API から試すと、ORDS の全体像をつかみやすいと思います。




