5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Select AIで複数データソースを横断検索する:BaseDB 19c × Snowflake Iceberg

5
Last updated at Posted at 2026-04-30

Oracle Autonomous AI Databaseは、外部データソースを含めた複数のデータをつなぐ AI検索のハブ として利用できます。

データをすべてADBに取り込むのではなく、ADBを窓口として外部データに接続し、Select AI によって自然言語で問い合わせを行います。さらに、単なるハブ・中継地点として機能するだけでなく、Oracle AI Database / Autonomous AI Databaseは、リレーショナルデータ、JSON、テキスト、ベクトル、グラフ、地理空間データなどを単一のコンバージド・データベース基盤で扱えるため、AI活用に必要となる業務データ、メタデータ、セマンティック検索用のベクトル、RAGで利用するコンテキスト、さらにはエージェントが利用する短期・長期メモリを、統合的かつセキュアに管理する基盤として位置付けることができます。
このように、ADBが外部データへの問い合わせを仲介する役割を担う構成を、AIプロキシ・データベース または サイドカー と呼んでいます。

今回は、Oracle Database上にある顧客情報や取引情報などの基幹データ(BaseDB 19c)に、外部データソースであるSnowflake上のIcebergデータを組み合わせる形で、ADBをAI検索のハブとして利用します。

これにより、利用者はデータの保存場所や接続先を意識することなく、Select AI を使って複数のデータソースをまたいだ自然言語検索を実行できます。本記事では、このような AIプロキシ・データベース / サイドカー の構成を確認します。

image.png

全体の構成

今回の構成では、ADBをAI検索の入口 として配置し、ADBからBaseDB 19cおよび外部データソース(Snowflake)を参照します。

ポイントは、すべてのデータをADBに集約するのではなく、ADB上に参照用のViewを作成し、必要なデータをDB Linkや外部表経由で取得する点です。
利用者はADBに対してSelect AIで自然言語の問い合わせを行い、ADB側で定義したViewをもとにSQLが生成されます。

構成要素は大きく次の通りです。

  • BaseDB 19c
    顧客情報、売上、キャンペーン、サポート問い合わせなどの基幹系データを保持します。

  • Snowflake / Icebergデータ
    外部データソースとして、Iceberg形式のデータを利用します。今回は顧客データや国データの一部を組み合わせて利用します。

  • ADB 26ai
    BaseDB 19cへのDB Link、外部データ参照、統合View、Select AIプロファイルを持つ中心的な役割を担います。

この構成では、ADB上に V_CUSTOMER_360 という統合Viewを作成します。
このViewでは、BaseDB 19c上の顧客・売上・マーケティング・サポート情報と、ADB側から参照できるIceberg由来の国データを結合し、顧客ごとの分析に使いやすい形にまとめます。

image.png

■ 0. 前提条件

  • ADB(26ai)が作成されている
  • BaseDBを構築するVCNが作成されている
  • Snowflake側の準備が以下の記事に沿って済んでいる

■ 1. Base DBの作成

ナビゲーションメニューから、Oracle AI DatabaseOracle Base Database Serviceに移動します。

DBシステムの作成」をクリックします。

image.png

必要な項目を入力して、DBシステムを作成します。
今回は基本的にはデフォルトの設定のまま、バージョンは19c、パブリックサブネットで作成します。

image.png

設定の例:

  • DBシステム名:DBSystem-2026043XXXX
  • コンパートメント:任意
  • Oracle Database ソフトウエア・エディション:Standard Edition
  • ホスト名接頭辞:DB0430
  • データベース名:DB0430
  • PDB名:pdb1

作成できました。
image.png

アクセスします。

ssh -i <秘密鍵ファイルのパス> opc@<DB_SYSTEM_IP>
sudo su - oracle
sqlplus / as sysdba

image.png

■ 2. BaseDB側の準備

2-1. ユーザー作成と権限付与

PDBに接続します。
CDB$ROOT と表示される場合は、PDBではなくCDBルートに接続しているので、PDBに接続し直してください。

show con_name;
show pdbs;
alter session set container=PDB1;
show con_name;

BaseDB 19c側に ORA_APP ユーザーを作成します。

CREATE USER ora_app IDENTIFIED BY "your_password"
  DEFAULT TABLESPACE users
  TEMPORARY TABLESPACE temp
  QUOTA UNLIMITED ON users;

必要な権限を付与します。

GRANT CREATE SESSION TO ora_app;
GRANT CREATE TABLE TO ora_app;
GRANT CREATE VIEW TO ora_app;
GRANT CREATE SEQUENCE TO ora_app;
GRANT CREATE PROCEDURE TO ora_app;

2-2. ユーザー作成と権限付与

ORA_APP ユーザーでテーブルを作成します。

conn ora_app/"your_password"@PDB1

今回は、こちらの「21. Oracle DBのデータを作成する」に示したデータと同様のものを作成します。

こちらをクリックしてSQL文を表示:point_down:
ALTER USER ora_app QUOTA UNLIMITED ON USERS;
GRANT CREATE SESSION, CREATE TABLE TO ora_app;

CREATE TABLE ora_app.ORA_LAB_CUSTOMERS (
  C_CUSTKEY     NUMBER,
  C_NAME        VARCHAR2(100),
  C_NATIONKEY   NUMBER,
  C_MKTSEGMENT  VARCHAR2(50),
  C_ACCTBAL     NUMBER,
  RN            NUMBER
);

CREATE TABLE ORA_SALES_ORDER (
  ORDER_ID          NUMBER,
  C_CUSTKEY         NUMBER,
  ORDER_DATE        DATE,
  CHANNEL           VARCHAR2(20),
  PRODUCT_CATEGORY  VARCHAR2(30),
  ORDER_AMOUNT      NUMBER
);

CREATE TABLE ORA_MARKETING_TOUCH (
  TOUCH_ID         NUMBER,
  C_CUSTKEY        NUMBER,
  CAMPAIGN_NAME    VARCHAR2(100),
  SENT_DATE        DATE,
  OPENED_FLAG      CHAR(1),
  CLICKED_FLAG     CHAR(1),
  RESPONSE_STATUS  VARCHAR2(20)
);

CREATE TABLE ORA_SUPPORT_CASE (
  CASE_ID             NUMBER,
  C_CUSTKEY           NUMBER,
  OPENED_DATE         DATE,
  ISSUE_TYPE          VARCHAR2(30),
  PRIORITY            VARCHAR2(10),
  STATUS              VARCHAR2(10),
  SATISFACTION_SCORE  NUMBER
);

image.png

作成できました。

■ 3. ADBからBaseDB 19c へ接続できるようにする

こちらをクリックして詳細の手順表示:point_down:

3-1. ADBのアウトバウンドIPを確認する

ADBに ADMIN で接続して、以下を実行します。

SELECT jt.ip AS adb_outbound_ip
FROM v$pdbs p,
     JSON_TABLE(
       p.cloud_identity,
       '$.OUTBOUND_IP_ADDRESS[*]'
       COLUMNS ip VARCHAR2(64) PATH '$'
     ) jt;

結果の例です。

ADB_OUTBOUND_IP
---------------
xxx.xxx.xxx.xxx

image.png

3-2. BaseDB側のNSG / Security Listを変更する

BaseDBが所属するPublic SubnetのSecurity List、またはDB Systemに紐づいているNSGで、以下を許可します。

  • Ingress
  • ソース: ADBのアウトバウンドIP /32
  • プロトコル: TCP
  • 宛先ポート: 2484

3-3. BaseDB 19cでTCPSを有効化する

BaseDB 19cをPublic DB Linkのターゲットにするため、BaseDB側にTCPSリスナーを追加します。
今回はADBからDBユーザー/パスワードで接続するため、BaseDB側でTCPS接続を受け付けられるようにし、ADB側にはBaseDB接続用のcwallet.ssoを配置します。

現在のListener設定を確認する

BaseDBのOSにログインして、リスナー状態を確認します。

lsnrctl status

確認したいポイントは、以下のように TCPS のエンドポイントが見えることです。

(PROTOCOL=tcps)(HOST=db0430...)(PORT=2484)

3-4. BaseDB側でTCPS用Walletを作成する

BaseDB側のWalletファイル cwallet.sso をADB側に配置します。

BaseDBのOSに入って、Walletを作成します。

ssh opc@XX.XX.XX.XX
sudo su - oracle
exit

sudo mkdir -p /u01/app/oracle/tcps_wallet/server
sudo mkdir -p /u01/app/oracle/tcps_wallet/client
sudo mkdir -p /u01/app/oracle/tcps_wallet/certs

sudo chown -R oracle:oinstall /u01/app/oracle/tcps_wallet

Walletの作成はoracleユーザーで行います。

sudo su - oracle
whoami

Wallet作成用の変数をセットする

ここから同じシェルで作業します。

export BASE=/u01/app/oracle/tcps_wallet

Walletパスワードを入力します。画面には表示されません。

read -s -p "Wallet password: " WALLET_PWD

このパスワードはWallet作成時に使います。

echo ${#WALLET_PWD}

数字が出ればOKです。たとえば 14 のように文字数が出ます。

3-5. Server Walletを作る

orapki wallet create \
  -wallet $BASE/server \
  -pwd "$WALLET_PWD" \
  -auto_login

成功すると、以下のような表示になります。

Operation is successfully completed.

次に、Server Walletに自己署名証明書を作ります。

orapki wallet add \
  -wallet $BASE/server \
  -pwd "$WALLET_PWD" \
  -dn "CN=db0430" \
  -keysize 2048 \
  -self_signed \
  -validity 3650 \
  -sign_alg sha256

ここで指定したこれが重要です。

CN=db0430

この値を、後でADB側のDB Link作成時に指定します。

3-6. Client Walletを作る

Client Walletは、ADB側に渡すためのWalletです。

orapki wallet create \
  -wallet $BASE/client \
  -pwd "$WALLET_PWD" \
  -auto_login

Client Walletにも証明書を作ります。

orapki wallet add \
  -wallet $BASE/client \
  -pwd "$WALLET_PWD" \
  -dn "CN=adb-client" \
  -keysize 2048 \
  -self_signed \
  -validity 3650 \
  -sign_alg sha256

この CN=adb-client は、ADB側クライアント用の証明書名だと思ってください。

3-7. Server証明書とClient証明書を交換する

TCPS/mTLSでは、BaseDB側とADB側が互いを信頼できる必要があります。
そのため、次のように証明書を交換します。

  • Server WalletにClient証明書を登録する
  • Client WalletにServer証明書を登録する

まず、Server証明書をファイルに出します。

orapki wallet export \
  -wallet $BASE/server \
  -pwd "$WALLET_PWD" \
  -dn "CN=db0430" \
  -cert $BASE/certs/server.crt

次に、Client証明書をファイルに出します。

orapki wallet export \
  -wallet $BASE/client \
  -pwd "$WALLET_PWD" \
  -dn "CN=adb-client" \
  -cert $BASE/certs/client.crt

Client証明書をServer Walletに登録します。

orapki wallet add \
  -wallet $BASE/server \
  -pwd "$WALLET_PWD" \
  -trusted_cert \
  -cert $BASE/certs/client.crt

Server証明書をClient Walletに登録します。

orapki wallet add \
  -wallet $BASE/client \
  -pwd "$WALLET_PWD" \
  -trusted_cert \
  -cert $BASE/certs/server.crt

3-8. Walletができたか確認する

Server Walletを確認します。

orapki wallet display \
  -wallet $BASE/server \
  -pwd "$WALLET_PWD"

Client Walletを確認します。

orapki wallet display \
  -wallet $BASE/client \
  -pwd "$WALLET_PWD"

Trusted CertificatesUser Certificates が表示されればOKです。

ADBへ渡す cwallet.sso が作成されていることも確認します。

ls -l $BASE/client/cwallet.sso

これが表示されればOKです。

/u01/tcps/client/cwallet.sso

また、BaseDB Listenerが使用するServer Walletも確認します。

ls -l $BASE/server

3-9. 権限を調整する

まず oracle から抜けて root に戻ります。

exit

root で以下を実行します。

chown -R oracle:oinstall /u01/app/oracle/tcps_wallet

chmod 750 /u01/app/oracle/tcps_wallet
chmod 750 /u01/app/oracle/tcps_wallet/server
chmod 750 /u01/app/oracle/tcps_wallet/client

chmod 640 /u01/app/oracle/tcps_wallet/server/cwallet.sso
chmod 640 /u01/app/oracle/tcps_wallet/server/ewallet.p12
chmod 640 /u01/app/oracle/tcps_wallet/client/cwallet.sso
chmod 640 /u01/app/oracle/tcps_wallet/client/ewallet.p12

確認します。

ls -l /u01/app/oracle/tcps_wallet/server
ls -l /u01/app/oracle/tcps_wallet/client

3-10. BaseDBのlistener/sqlnetにWallet場所を設定する

su - oracle
echo $ORACLE_HOME

例です。

/u01/app/oracle/product/19.0.0.0/dbhome_1

この手順では、以降この場所を使います。

export OH=$ORACLE_HOME

Listener設定ファイルがあるか確認します。

ls -l $OH/network/admin

以下のようなファイルがあるはずです。

listener.ora
sqlnet.ora
tnsnames.ora

Oracle Listener Control Utilityは、TNS_ADMIN 配下、または $ORACLE_HOME/network/admin 配下の listener.ora を見てListener名や接続先を解決します。

もし TNS_ADMIN が設定されている場合は、そちらが優先されます。

echo $TNS_ADMIN

値が出る場合は、そのディレクトリを使ってください。

ls -l $TNS_ADMIN

以降、わかりやすくするために設定ディレクトリを変数に入れます。
以下を実行してください。

if [ -n "$TNS_ADMIN" ]; then
  export NET_ADMIN=$TNS_ADMIN
else
  export NET_ADMIN=$ORACLE_HOME/network/admin
fi

echo $NET_ADMIN

期待される表示はこれです。

/u01/app/oracle/product/19.0.0/dbhome_1/network/admin

次に、設定ファイルをバックアップします。

cp -p $NET_ADMIN/listener.ora $NET_ADMIN/listener.ora.bak.$(date +%Y%m%d_%H%M%S)
cp -p $NET_ADMIN/sqlnet.ora   $NET_ADMIN/sqlnet.ora.bak.$(date +%Y%m%d_%H%M%S)
cp -p $NET_ADMIN/tnsnames.ora $NET_ADMIN/tnsnames.ora.bak.$(date +%Y%m%d_%H%M%S)

バックアップできたか確認します。

ls -l $NET_ADMIN/*.bak.*

3-11. listener.oraにTCPSポートとWallet設定を追加する

既存の LISTENER = ... 定義を探します。
ここに、TCPSの 2484 を追加します。

修正後の例です。

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = db0430)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCPS)(HOST = db0430)(PORT = 2484))
    )
  )

次に、listener.ora の末尾にWallet設定を追加します。

WALLET_LOCATIONDIRECTORY を変更します。

変更前:

WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=/opt/oracle/dcs/commonstore/tcps_wallet)))

変更後:

WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=/u01/app/oracle/tcps_wallet/server)))

client ではなく、BaseDBのListenerが使う server wallet を指定します。

3-12. sqlnet.oraにWallet設定を追加する

次に sqlnet.ora を開きます。

vi $NET_ADMIN/sqlnet.ora

末尾に以下を追加します。

変更前:

WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=/opt/oracle/dcs/commonstore/tcps_wallet)))
SSL_CLIENT_AUTHENTICATION=FALSE

変更後:

WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=/u01/app/oracle/tcps_wallet/server)))
SSL_CLIENT_AUTHENTICATION=TRUE
SSL_SERVER_DN_MATCH=ON

ここでも指定するのは、BaseDB側のserver walletです。

/u01/app/oracle/tcps_wallet/server

3-13. listener.ora sqlnet.oraの内容を確認する

編集ミスがないか確認します。

cat $NET_ADMIN/listener.ora

最低限、以下が含まれていることを確認してください。

(PROTOCOL = TCPS)(HOST = db0430)(PORT = 2484)

または、

(PROTOCOL = TCPS)(HOST = 0.0.0.0)(PORT = 2484)

さらに、以下も含まれていることを確認します。

DIRECTORY = /u01/app/oracle/tcps_wallet/server

sqlnet.oraを確認します。

cat $NET_ADMIN/sqlnet.ora

以下が含まれていればOKです。

WALLET_LOCATION =
DIRECTORY = /u01/app/oracle/tcps_wallet/server
SSL_CLIENT_AUTHENTICATION = TRUE

3-14. Listenerを再起動する

oracle ユーザーのまま実行します。

まず現在の状態を確認します。

lsnrctl status

Listenerを停止します。

lsnrctl stop

Listenerを起動します。

lsnrctl start

状態を確認します。

lsnrctl status

TCPS 2484で待ち受けているか確認する

lsnrctl status の出力に、以下のような行があるか確認します。

(PROTOCOL=tcps)(HOST=...)(PORT=2484)

例です。

Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=db0430)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=db0430)(PORT=2484)))

OS上でも確認できます。

ss -ltnp | grep 2484

もし ss で権限が足りない場合は、いったん root で確認します。

exit
sudo su -
ss -ltnp | grep 2484

以下のように 2484 が表示されればOKです。

LISTEN ... :2484 ...

3-15. PDBサービス名を確認する

ADBのDB Link作成時には、BaseDBの PDBサービス名 が必要です。
Services Summary の中からPDBのサービス名を探します。

例です。

Service "pdb1.subxxxxxxxxxx.vcn.oraclevcn.com" has 1 instance(s).

この場合、DB Linkで使う service_name は以下です。

pdb1.sub01130750020.vcn.oraclevcn.com

CDB のサービスではなく、PDB のサービスを使ってください。

3-16. ADBへ渡すcwallet.ssoを取り出す

ADBへ渡すのは、cwallet.ssoファイルはこちらです。

/u01/app/oracle/tcps_wallet/client/cwallet.sso

BaseDB上で、opc ユーザーが取得できる場所にコピーします。

root で実行します。

sudo su -
cp /u01/app/oracle/tcps_wallet/client/cwallet.sso /home/opc/cwallet.sso
chown opc:opc /home/opc/cwallet.sso
chmod 600 /home/opc/cwallet.sso

自分のPC、またはCloud Shell側から取得します。

scp -i <SSH秘密鍵ファイル> opc@138.2.32.232:/home/opc/cwallet.sso .

OCIコンソールでObject Storageへアップロードします。

Bucket:
  adb-dblink-wallet

Object name:
  cwallet.sso

ファイル名は必ず以下にしてください。

cwallet.sso

image.png

Object Storage上のWalletファイルは cwallet.sso という名前のままにする必要があります。また、WalletファイルとDBユーザー/パスワードの組み合わせでターゲットDBへアクセスできるため、共有範囲は最小限にしてください。

アップロードが終わったら、BaseDB上の一時コピーは削除しておきます。

rm /home/opc/cwallet.sso

3-17. ADB側にWallet格納用ディレクトリを作る

ここからADB側の作業です。
ADBに ADMIN で接続します。

今回は、BaseDB 19c用のWallet専用ディレクトリとして、以下を作ります。

CREATE OR REPLACE DIRECTORY BASEDB19C_WALLET_DIR AS 'basedb19c_wallet_dir';

確認します。

SELECT directory_name, directory_path
FROM all_directories
WHERE directory_name = 'BASEDB19C_WALLET_DIR';

image.png

ADBのDB Linkでは、1つのディレクトリに有効なWalletファイルは1つだけです。複数の cwallet.sso を使う場合は、Walletごとに別ディレクトリを作ります。

3-18. Object StorageからADBへcwallet.ssoを取り込む

Object Storageにアップロードした cwallet.sso を、ADBのディレクトリへ取り込みます。

Object URIの形式は以下です。

https://objectstorage.<region>.oraclecloud.com/n/<namespace>/b/<bucket>/o/cwallet.sso

大阪リージョンなら例はこうです。

https://objectstorage.ap-osaka-1.oraclecloud.com/n/<namespace>/b/adb-dblink-wallet/o/cwallet.sso

ADBで実行します。

BEGIN
  DBMS_CLOUD.GET_OBJECT(
    credential_name => 'OBJ_STORE_CRED',
    object_uri      => 'https://objectstorage.ap-osaka-1.oraclecloud.com/n/<namespace>/b/adb-dblink-wallet/o/cwallet.sso',
    directory_name  => 'BASEDB19C_WALLET_DIR'
  );
END;
/

<namespace> は自分のObject Storage namespaceに置き換えてください。

取り込めたか確認します。

SELECT object_name, bytes
FROM DBMS_CLOUD.LIST_FILES('BASEDB19C_WALLET_DIR');

以下が表示されればOKです。

cwallet.sso

image.png

================

3-19. BaseDB接続用Credentialを作る

ADB側で、BaseDBの ORA_APP ユーザーへ接続するためのCredentialを作成します。

BEGIN
  DBMS_CLOUD.CREATE_CREDENTIAL(
    credential_name => 'BASEDB19C_LINK_CRED',
    username        => 'ORA_APP',
    password        => 'your_password'
  );
END;
/

確認します。

SELECT credential_name, username
FROM user_credentials
WHERE credential_name = 'BASEDB19C_LINK_CRED';

image.png

3-20. BaseDB側のSEC_CASE_SENSITIVE_LOGONを確認する

BaseDB側で確認します。

BaseDBに oracle ユーザーで入り、SQL*Plusを起動します。

sudo su - oracle
sqlplus / as sysdba

確認します。

SHOW PARAMETER sec_case_sensitive_logon;

TRUE ならOKです。

NAME                    TYPE    VALUE
----------------------- ------- -----
sec_case_sensitive_logon boolean TRUE

もし FALSE の場合は、以下を実行します。

ALTER SYSTEM SET sec_case_sensitive_logon=TRUE SCOPE=BOTH;

EXITで抜けます。

Autonomous Database側では SEC_CASE_SENSITIVE_LOGON がTRUEで固定されているため、ターゲットの非Autonomous DB側でもTRUEにする必要があります。FALSEの場合、DB Link接続時に ORA-28040 になることがあります。

■ 4. ADB側でDB Linkを作成する

4-1. DB Linkを作成する

ADBに ADMIN で接続して実行します。

service_name は、BaseDBの lsnrctl status で確認したPDBサービス名に置き換えてください。

BEGIN
  DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINK(
    db_link_name       => 'BASEDB19C_LINK',
    hostname           => '138.2.32.232',
    port               => 2484,
    service_name       => '<BaseDB 19cのPDBサービス名>',
    ssl_server_cert_dn => 'CN=db0430',
    credential_name    => 'BASEDB19C_LINK_CRED',
    directory_name     => 'BASEDB19C_WALLET_DIR'
  );
END;
/

例です。

BEGIN
  DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINK(
    db_link_name       => 'BASEDB19C_LINK',
    hostname           => '138.XX.XX.XX',
    port               => 2484,
    service_name       => 'pdb1.sub01000000000.vcn.oraclevcn.com',
    ssl_server_cert_dn => 'CN=db0430',
    credential_name    => 'BASEDB19C_LINK_CRED',
    directory_name     => 'BASEDB19C_WALLET_DIR'
  );
END;
/

ssl_server_cert_dn は、Server Wallet作成時に指定したDNと一致させます。

前の手順でServer証明書を以下のように作った場合、-dn "CN=db0430"、DB Link側もssl_server_cert_dn => CN=db0430'にします。

4-2. DB Linkの疎通確認をする

ADB側で実行します。

SELECT 1
FROM dual@BASEDB19C_LINK;

以下のように返れば成功です。

         1
----------
         1

image.png

TCPSで接続できているか確認します。

SELECT SYS_CONTEXT('USERENV', 'NETWORK_PROTOCOL') AS network_protocol
FROM dual@BASEDB19C_LINK;

期待値です。

NETWORK_PROTOCOL
----------------
tcps

■ 5. BaseDB側の表が見えるか確認する

ADBから確認します。

SELECT COUNT(*)
FROM ORA_APP.ORA_SALES_ORDER@BASEDB19C_LINK;

まだデータ投入前なら 0 件でもOKです。
ここでエラーにならず、件数が返ることが大事です。

image.png

BaseDB 19c側に作成した表が見えるか確認します。

SELECT owner, table_name
FROM all_tables@BASEDB19C_LINK
WHERE table_name LIKE 'ORA\_%' ESCAPE '\'
ORDER BY owner, table_name;

image.png

■ 6. BaseDBにデータを挿入する

今回は、既に作成してあるデータをADBからBaseDBにコピー、インサートするので以下の手順で行います。

こちらをクリックして表示:point_down:

今回は、まずADB側に一時的な作業用表として STG_ORA_LAB_CUSTOMERS を作ります。
その後、DB Link経由でBaseDB 19cの ORA_LAB_CUSTOMERS にINSERTします。

ADBで以下を実行します。

BEGIN
  EXECUTE IMMEDIATE 'DROP TABLE STG_ORA_LAB_CUSTOMERS PURGE';
EXCEPTION
  WHEN OTHERS THEN
    IF SQLCODE <> -942 THEN
      RAISE;
    END IF;
END;
/
CREATE TABLE STG_ORA_LAB_CUSTOMERS AS
SELECT
  t.C_CUSTKEY,
  t.C_NAME,
  t.C_NATIONKEY,
  t.C_MKTSEGMENT,
  t.C_ACCTBAL,
  ROW_NUMBER() OVER (ORDER BY t.C_CUSTKEY) AS RN
FROM (
  SELECT
    C_CUSTKEY,
    C_NAME,
    C_NATIONKEY,
    C_MKTSEGMENT,
    C_ACCTBAL
  FROM CUSTOMER_ICEBERG
  FETCH FIRST 300 ROWS ONLY
) t;

件数を確認します。

SELECT COUNT(*) AS customer_count
FROM STG_ORA_LAB_CUSTOMERS;

結果が 300 ならOKです。

6-1. ADBからBaseDB 19cへデータをINSERTする

ここから、元記事のデータ生成ロジックを使って、BaseDB 19c側の表にデータを入れます。

念のため、BaseDB 19c側の表を空にします。
DB Link越しにDDLの TRUNCATE は使わず、ここでは DELETE を使います。

DELETE FROM ORA_APP.ORA_SUPPORT_CASE@BASEDB19C_LINK;
DELETE FROM ORA_APP.ORA_MARKETING_TOUCH@BASEDB19C_LINK;
DELETE FROM ORA_APP.ORA_SALES_ORDER@BASEDB19C_LINK;
DELETE FROM ORA_APP.ORA_LAB_CUSTOMERS@BASEDB19C_LINK;

COMMIT;

6-1-1. ORA_LAB_CUSTOMERSへINSERTする

INSERT INTO ORA_APP.ORA_LAB_CUSTOMERS@BASEDB19C_LINK (
  C_CUSTKEY,
  C_NAME,
  C_NATIONKEY,
  C_MKTSEGMENT,
  C_ACCTBAL,
  RN
)
SELECT
  C_CUSTKEY,
  C_NAME,
  C_NATIONKEY,
  C_MKTSEGMENT,
  C_ACCTBAL,
  RN
FROM STG_ORA_LAB_CUSTOMERS;

COMMIT;

確認します。

SELECT COUNT(*) AS customer_count
FROM ORA_APP.ORA_LAB_CUSTOMERS@BASEDB19C_LINK;

結果が 300 ならOKです。


6-1-2. ORA_SALES_ORDERへINSERTする

元記事の ORA_SALES_ORDER 作成ロジックを使います。
違いは、CREATE TABLE AS SELECT ではなく、BaseDB 19c側の表へ INSERT INTO ...@DBLINK する点です。

INSERT INTO ORA_APP.ORA_SALES_ORDER@BASEDB19C_LINK (
  ORDER_ID,
  C_CUSTKEY,
  ORDER_DATE,
  CHANNEL,
  PRODUCT_CATEGORY,
  ORDER_AMOUNT
)
SELECT
  lc.RN * 10 + s.SEQ_NO AS ORDER_ID,
  lc.C_CUSTKEY,
  DATE '2025-01-01' + MOD(lc.RN * 7 + s.SEQ_NO * 11, 120) AS ORDER_DATE,
  CASE MOD(lc.RN + s.SEQ_NO, 3)
    WHEN 0 THEN 'WEB'
    WHEN 1 THEN 'STORE'
    ELSE 'PARTNER'
  END AS CHANNEL,
  CASE MOD(lc.RN + s.SEQ_NO, 5)
    WHEN 0 THEN 'COMPUTE'
    WHEN 1 THEN 'STORAGE'
    WHEN 2 THEN 'DATABASE'
    WHEN 3 THEN 'AI'
    ELSE 'NETWORK'
  END AS PRODUCT_CATEGORY,
  ROUND(
    100
    + MOD(lc.RN * 37 + s.SEQ_NO * 53, 1500)
    + GREATEST(NVL(lc.C_ACCTBAL, 0), 0) * 0.01,
    2
  ) AS ORDER_AMOUNT
FROM STG_ORA_LAB_CUSTOMERS lc
CROSS JOIN (
  SELECT LEVEL AS SEQ_NO
  FROM dual
  CONNECT BY LEVEL <= 3
) s
WHERE MOD(lc.RN + s.SEQ_NO, 4) <> 0;

COMMIT;

確認します。

SELECT COUNT(*) AS order_count
FROM ORA_APP.ORA_SALES_ORDER@BASEDB19C_LINK;

このロジックでは、件数は 675 になります。


6-1-3. ORA_MARKETING_TOUCHへINSERTする

INSERT INTO ORA_APP.ORA_MARKETING_TOUCH@BASEDB19C_LINK (
  TOUCH_ID,
  C_CUSTKEY,
  CAMPAIGN_NAME,
  SENT_DATE,
  OPENED_FLAG,
  CLICKED_FLAG,
  RESPONSE_STATUS
)
SELECT
  lc.RN AS TOUCH_ID,
  lc.C_CUSTKEY,
  CASE MOD(lc.RN, 4)
    WHEN 0 THEN 'AI導入キャンペーン'
    WHEN 1 THEN 'クラウド移行キャンペーン'
    WHEN 2 THEN 'データ活用キャンペーン'
    ELSE 'セキュリティ強化キャンペーン'
  END AS CAMPAIGN_NAME,
  DATE '2025-01-05' + MOD(lc.RN * 5, 100) AS SENT_DATE,
  CASE
    WHEN MOD(lc.RN, 3) <> 0 THEN 'Y'
    ELSE 'N'
  END AS OPENED_FLAG,
  CASE
    WHEN MOD(lc.RN, 5) = 0 THEN 'Y'
    ELSE 'N'
  END AS CLICKED_FLAG,
  CASE
    WHEN MOD(lc.RN, 5) = 0 THEN 'RESPONDED'
    WHEN MOD(lc.RN, 3) <> 0 THEN 'OPENED_ONLY'
    ELSE 'NO_RESPONSE'
  END AS RESPONSE_STATUS
FROM STG_ORA_LAB_CUSTOMERS lc
WHERE MOD(lc.RN, 2) = 0;

COMMIT;

確認します。

SELECT COUNT(*) AS marketing_touch_count
FROM ORA_APP.ORA_MARKETING_TOUCH@BASEDB19C_LINK;

結果は 150 になります。


6-1-4. ORA_SUPPORT_CASEへINSERTする

INSERT INTO ORA_APP.ORA_SUPPORT_CASE@BASEDB19C_LINK (
  CASE_ID,
  C_CUSTKEY,
  OPENED_DATE,
  ISSUE_TYPE,
  PRIORITY,
  STATUS,
  SATISFACTION_SCORE
)
SELECT
  lc.RN AS CASE_ID,
  lc.C_CUSTKEY,
  DATE '2025-02-01' + MOD(lc.RN * 3, 90) AS OPENED_DATE,
  CASE MOD(lc.RN, 4)
    WHEN 0 THEN 'PERFORMANCE'
    WHEN 1 THEN 'BILLING'
    WHEN 2 THEN 'USAGE'
    ELSE 'SECURITY'
  END AS ISSUE_TYPE,
  CASE MOD(lc.RN, 3)
    WHEN 0 THEN 'HIGH'
    WHEN 1 THEN 'MEDIUM'
    ELSE 'LOW'
  END AS PRIORITY,
  CASE
    WHEN MOD(lc.RN, 5) = 0 THEN 'OPEN'
    ELSE 'CLOSED'
  END AS STATUS,
  CASE
    WHEN MOD(lc.RN, 5) = 0 THEN CAST(NULL AS NUMBER)
    ELSE MOD(lc.RN, 5) + 1
  END AS SATISFACTION_SCORE
FROM STG_ORA_LAB_CUSTOMERS lc
WHERE MOD(lc.RN, 3) = 0;

COMMIT;

確認します。

SELECT COUNT(*) AS support_case_count
FROM ORA_APP.ORA_SUPPORT_CASE@BASEDB19C_LINK;

結果は 100 になります。


6-2. BaseDB 19c側の投入結果をまとめて確認する

ADBからDB Link経由で確認します。

SELECT 'ORA_LAB_CUSTOMERS' AS table_name, COUNT(*) AS row_count
FROM ORA_APP.ORA_LAB_CUSTOMERS@BASEDB19C_LINK
UNION ALL
SELECT 'ORA_SALES_ORDER' AS table_name, COUNT(*) AS row_count
FROM ORA_APP.ORA_SALES_ORDER@BASEDB19C_LINK
UNION ALL
SELECT 'ORA_MARKETING_TOUCH' AS table_name, COUNT(*) AS row_count
FROM ORA_APP.ORA_MARKETING_TOUCH@BASEDB19C_LINK
UNION ALL
SELECT 'ORA_SUPPORT_CASE' AS table_name, COUNT(*) AS row_count
FROM ORA_APP.ORA_SUPPORT_CASE@BASEDB19C_LINK;

期待する結果です。

TABLE_NAME             ROW_COUNT
-------------------- ----------
ORA_LAB_CUSTOMERS            300
ORA_SALES_ORDER              675
ORA_MARKETING_TOUCH          150
ORA_SUPPORT_CASE             100

ここまでで、元記事でADBローカル表として作っていたデータを、BaseDB 19c側に配置できました。

6-3. BaseDB 19c側にコメントを付ける

ここはBaseDB 19cに ORA_APP で接続して実行します。

こちらをクリックして表示:point_down:
COMMENT ON TABLE ORA_LAB_CUSTOMERS IS
'BaseDB 19c内のサンプル顧客データ。ADBのCUSTOMER_ICEBERGから300件を抽出して投入したデータ。';

COMMENT ON COLUMN ORA_LAB_CUSTOMERS.C_CUSTKEY IS
'顧客キー。CUSTOMER_ICEBERG.C_CUSTKEY由来。';

COMMENT ON COLUMN ORA_LAB_CUSTOMERS.C_MKTSEGMENT IS
'顧客のマーケットセグメント。';

COMMENT ON COLUMN ORA_LAB_CUSTOMERS.C_ACCTBAL IS
'顧客の口座残高。';
COMMENT ON TABLE ORA_SALES_ORDER IS
'BaseDB 19c内のサンプル受注データ。ORA_LAB_CUSTOMERSのC_CUSTKEYと結合する。';

COMMENT ON COLUMN ORA_SALES_ORDER.C_CUSTKEY IS
'顧客キー。ORA_LAB_CUSTOMERS.C_CUSTKEYと結合する。';

COMMENT ON COLUMN ORA_SALES_ORDER.ORDER_AMOUNT IS
'受注金額。売上集計に使用する。';

COMMENT ON COLUMN ORA_SALES_ORDER.CHANNEL IS
'販売チャネル。WEB、STORE、PARTNERのいずれか。';

COMMENT ON COLUMN ORA_SALES_ORDER.PRODUCT_CATEGORY IS
'商品カテゴリ。COMPUTE、STORAGE、DATABASE、AI、NETWORKのいずれか。';
COMMENT ON TABLE ORA_MARKETING_TOUCH IS
'BaseDB 19c内のサンプルキャンペーン接触データ。顧客ごとの開封、クリック、反応状況を持つ。';

COMMENT ON COLUMN ORA_MARKETING_TOUCH.C_CUSTKEY IS
'顧客キー。ORA_LAB_CUSTOMERS.C_CUSTKEYと結合する。';

COMMENT ON COLUMN ORA_MARKETING_TOUCH.CAMPAIGN_NAME IS
'キャンペーン名。';

COMMENT ON COLUMN ORA_MARKETING_TOUCH.RESPONSE_STATUS IS
'キャンペーン反応状況。RESPONDED、OPENED_ONLY、NO_RESPONSEのいずれか。';
COMMENT ON TABLE ORA_SUPPORT_CASE IS
'BaseDB 19c内のサンプルサポート問い合わせデータ。顧客ごとの問い合わせ種別、優先度、満足度を持つ。';

COMMENT ON COLUMN ORA_SUPPORT_CASE.C_CUSTKEY IS
'顧客キー。ORA_LAB_CUSTOMERS.C_CUSTKEYと結合する。';

COMMENT ON COLUMN ORA_SUPPORT_CASE.ISSUE_TYPE IS
'問い合わせ種別。PERFORMANCE、BILLING、USAGE、SECURITYのいずれか。';

COMMENT ON COLUMN ORA_SUPPORT_CASE.SATISFACTION_SCORE IS
'サポート満足度。1から5の数値。未解決の場合はNULL。';

ただし、SELECT AIが直接見るのは、あとで作成するADB側の V_CUSTOMER_360 です。
そのため、SELECT AIの精度に一番効くのは ADB側のViewコメント です。

BaseDB側のコメントは、保守や人間が見る用途として付けておきます。

6-4. BaseDB 19c側にインデックスを作成する

BaseDB 19cに ORA_APP で接続して実行します。

CREATE INDEX IDX_ORA_LAB_CUSTOMERS_KEY
ON ORA_LAB_CUSTOMERS(C_CUSTKEY);
CREATE INDEX IDX_ORA_SALES_ORDER_CUST
ON ORA_SALES_ORDER(C_CUSTKEY);
CREATE INDEX IDX_ORA_MARKETING_TOUCH_CUST
ON ORA_MARKETING_TOUCH(C_CUSTKEY);
CREATE INDEX IDX_ORA_SUPPORT_CASE_CUST
ON ORA_SUPPORT_CASE(C_CUSTKEY);

サンプルデータは小さいので性能上は必須ではありません。
ただ、実際の業務データを想定すると、結合列にインデックスを作っておくのは自然です。

■ 7. ADB側にDB Link参照用Viewを作成する

ここから再びADB側の作業です。
ADBに ADMIN で接続します。

BaseDB 19c上の表を、ADB側のビューとして見せます。

7-1. ビューを作成します

こちらをクリックして表示:point_down:

7-1-1. V_ORA_LAB_CUSTOMERS

CREATE OR REPLACE VIEW V_ORA_LAB_CUSTOMERS AS
SELECT
  C_CUSTKEY,
  C_NAME,
  C_NATIONKEY,
  C_MKTSEGMENT,
  C_ACCTBAL,
  RN
FROM ORA_APP.ORA_LAB_CUSTOMERS@BASEDB19C_LINK;

7-1-2. V_ORA_SALES_ORDER

CREATE OR REPLACE VIEW V_ORA_SALES_ORDER AS
SELECT
  ORDER_ID,
  C_CUSTKEY,
  ORDER_DATE,
  CHANNEL,
  PRODUCT_CATEGORY,
  ORDER_AMOUNT
FROM ORA_APP.ORA_SALES_ORDER@BASEDB19C_LINK;

7-1-3. V_ORA_MARKETING_TOUCH

CREATE OR REPLACE VIEW V_ORA_MARKETING_TOUCH AS
SELECT
  TOUCH_ID,
  C_CUSTKEY,
  CAMPAIGN_NAME,
  SENT_DATE,
  OPENED_FLAG,
  CLICKED_FLAG,
  RESPONSE_STATUS
FROM ORA_APP.ORA_MARKETING_TOUCH@BASEDB19C_LINK;

7-1-4. V_ORA_SUPPORT_CASE

CREATE OR REPLACE VIEW V_ORA_SUPPORT_CASE AS
SELECT
  CASE_ID,
  C_CUSTKEY,
  OPENED_DATE,
  ISSUE_TYPE,
  PRIORITY,
  STATUS,
  SATISFACTION_SCORE
FROM ORA_APP.ORA_SUPPORT_CASE@BASEDB19C_LINK;

7-2. ADB側の参照Viewを確認する

SELECT COUNT(*) AS customer_count
FROM V_ORA_LAB_CUSTOMERS;
SELECT COUNT(*) AS order_count
FROM V_ORA_SALES_ORDER;
SELECT COUNT(*) AS marketing_touch_count
FROM V_ORA_MARKETING_TOUCH;
SELECT COUNT(*) AS support_case_count
FROM V_ORA_SUPPORT_CASE;

期待値です。

V_ORA_LAB_CUSTOMERS       300
V_ORA_SALES_ORDER         675
V_ORA_MARKETING_TOUCH     150
V_ORA_SUPPORT_CASE        100

7-3. ADB側のViewにコメントを付ける

SELECT AIにとっては、ADB側のViewや列コメントが重要です。
BaseDB 19c側の実表ではなく、SELECT AIの対象になるADB側オブジェクトにコメントを付けます。

こちらをクリックして表示:point_down:
COMMENT ON TABLE V_ORA_LAB_CUSTOMERS IS
'BaseDB 19c上の顧客データをDB Link経由で参照するView。CUSTOMER_ICEBERGから抽出した300件の顧客情報。';

COMMENT ON COLUMN V_ORA_LAB_CUSTOMERS.C_CUSTKEY IS
'顧客キー。';

COMMENT ON COLUMN V_ORA_LAB_CUSTOMERS.C_NAME IS
'顧客名。';

COMMENT ON COLUMN V_ORA_LAB_CUSTOMERS.C_NATIONKEY IS
'国キー。NATION_ICEBERG.N_NATIONKEYと結合する。';

COMMENT ON COLUMN V_ORA_LAB_CUSTOMERS.C_MKTSEGMENT IS
'顧客のマーケットセグメント。';

COMMENT ON COLUMN V_ORA_LAB_CUSTOMERS.C_ACCTBAL IS
'顧客の口座残高。';
COMMENT ON TABLE V_ORA_SALES_ORDER IS
'BaseDB 19c上の受注・売上データをDB Link経由で参照するView。顧客別の注文、販売チャネル、商品カテゴリ、受注金額を持つ。';

COMMENT ON COLUMN V_ORA_SALES_ORDER.C_CUSTKEY IS
'顧客キー。V_ORA_LAB_CUSTOMERS.C_CUSTKEYと結合する。';

COMMENT ON COLUMN V_ORA_SALES_ORDER.ORDER_AMOUNT IS
'受注金額。売上集計に使用する。';
COMMENT ON TABLE V_ORA_MARKETING_TOUCH IS
'BaseDB 19c上のキャンペーン接触データをDB Link経由で参照するView。顧客ごとの開封、クリック、反応状況を持つ。';

COMMENT ON COLUMN V_ORA_MARKETING_TOUCH.C_CUSTKEY IS
'顧客キー。V_ORA_LAB_CUSTOMERS.C_CUSTKEYと結合する。';

COMMENT ON COLUMN V_ORA_MARKETING_TOUCH.RESPONSE_STATUS IS
'キャンペーン反応状況。RESPONDED、OPENED_ONLY、NO_RESPONSEのいずれか。';
COMMENT ON TABLE V_ORA_SUPPORT_CASE IS
'BaseDB 19c上のサポート問い合わせデータをDB Link経由で参照するView。顧客ごとの問い合わせ種別、優先度、満足度を持つ。';

COMMENT ON COLUMN V_ORA_SUPPORT_CASE.C_CUSTKEY IS
'顧客キー。V_ORA_LAB_CUSTOMERS.C_CUSTKEYと結合する。';

COMMENT ON COLUMN V_ORA_SUPPORT_CASE.SATISFACTION_SCORE IS
'サポート満足度。1から5の数値。未解決の場合はNULL。';

■ 8. ADB側にV_CUSTOMER_360を作成する

元記事の V_CUSTOMER_360 を、DB Link参照Viewを使う形に変更します。

8-1. ビューを作成する

ADBで以下を実行します。

こちらをクリックして表示:point_down:
CREATE OR REPLACE VIEW V_CUSTOMER_360 AS
WITH sales AS (
  SELECT
    C_CUSTKEY,
    COUNT(*) AS ORDER_COUNT,
    ROUND(SUM(ORDER_AMOUNT), 2) AS TOTAL_SALES,
    ROUND(AVG(ORDER_AMOUNT), 2) AS AVG_ORDER_AMOUNT,
    MAX(ORDER_DATE) AS LAST_ORDER_DATE
  FROM V_ORA_SALES_ORDER
  GROUP BY C_CUSTKEY
),
marketing AS (
  SELECT
    C_CUSTKEY,
    COUNT(*) AS CAMPAIGN_TOUCH_COUNT,
    SUM(CASE WHEN OPENED_FLAG = 'Y' THEN 1 ELSE 0 END) AS OPENED_COUNT,
    SUM(CASE WHEN CLICKED_FLAG = 'Y' THEN 1 ELSE 0 END) AS CLICKED_COUNT,
    SUM(CASE WHEN RESPONSE_STATUS = 'RESPONDED' THEN 1 ELSE 0 END) AS RESPONDED_COUNT
  FROM V_ORA_MARKETING_TOUCH
  GROUP BY C_CUSTKEY
),
support AS (
  SELECT
    C_CUSTKEY,
    COUNT(*) AS SUPPORT_CASE_COUNT,
    SUM(CASE WHEN STATUS = 'OPEN' THEN 1 ELSE 0 END) AS OPEN_CASE_COUNT,
    ROUND(AVG(SATISFACTION_SCORE), 2) AS AVG_SATISFACTION_SCORE
  FROM V_ORA_SUPPORT_CASE
  GROUP BY C_CUSTKEY
),
nation_dedup AS (
  SELECT
    N_NATIONKEY,
    MAX(N_NAME) AS N_NAME
  FROM NATION_ICEBERG
  GROUP BY N_NATIONKEY
)
SELECT
  lc.C_CUSTKEY,
  lc.C_NAME AS CUSTOMER_NAME,
  n.N_NAME AS NATION,
  lc.C_MKTSEGMENT AS MARKET_SEGMENT,
  lc.C_ACCTBAL AS ACCOUNT_BALANCE,

  NVL(s.ORDER_COUNT, 0) AS ORDER_COUNT,
  NVL(s.TOTAL_SALES, 0) AS TOTAL_SALES,
  NVL(s.AVG_ORDER_AMOUNT, 0) AS AVG_ORDER_AMOUNT,
  s.LAST_ORDER_DATE,

  NVL(m.CAMPAIGN_TOUCH_COUNT, 0) AS CAMPAIGN_TOUCH_COUNT,
  NVL(m.OPENED_COUNT, 0) AS OPENED_COUNT,
  NVL(m.CLICKED_COUNT, 0) AS CLICKED_COUNT,
  NVL(m.RESPONDED_COUNT, 0) AS RESPONDED_COUNT,

  NVL(sp.SUPPORT_CASE_COUNT, 0) AS SUPPORT_CASE_COUNT,
  NVL(sp.OPEN_CASE_COUNT, 0) AS OPEN_CASE_COUNT,
  sp.AVG_SATISFACTION_SCORE
FROM V_ORA_LAB_CUSTOMERS lc
LEFT JOIN nation_dedup n
  ON lc.C_NATIONKEY = n.N_NATIONKEY
LEFT JOIN sales s
  ON lc.C_CUSTKEY = s.C_CUSTKEY
LEFT JOIN marketing m
  ON lc.C_CUSTKEY = m.C_CUSTKEY
LEFT JOIN support sp
  ON lc.C_CUSTKEY = sp.C_CUSTKEY;

これで、ADB側の V_CUSTOMER_360 から以下を統合して参照できます。

顧客データ      : BaseDB 19cのORA_LAB_CUSTOMERS
国データ        : ADBのNATION_ICEBERG
売上データ      : BaseDB 19cのORA_SALES_ORDER
キャンペーン    : BaseDB 19cのORA_MARKETING_TOUCH
サポート        : BaseDB 19cのORA_SUPPORT_CASE

8-2. V_CUSTOMER_360にコメントを付ける

SELECT AIの対象は、この V_CUSTOMER_360 です。
そのため、ここに丁寧なコメントを付けます。

こちらをクリックして表示:point_down:
COMMENT ON TABLE V_CUSTOMER_360 IS
'BaseDB 19c上の顧客・売上・キャンペーン・サポートデータと、ADB上のNATION_ICEBERGの国データを統合した顧客360度分析ビュー。SELECT AIで自然言語分析するための中心ビュー。';
COMMENT ON COLUMN V_CUSTOMER_360.C_CUSTKEY IS
'顧客キー。顧客を一意に識別するID。';

COMMENT ON COLUMN V_CUSTOMER_360.CUSTOMER_NAME IS
'顧客名。BaseDB 19cのORA_LAB_CUSTOMERSに格納された、CUSTOMER_ICEBERG由来の顧客名。';

COMMENT ON COLUMN V_CUSTOMER_360.NATION IS
'国名。ADB上のNATION_ICEBERG由来。';

COMMENT ON COLUMN V_CUSTOMER_360.MARKET_SEGMENT IS
'顧客のマーケットセグメント。';

COMMENT ON COLUMN V_CUSTOMER_360.ACCOUNT_BALANCE IS
'顧客の口座残高。資金余力の目安として使用する。';

COMMENT ON COLUMN V_CUSTOMER_360.ORDER_COUNT IS
'顧客別の注文件数。BaseDB 19c上の受注データから集計。';

COMMENT ON COLUMN V_CUSTOMER_360.TOTAL_SALES IS
'顧客別の総売上。BaseDB 19c上の受注データから計算。';

COMMENT ON COLUMN V_CUSTOMER_360.AVG_ORDER_AMOUNT IS
'顧客別の平均注文金額。';

COMMENT ON COLUMN V_CUSTOMER_360.LAST_ORDER_DATE IS
'顧客の最終注文日。';

COMMENT ON COLUMN V_CUSTOMER_360.CAMPAIGN_TOUCH_COUNT IS
'顧客に対するキャンペーン接触回数。';

COMMENT ON COLUMN V_CUSTOMER_360.OPENED_COUNT IS
'顧客がキャンペーンを開封した回数。';

COMMENT ON COLUMN V_CUSTOMER_360.CLICKED_COUNT IS
'顧客がキャンペーンをクリックした回数。';

COMMENT ON COLUMN V_CUSTOMER_360.RESPONDED_COUNT IS
'顧客がキャンペーンに反応した回数。RESPONDEDの件数。';

COMMENT ON COLUMN V_CUSTOMER_360.SUPPORT_CASE_COUNT IS
'顧客別のサポート問い合わせ件数。';

COMMENT ON COLUMN V_CUSTOMER_360.OPEN_CASE_COUNT IS
'未解決のサポート問い合わせ件数。';

COMMENT ON COLUMN V_CUSTOMER_360.AVG_SATISFACTION_SCORE IS
'サポート満足度の平均。1から5の数値。未解決のみの場合はNULLになることがある。';

8-3. V_CUSTOMER_360を確認する

件数を確認します。

SELECT COUNT(*) AS customer_360_count
FROM V_CUSTOMER_360;

結果が 300 ならOKです。

売上上位顧客トップ10を確認する

SELECT
  CUSTOMER_NAME,
  NATION,
  MARKET_SEGMENT,
  TOTAL_SALES,
  ORDER_COUNT,
  RESPONDED_COUNT,
  SUPPORT_CASE_COUNT
FROM V_CUSTOMER_360
ORDER BY TOTAL_SALES DESC
FETCH FIRST 10 ROWS ONLY;

このSQLで、以下が統合できていることを確認できます。

CUSTOMER_NAME      : BaseDB 19c上の顧客データ
NATION             : ADB上のNATION_ICEBERG
MARKET_SEGMENT     : BaseDB 19c上の顧客データ
TOTAL_SALES        : BaseDB 19c上の売上データ
ORDER_COUNT        : BaseDB 19c上の売上データ
RESPONDED_COUNT    : BaseDB 19c上のマーケティングデータ
SUPPORT_CASE_COUNT : BaseDB 19c上のサポートデータ

image.png

■ 9. SELECT AI用Credentialを確認する

元記事では、SELECT AI用のCredentialとしてOCI_GENAIを使っています。

SELECT credential_name
FROM user_credentials
WHERE credential_name = 'OCI_GENAI';

■ 10. SELECT AI用プロファイルを作成する

元記事に合わせて、プロファイル名は GENAI_CUSTOMER360 にします。

今回、SELECT AIの対象にするのはADB側の V_CUSTOMER_360 だけです。

BEGIN
  BEGIN
    DBMS_CLOUD_AI.DROP_PROFILE('GENAI_CUSTOMER360');
  EXCEPTION
    WHEN OTHERS THEN NULL;
  END;

  DBMS_CLOUD_AI.CREATE_PROFILE(
    profile_name => 'GENAI_CUSTOMER360',
    attributes   => '{
      "provider"       : "oci",
      "credential_name": "OCI_GENAI",
      "model"          : "xai.grok-4",
      "region"         : "us-chicago-1",
      "object_list"    : [
        {"owner": "ADMIN", "name": "V_CUSTOMER_360"}
      ],
      "comments": true
    }'
  );
END;
/

■ 11. Select AIを試す

ここまでで、ADB上に V_CUSTOMER_360 を作成し、SELECT AI用のプロファイル GENAI_CUSTOMER360 も作成できました。

この章では、実際に自然言語で問い合わせを行い、SELECT AIが V_CUSTOMER_360 の表定義やコメントをもとにSQLを生成できることを確認します。

11-1. SELECT AIでSQLだけ生成して確認する

本番データや複雑な問い合わせでは、まず showsql でSQLの内容を確認してから実行するのがおすすめです。

V_CUSTOMER_360を使って、マーケットセグメントごとの顧客数、総売上、平均売上、サポート問い合わせ件数を表示してください。総売上が多い順に並べてください。

SELECT DBMS_CLOUD_AI.GENERATE(
  prompt       => 'V_CUSTOMER_360を使って、マーケットセグメントごとの顧客数、総売上、平均売上、サポート問い合わせ件数を表示してください。総売上が多い順に並べてください。',
  profile_name => 'GENAI_CUSTOMER360',
  action       => 'showsql'
) AS generated_sql
FROM dual;

image.png

生成されたSQLでは、V_CUSTOMER_360 を対象にして、マーケットセグメント単位で集計が行われています。
このように、自然言語の「顧客数」「総売上」「平均売上」「サポート問い合わせ件数」といった表現が、ビュー上の列に対応するSQLへ変換されます。

生成されたSQLの意味を確認したい場合は、explainsql を使います。

explainsql は、生成されたSQLが何をしているのかを自然言語で説明してくれるため、SQLの妥当性を確認したい場合に便利です。

image.png

ここまでで、SELECT AIが V_CUSTOMER_360 の構造をもとに、自然言語からSQLを生成できることを確認できました。

11-2. 分析してみる

次に、より業務寄りの分析を試します。

ここでは、単純な集計ではなく、次のような条件を組み合わせた顧客抽出を行います。

  • キャンペーンに反応している
  • 口座残高が高い
  • まだ総売上が低い
  • 営業フォロー候補として上位10件を表示する

このような問い合わせは、通常であれば条件や並び順をSQLで細かく書く必要があります。
SELECT AIを使うと、利用者は分析したい観点を自然言語で指定できます。

V_CUSTOMER_360を使って、キャンペーンに反応しており、口座残高が高いが、総売上が低い顧客を営業フォロー候補として10件表示してください。顧客名、国、マーケットセグメント、口座残高、総売上、キャンペーン反応回数を表示してください。

SELECT DBMS_CLOUD_AI.GENERATE(
  prompt       => 'V_CUSTOMER_360を使って、キャンペーンに反応しており、口座残高が高いが、総売上が低い顧客を営業フォロー候補として10件表示してください。顧客名、国、マーケットセグメント、口座残高、総売上、キャンペーン反応回数を表示してください。',
  profile_name => 'GENAI_CUSTOMER360',
  action       => 'narrate'
) AS generated_sql
FROM dual;

image.png

ここでは actionnarrate を指定しています。

narrate を使うと、SQLの実行結果をもとに、結果の内容を自然言語で説明してくれます。
そのため、単にSQLや表形式の結果を見るだけでなく、「どのような顧客が営業フォロー候補として抽出されたのか」を文章として確認できます。

これらのデータは、もともとBaseDB 19cやIcebergデータに分かれて存在していました。
しかし、ADB側の V_CUSTOMER_360 に統合しておくことで、SELECT AIからは1つの分析用ビューとして扱えます。

このように、ADBをAI検索のハブとして使うことで、複数データソースをまたいだ分析を自然言語で実行できることが確認できました。

おわりに

今回は、ADBを AIプロキシ・データベース / サイドカー として利用し、BaseDB 19cと外部データソースを組み合わせてSELECT AIから自然言語検索する構成を確認しました。

ポイントは、すべてのデータをADBに取り込むのではなく、ADBを問い合わせの入口として利用する点です。
DB Linkや外部データ参照を使って複数のデータソースをつなぎ、ADB側に分析用Viewを作成することで、利用者はデータの配置を意識せずに自然言語で分析できます。

また、SELECT AIでは表名・列名・コメントがSQL生成に利用されるため、分析対象となるViewに分かりやすいコメントを付けておくことが重要です。

この構成を使うことで、既存の基幹データを活かしながら、ADBを中心にしたAI検索・自然言語分析の仕組みを作ることができます。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?