Upgrade to Pro — share decks privately, control downloads, hide ads and more …

【20261028 AI×DevOpsStudy #26】AIを用いた SQL & PL/SQ...

【20261028 AI×DevOpsStudy #26】AIを用いた SQL & PL/SQLの移行、ScalarDBへの移行例

■ AI×DevOps Study #26の概要
2026年10月28日に開催した「AI×DevOps Study」第26回の勉強会資料です。

「AI×DevOps Study」は、AI駆動開発やそこに関係するマイクロサービスについて理解を深める場になります。
株式会社ScalarではAIを使ったチーム開発を進めており、参画しているメンバーや協力会社の方から、具体的なAI駆動開発を実施する方法、その中で生まれたマイクロサービスアーキテクチャを使用したAI駆動開発の事例や実際に使えるエージェントについてお話頂き、参加者の皆様と知識の共有や交換を目的としています。
(弊社製品であるScalarDBも絡んだお話も一部出てきますが、汎用的な内容となっておりますのでフラットにお楽しみいいただけます)

■ 今回のテーマ
今回のテーマは、「AIを用いた SQL & PL/SQLの移行、ScalarDBへの移行例 ~Oracle の SQL とOracle PL/SQL を ScalarDB へ移す PoC~」です。

OracleのSQLやPL/SQLをScalarDBへ移行するPoCを自動化ツールを利用して実施した内容になります。
変換可能なSQLの自動書き換えや、変換が困難な構文の実行計画への分解に加え、AIエージェントを活用した人による判断・承認プロセス、実データベースを用いた網羅的な検証手法について説明します。

■ 登壇者情報(敬称略)
深津航

株式会社Scalar Founder & CEO。日本オラクル株式会社、決済系のスタートアップを経て、株式会社Scalarを創業。

■関連コンテンツ
・Youtube(過去の勉強会動画も公開中!)
www.youtube.com/@scalar-labs

・Zenn ブログ
https://zenn.dev/p/scalar_sol_blog

・イベントページ(connpass)
https://scalar.connpass.com/

Avatar for Scalar, Inc.

Scalar, Inc. PRO

November 05, 2026

More Decks by Scalar, Inc.

Other Decks in Technology

Transcript

  1. クラウドネイティブ化から、DB と SQL‧PL/SQL の移⾏へ 1 2 3 4 5 クラウドネイティブ

    への移⾏ DB の移⾏先を選ぶ 次のネック 設計に戻して再⽣成 デモ 作り‧運⽤‧組織が変わる 4 つの選択肢から選ぶ SQL の変換と PL/SQL の書き直し 仕様に戻して作り直す このリポジトリのツールと スキル この資料の中⼼は 4:変換器に直訳させず、原⽂から仕様(要件‧設計)を起こし、⼈の判断を記録してから再⽣成する AIxDevOps © 2026 Scalar, inc. 2
  2. サーバを移すことより、作りと運⽤を変えないことでつまずく ⾒えている作業 ‧サーバを新しい場所に移す ‧OS とミドルウェアを載せ替える ⾒落とされやすい変化 ‧サーバに状態を持たない作り ‧障害を前提にした設計 ‧IaC‧CI/CD‧オブザーバビリティ ‧ID

    ごとに守るセキュリティ ‧費⽤の管理の仕⽅ ‧チームの役割とスキル 置き場所だけを変える移⾏(Rehost)は早いが、費⽤も運⽤の⼿間もあまり減らない。 AIxDevOps © 2026 Scalar, inc. 4
  3. サーバに状態を持つ作りは、ステートレスに直す オンプレ:状態をサーバが抱える クラウドネイティブ:状態を外に出す アプリサーバ 1 台 アプリ 1 キャッシュ (セッション)

    アプリ 2 ストレージ (ファイル) セッション 利⽤者 ローカルファイル LB ログ‧設定 ログ基盤 アプリ 3 固定 IP 秘密情報の保管庫 1 台が落ちると状態ごと失われる。 台数を増やしても負荷を分けられない。 どのアプリが落ちても、残りがそのまま処理を引き継ぐ。 最初から全部をマイクロサービスに分ける必要はない。まず同じアプリを複数台で動かせる形にする。 AIxDevOps © 2026 Scalar, inc. 5
  4. インスタンスは消える前提で、障害を受け流す作りにする 依存先のサービス インスタンス 1 応答が来ない 呼び出し元 インスタンス(障害) クラウドでは、インスタンスの ⼊れ替えや⼀部のゾーンの障害が ⽇常的に起きる。

    呼び出し元が待ち続けると、 障害が全体に広がる。 インスタンス 3 タイムアウト 待つ時間に上限を決める リトライ 間隔を広げて再試⾏する ✓ 冪等性 縮退 重複しても結果を変えない 落ちた先を切り離して動く 可⽤性は、複数のゾーンに置くことだけでは決まらない。アプリが障害を受け流せて初めて冗⻑化が効く。 AIxDevOps © 2026 Scalar, inc. 6
  5. データは最後まで動かしにくいので、移し⽅を最初に決める オンプレ ① ⼀括で移送 クラウド ⼤量なら⽇単位。物理搬送も検討 ② 差分を同期し続ける 現⾏の DB

    新しい DB レプリケーションで追いつく ③ 短い停⽌で切り替える 結果を突き合わせてから DB エンジンの変更 整合性 性能 SQL‧型‧トランザクションの 挙動が変わる DB を分けると、 またがる更新の作り直しが要る アプリと DB の往復が遅いと、 SQL の多い処理が遅くなる データを移す⼿順の前に、「どの DB に移すか」を決める。それが次の章。 AIxDevOps © 2026 Scalar, inc. 7
  6. 移⾏先は⼤きく 4 つ。得意なデータと、失うものが違う マネージド RDBMS SQL‧JOIN‧ トランザクションを そのまま使える。 1 台の性能が上限に

    なりやすい NoSQL NewSQL(分散 SQL) キーで引く読み書きを 横に伸ばせる。 JOIN と複数⾏の トランザクションは弱い SQL と トランザクションを 保ったまま、ノードを ⾜して伸ばせる Blob ストレージ ⼤きなファイルを 安く、ほぼ無制限に 置ける。 検索と更新は苦⼿ 業務の中⼼の データ セッション 履歴‧イベント 伸びる業務データ 地理分散 帳票‧画像 バックアップ 例: PostgreSQL‧MySQL 例: Cassandra‧MongoDB‧Redis 例: CockroachDB‧TiDB 例: S3 互換ストレージ 1 つに決める必要はない。データの性質ごとに置き場所を選ぶ(次の 2 ページ)。 AIxDevOps © 2026 Scalar, inc. 9
  7. データの性質を順に問うと、置き場所が決まる ⼤きなファイル‧帳票‧ バックアップか? はい Blob ストレージ いいえ キーで引くだけで、複数⾏の トランザクションは要らないか? はい

    NoSQL いいえ 1 台の DB で処理量と 容量が⾜りるか? 組み合わせるとき データごとに答えが違えば、 DB を複数使う。 そのときは、DB をまたぐ 更新の整合性を誰が取るか (アプリか、整合性を取る層か) も決める。 はい マネージド RDBMS いいえ NewSQL(分散 SQL) AIxDevOps © 2026 Scalar, inc. 10
  8. 1 つのアプリが、性質の違うデータを別々の DB に置く 業務アプリ(ステートレス) DB をまたぐ更新の整合性を取る層(アプリで作るか、例: ScalarDB) マネージド RDBMS

    NewSQL NoSQL Blob 会員‧残⾼ 注⽂‧明細 ポイント履歴 明細書の PDF 置き場所を分けるほど、DB 1 つで済んでいたトランザクションを作り直す範囲が広がる。 AIxDevOps © 2026 Scalar, inc. 11
  9. 移⾏先ごとに、得られるものと失うものを⽐べる マネージド RDBMS NoSQL NewSQL Blob SQL の互換性 複数⾏のトランザクション ノードを⾜して伸ばす

    運⽤の⼿間の少なさ PL/SQL をそのまま動かす 点の数は⼀般的な傾向(製品と構成で変わる)。どれを選んでも、PL/SQL はそのままでは動かない。 AIxDevOps © 2026 Scalar, inc. 12
  10. 移⾏先を決めても、SQL と PL/SQL の書き換えが残る </> 画⾯‧API そのまま使える アプリの SQL(数百〜数千⽂) ⽅⾔を変換し、意味の差を確かめる

    DB の中の PL/SQL 移⾏先に無いので、アプリ側に書き直す データ 移送ツールと差分の同期で移せる SQL は⽂の数が多く、PL/SQL は DB の機能に深く頼っている。どちらも⼿作業だけでは、判断の経緯が残らない。 AIxDevOps © 2026 Scalar, inc. 14
  11. SQL の違いは 3 つ。危ないのは「結果が黙って変わる」もの ✓ ① 書き換えれば済む ② 結果が黙って変わる 構⽂や関数の名前が違う。

    実⾏するとエラーになるので ⾒つけやすい。 どちらでも動き、 結果だけが違う。 ⽐べないと⾒つからない。 例: ROWNUM‧(+)‧NVL DECODE‧seq.NEXTVAL 例: '' と NULL‧DATE の時刻 整数の除算‧名前の⼤⼩⽂字 ③ 設計から⾒直す 対応する機能が無い。 例: PL/SQL のパッケージ ⾏ロック‧⾃律型 トランザクション DDL の暗黙のコミット ①は機械で直せる。②は機械で⾒つけて⼈が決める。③は要件に戻って設計し直す。 AIxDevOps © 2026 Scalar, inc. 15
  12. 素の変換器は (+) を内部結合にし、ROWNUM を残す -- Oracle SELECT e.ename, d.dname FROM

    emp e, dept d WHERE e.deptno = d.deptno(+); -- PostgreSQL(sql-transpile の出力) SELECT e.ename, d.dname FROM emp AS e LEFT JOIN dept AS d ON e.deptno = d.deptno; SELECT ename, NVL(comm, 0) AS comm FROM emp WHERE ROWNUM <= 5; SELECT ename, COALESCE(comm, 0) AS comm FROM emp LIMIT 5; SELECT ename FROM emp WHERE hiredate > SYSDATE - 30; -- WARN DATE_ARITH: SYSDATE - 30 は -型によって interval か型エラー 素の sqlglot.transpile(read='oracle', write='postgres') の出⼒ WHERE e.deptno = d.deptno … (+) が消えて内部結合になり、⾏が黙って減る WHERE ROWNUM <= 5 … そのまま残り、PostgreSQL で実⾏時エラーになる AIxDevOps © 2026 Scalar, inc. 16
  13. PL/SQL は DB の機能に頼り、直訳すると意味が変わる ① SYSDATE -- pkg_points.pkb(use_points、抜粋) v_now DATE

    := SYSDATE; ... SELECT balance, last_seq INTO v_balance, v_seq FROM members WHERE member_id = p_member_id FOR UPDATE; DB の時計。時刻と型(DATE は時刻を持つ) ② FOR UPDATE ⾏ロックで同時の利⽤を待たせる。移⾏先に無いことが多い IF v_balance < p_points THEN RAISE_APPLICATION_ERROR(-20103, 'ポイントが不足しています '); END IF; ... UPDATE members SET balance = v_balance - p_points WHERE member_id = p_member_id; ③ -20103 業務のエラーコード。呼び出し側がこれで分岐している ④ COMMIT が無い トランザクションの境界は呼び出し側にある AIxDevOps © 2026 Scalar, inc. 17
  14. 直訳せず、仕様と判断を経由して再⽣成する 直訳する道 原⽂ 新しいコード 変換器(1 ⽂ずつ置き換え) 意味のずれと、判断の 経緯が残らない 設計に戻す道(このツール) 解析

    AST‧IR 原⽂ 仕様 要件‧設計 判断と承認 limits.yaml 再⽣成 SQL‧Java 突き合わせ 証拠 差が出たら、仕様か判断に戻って作り直す ⽣成物は⼿で直さない。直すのは原⽂‧仕様‧判断の記録で、そこから何度でも同じものが出る。 AIxDevOps © 2026 Scalar, inc. 19
  15. SQLGlot: SQL を⽊(AST)にして、別の⽅⾔で書き出す Select import sqlglot Column ename Coalesce (is_nvl)

    From Table emp sql = "SELECT ename, NVL(comm, 0) FROM emp" " WHERE deptno = 10" Where EQ tree = sqlglot.parse_one(sql, read="oracle") # NVL は Coalesce(is_nvl=True) になる print(tree.sql(dialect="postgres")) # SELECT ename, COALESCE(comm, 0) # FROM emp WHERE deptno = 10 print(tree.sql(dialect="mysql")) # SELECT ename, COALESCE(comm, 0) ... Column deptno AIxDevOps Literal 10 © 2026 Scalar, inc. 20
  16. SQLGlot の前後で直して検査し、⽂ごとに判定する 前処理 SQLGlot 意味の検査 往復の検証 判定と出⼒ ROWNUM‧(+) を直す AST

    にして書き出す 空⽂字‧⽇付‧除算 変換先で読み直す OK‧WARN‧ERROR ScalarDB を移⾏先にしたとき(points.sql の 20 ⽂) [ 7 6 4 3 OK WARN PLANNED ERROR 8] ERROR UPDATE SET balance = balance + 100 -> SELECT -> 計算 -> UPDATE を 1 つのトランザクションで [ 14] WARN SELECT ... ROWNUM <= 3 -> LIMIT 3。Oracle は ORDER BY の 前に数えるので結果が変わりうる PLANNED = ScalarDB から取得し、残りを H2 で実⾏する計画に分解した⽂ AIxDevOps © 2026 Scalar, inc. 21
  17. ANTLR: PL/SQL を構⽂⽊にし、IR を事実の源にする PL/SQL 原⽂ ANTLR PL/SQL ⽂法 構⽂⽊

    判定(AUTO‧REVIEW‧REDESIGN) IR 意味つき // program.ir.json(抜粋) { "id": "pkg_points.use_points#stmt-3", "kind": "SqlOperation", "sourceRange": { "file": "pkg_points.pkb", "startLine": 69, "endLine": 72 }, "diagnostics": [ { "severity": "WARN", "code": "ROW_LOCK", "message": "FOR UPDATE is row locking; the target has to provide the same guarantee another way" } ] } Java(Service‧Repository) 仕様書の事実の欄 トレーサビリティ AIxDevOps © 2026 Scalar, inc. 22
  18. IR から仕様の事実を出し、業務ルールは原⽂を読んで書く 開始 L64: p_points <= 0 ? 事実の欄(機械) エラー

    -20102 引数‧読み書きする表‧SQL‧エラーコード‧ 処理の流れの図。原⽂が変わると「古い」と検査で分かる L69: SELECT members(FOR UPDATE) ⽂章(⼈と AI が原⽂を読む) L74: v_balance < p_points ? エラー -20103 動作‧業務ルール‧確かめたいことを、原⽂の位置 (pkg_points.pkb:74)つきで書く。例: 「会員がいないとき use_points だけ NO_DATA_FOUND をそのまま出す」 L80: INSERT point_history L84: UPDATE members use_points の処理の流れ(IR から機械的に出した図) AIxDevOps © 2026 Scalar, inc. 23
  19. ⼈が決めたことを記録し、それを読んで再⽣成する # limits.yaml(決めた人・日付・理由) rowLocks: optimistic: pkg_points.use_points: >残高は同じトランザクションの中で 読んだ値から計算して書く。同時の 利用は commit

    で衝突として弾かれ るので、残高はマイナスにならない // 生成された PkgPointsService.java // pkg_points.pkb:69 // FOR UPDATE を落とした // (rowLocks.optimistic)。 // 同じ行を書く衝突は commit で弾かれる var row = repository .usePointsStmt3(pMemberId); vBalance = Plsql.fitLong(row[0], 10); 決めていない routine の書き込みは、⽣成器が拒否したまま 決定を変えたら再⽣成。⼿で直した⽣成物は次の⽣成で消える ⽣成物には原⽂の⾏番号と、決定の理由がコメントで残る AIxDevOps © 2026 Scalar, inc. 24
  20. 同じシナリオを移⾏元と移⾏先で流し、⼀致したことを証拠にする Oracle で実⾏ シナリオ (承認済みの仕様から) ⼀致 → 証拠(指紋つき) 結果を⽐べる 表‧例外‧戻り値

    証拠のある routine だけ AUTO ⽣成した Java で実⾏ 原⽂か⽣成器が変わると指紋が合わなくなり、証拠は「古い」になって REVIEW に戻る 出典: docs/guide/tutorial.md(ポイントカードの例: 承認済みの仕様から起こした 13 シナリオが、すべて Oracle と⼀致) AIxDevOps © 2026 Scalar, inc. 25
  21. migrate-flow: 3 つの承認がそろうまでテストに進めない ✓ ① 現⾏の仕様 plsql-spec スキル ② ⼈の判断

    承認 plsql-migrate スキル ③ 変換後の仕様 承認 承認 実 DB で突き合わせ 承認は、承認した⼈‧⽇付‧そのときの中⾝の指紋で記録す る。承認のあとで原⽂や⽣成物が変わると承認は古くなり、変 えた所を⽰して取り直す。 $ flow.py approve spec --by 移行責任者 \ --date 2026-09-20 $ flow.py gate GATE=closed # 3 つそろうと open AIxDevOps plsql-migrate スキル ④ テスト © 2026 Scalar, inc. 26
  22. デモ 1: SQL 変換のコマンドを直接動かす 動画の流れ ① 素の SQLGlot の出⼒ ②

    sql-transpile の変換で PostgreSQL へ ③ ScalarDB 向けに⽂ごとに判定 ④ 取得 + H2 の実⾏計画 Claude は使わない。スキルが裏で呼ぶコマンドを直接実⾏した(DB も要らない)。 AIxDevOps © 2026 Scalar, inc. 28
  23. デモ 2: PL/SQL 変換のコマンドを直接動かす 動画の流れ ① 移⾏元の PL/SQL(use_points) ② ANTLR

    で解析、IR と判定 ③ 仕様書の事実の欄(Mermaid) ④ limits.yaml の決定 ⑤ Java を再⽣成しコンパイル ⑥ ⽣成された Java ⑦ migrate-flow の関⾨ Claude は使わない。スキルが裏で呼ぶコマンドを直接実⾏した。⽂章を書く‧判断を確かめる所はデモ 3。 AIxDevOps © 2026 Scalar, inc. 29
  24. デモ 3: Claude Code で migrate-flow スキルを呼ぶ 動画の流れ ① ⾃然⽂で移⾏を頼む

    ② スキルを読み、IR と事実の欄を出す ③ 原⽂を読んで仕様の⽂章を書く ④ 検査 0 件で承認を求めて⽌まる ⑤ 承認 → 段階 2 で Java を⽣成 ⑥ 判断を推奨‧理由‧影響つきで聞く ⑦ 推奨どおり記録し、承認を待つ claude -p で実際に動かしたセッションの記録を早送りで再⽣(実時間は約 7 分)。作業⽤の複製で実⾏した。 AIxDevOps © 2026 Scalar, inc. 30
  25. まとめ: 移⾏先を選び、SQL と PL/SQL は設計に戻して作り直す </> ✓ クラウドネイティブ化 置き場所より、作り‧運⽤‧組織を変える 移⾏先を選ぶ

    データの性質ごとに RDBMS‧NoSQL‧NewSQL‧Blob を使い分ける SQL を変換する SQLGlot で AST にし、意味の差は検出して⼈が決める PL/SQL を書き直す ANTLR で IR にし、仕様と判断を経て Java に再⽣成する 確かめる 同じシナリオを両⽅で流し、⼀致を証拠として残す ツールとスキル: github.com/wfukatsu/sql-migration(Claude Code / Codex の marketplace から⼊れられる) AIxDevOps © 2026 Scalar, inc. 31
  26. Please give us a star on GitH ub! udy AIxDevOps

    St 毎週⽕曜開催 GitHub scalar-labs/scalardb connpass Scalar AIxDevOps © 2026 Scalar, inc.