資格道場 › レッスン一覧 › データベース
データベース・9/13・10分

プログラムからのDB利用とクエリ処理

ゴール

埋込みSQLのカーソル(OPEN→FETCH→WHERE CURRENT OF→CLOSE)、JDBC、ストアドプロシージャの利点、DBMSがクエリを処理する順番(構文解析→最適化→コード生成)を区別できるようになる。これらを問う過去問を、選択肢の用語の意味から自力で解けるようになる。

アプリからDBを使うときの「つなぎ方」と「DBの中で何が起きるか」は、実務のAPI設計でも毎回出てくる話です。試験では用語当てと順番当てが中心なので、ここで覚えればほぼ確実に1点取れます。

このレッスンで稽古する(用語チェック・過去問)

結論:このレッスンで覚える4つ

知識 一言でいうと 出題の形
ストアドプロシージャ よく使うSQLの手順をDBMS側に置いておく 「ネットワーク負荷を減らす仕組みは?」「利点は?」
JDBC JavaからDBにアクセスする標準API 「JavaのDBアクセスAPIは?」
カーソル 検索結果を1行ずつプログラムに渡すしくみ 「Xは何?」「1行ずつ渡す操作に関係する字句は?」
クエリ処理の流れ 構文解析 → 最適化 → コード生成 → 実行 「①〜③の組合せは?」「アクセス経路を選ぶ機能は?」

出題回数はストアドプロシージャが最も多いので、まずここを確実にします。

ストアドプロシージャ:「いつもの」で注文を済ませる

ストアドプロシージャは、よく使う一連のSQL(命令群)をあらかじめDBMS(データベース管理システム)に登録しておき、クライアントからは名前を指定して呼び出すだけにする仕組みです。stored(保存された)procedure(手続き)という意味です。

たとえるなら、行きつけの店で毎回メニューを全部読み上げずに「いつもの」とだけ言うようなものです。クライアントがSQLを1文ずつ送ってそのたびに結果を受け取る往復がなくなり、クライアントとサーバの間の通信量(ネットワーク負荷)が減ります。

試験で「利点」を問われたら、答えは通信量の削減です。サーバ内のディスクアクセス量、メモリ使用量、格納領域が減るわけではありません。処理そのものはサーバ上で同じように実行されるからです。

SQLを1文ずつ送る(往復が多い)クライアントDBMSSQL①結果SQL②結果SQL③結果ストアドプロシージャ(往復1回)クライアントDBMSSQL①②③名前で呼出し結果減るのは通信量。サーバ内の処理は同じ
SQLを1文ずつ送ると往復が3回あるが、ストアドプロシージャなら名前で1回呼ぶだけで済み、通信量が減る。

ストアドプロシージャと並ぶひっかけ選択肢

過去問では毎回ほぼ同じ4択が並びます。どれも「DBまわりの効率化」っぽく見えるのがひっかけです。

選択肢 何のための仕組みか 通信負荷の軽減?
ストアドプロシージャ 命令群をDBMSに格納し、呼出しだけで実行 ○(これが正解)
2相コミットメント 複数のDBにまたがるトランザクションを、全部確定か全部取消しにそろえる ×(分散DBの整合性のため)
グループコミットメント 複数トランザクションのコミット時のログ書込みをまとめて行う ×(ディスク書込み回数を減らすため)
サーバプロセスのマルチスレッド化 サーバが複数の要求を並行して処理する ×(同時処理能力のため)

見分けるコツは、問題文の「あらかじめDBMSに格納」「利用頻度が高い命令群」という言葉です。これが出たらストアドプロシージャです。

JDBC:JavaとDBをつなぐ標準の窓口

JDBC(Java Database Connectivity)は、Javaのプログラムからデータベースにアクセスするための標準API(プログラム同士の呼出し口)です。DBの製品が違っても、Java側は同じ書き方でSQLを送れます。

用語 正体 JavaのDBアクセスAPI?
JDBC JavaからDBにアクセスする標準API ○
JVM(Java VM) Javaのプログラムを実行する仮想マシン ×
JavaBeans Javaのプログラムを再利用しやすい部品にする仕様 ×
Javaアプレット ブラウザ上で動くJavaプログラム ×
SQL DBを操作する言語そのもの ×(APIではない)
HTML Webページを記述する言語 ×

「Java」と「DB」が両方出たら JDBC、と覚えれば十分です。

埋込みSQLとカーソル:結果を1行ずつ受け取る

埋込みSQLは、COBOLやCなどのプログラム(ホスト言語)の中にSQL文を直接書く方式で、EXEC SQL で始まります。困るのは、SQLの検索結果は複数行の表なのに、プログラムの変数は1回に1行分しか受け取れない点です。

このズレを埋めるのがカーソルです。検索結果の表の上を動く「いまどの行を見ているか」の目印で、本に挟むしおりのようなものです。

カーソルの操作は次の順番です。

  1. DECLARE CURSOR:カーソルに名前を付け、どのSELECT文の結果を扱うかを宣言する
  2. OPEN:SELECTを実行し、カーソルを結果の最初の行の手前に置く(この時点ではまだどの行も指していない)
  3. FETCH:カーソルを次の行に進め、その行をホスト変数(プログラム側の変数)に取り出す。取り出した行がカレント行(いまカーソルが指している行)になる
  4. UPDATE / DELETE … WHERE CURRENT OF カーソル名:FETCHで取り出したカレント行を更新・削除する
  5. CLOSE:カーソルを閉じて後片付けする

FETCHを繰り返すと1行目、2行目…と順に進み、最後の行の次でデータなしになって終わります。

カーソル=いま見ている行のしおり検索結果OPEN:手前に1行目FETCH 1回目2行目=カレント行FETCH 2回目3行目FETCH 3回目データなし→終了FETCH 4回目取出しホスト変数UPDATE … WHERE CURRENT OF:カレント行を更新最後に CLOSE で閉じる
OPENで最初の行の手前に置かれたカーソルが、FETCHのたびに1行ずつ進み、指している行(カレント行)をホスト変数に取り出したり、WHERE CURRENT OFで更新したりする。

カーソルの問われ方

コードの中の名前Xが何かを問う問題では、OPEN・FETCH・CLOSE・WHERE CURRENT OF の対象になっていることが決め手です。これらを受け付けるのはカーソルだけです。

選択肢 正体 OPEN/FETCHの対象?
カーソル 検索結果を1行ずつ指す目印 ○
テーブル データを実際に格納する表 ×
ビュー SELECT結果に名前を付けた仮想の表 ×
スキーマ DBの構造(表や列の定義)の枠組み ×

「導出表(問合せの結果としてできる表)を1行ずつ親プログラムに引き渡す」と書かれたら、字句は CURSOR です。ORDER BY(並べ替え)、UNION(結果の和)、UNIQUE(重複禁止の制約)は別の目的の字句です。

DBMSがクエリを実行するまでの流れ

DBMSはSQL文(クエリ)を受け取ると、構文解析 → 最適化 → コード生成 → 実行 の順に処理します。プログラムのコンパイルと似ていて、「読む→作戦を立てる→実行できる形にする」の順です。

flowchart LR
  A["クエリ(SQL文)"] --> B["① 構文解析"]
  B --> C["② 最適化"]
  C --> D["③ コード生成"]
  D --> E["実行"]
段階 やること
構文解析 SQLの文法が正しいか、表名・列名が存在するかを調べ、内部の形に分解する
最適化 索引を使うか、表をどの順で結合するかなど、**最も効率の良いアクセス経路(実行計画)**を選ぶ
コード生成 選んだ実行計画を、実際に実行できる手続きに変換する

最適化を担う機能をオプティマイザと呼びます。「効率が良いアクセス経路を選択する機能は?」と聞かれたらオプティマイザです。

クエリ(SQL文)① 構文解析:文法・表名・列名を確認② 最適化(オプティマイザ)候補A:索引で探す効率が良い→採用候補B:全行を読む効率が悪い→不採用実行計画③ コード生成:実行できる手続きにする実行
構文解析のあと、オプティマイザが複数のアクセス経路から最も効率の良いものを実行計画として選び、それをコード生成で実行できる手続きにする。

クエリ処理の問われ方

順番問題では、最適化とコード生成を入れ替えた選択肢が必ず混ざります。「作戦(実行計画)が決まる前に、実行用の手続きは作れない」と考えれば、最適化が先だと判断できます。最初が構文解析なのは、文を読めなければ何も始まらないからです。

機能名を問う問題では、名前の似た別分野の用語が並びます。

選択肢 正体
オプティマイザ SQLの効率の良いアクセス経路を選ぶRDBMSの機能
ガーベジコレクション 使われなくなったメモリ領域を自動で回収する機能
クラスタリング 関連するデータを物理的に近くに配置すること(またはサーバを束ねる構成)
マージソート 分割して整列し、併合していく整列アルゴリズム
例題 1

クエリ処理の①〜③を埋める

図は,DBMS が受け付けたクエリを実行するまでの処理の流れを表している。①〜③に入る処理の組合せとして,適切なものはどれか。
フロー: クエリ → ① → ② → ③ → 実行(各は四角のボックス,矢印で接続)。選択肢は ①②③ の組合せ表。

ア ① コード生成 ② 構文解析 ③ 最適化
イ ① コード生成 ② 最適化 ③ 構文解析
ウ ① 構文解析 ② コード生成 ③ 最適化
エ ① 構文解析 ② 最適化 ③ コード生成

出典:平成27年度 春期 基本情報技術者試験 午前 問30

解き方と答えを見る
  1. 最初に来るのは、SQL文を読んで文法と表名・列名を確かめる処理なので、①は「構文解析」。これでア・イ(①がコード生成)が消える。
  2. 残るウ(②コード生成→③最適化)とエ(②最適化→③コード生成)を比べる。
  3. 最適化は「どのアクセス経路で実行するか」を決める段階で、コード生成はその決定を実行可能な手続きにする段階。決める前には作れないので、最適化が先。
  4. よって ①構文解析 → ②最適化 → ③コード生成 → 実行 の順になる。

答え:エ(①構文解析 ②最適化 ③コード生成)

例題 2

埋込みSQLのXの正体を見抜く

次の埋込み SQL を用いたプログラムの一部において,X は何を表す名前か。
EXEC SQL OPEN X; EXEC SQL FETCH X INTO :NAME, :DEPT, :SALARY; EXEC SQL UPDATE 従業員 SET 給与 = 給与 * 1.1 WHERE CURRENT OF X; EXEC SQL CLOSE X;

ア カーソル
イ スキーマ
ウ テーブル
エ ビュー

出典:平成30年度 春期 基本情報技術者試験 午前 問28

解き方と答えを見る
  1. `EXEC SQL OPEN X;`:XがOPENの対象になっている。OPENはSELECTを実行し、Xを結果の最初の行の手前に置く操作。
  2. `EXEC SQL FETCH X INTO :NAME, :DEPT, :SALARY;`:Xを次の行(ここでは1行目)に進め、その行の値をホスト変数 NAME・DEPT・SALARY に取り出す。取り出した行がカレント行になる。
  3. `UPDATE 従業員 SET 給与 = 給与 * 1.1 WHERE CURRENT OF X;`:Xがいま指しているカレント行、つまり直前にFETCHした行の給与を1.1倍に更新する。
  4. `EXEC SQL CLOSE X;`:Xを閉じる。
  5. OPEN・FETCH・CLOSE・WHERE CURRENT OF の対象になれるのはカーソルだけ。テーブル・ビュー・スキーマはFETCHできない。

答え:ア(カーソル)

要点(試験直前に読む)

  • ストアドプロシージャ=命令群をDBMSに格納して呼び出すだけ。利点は「クライアント・サーバ間の通信量(ネットワーク負荷)の削減」。
  • JavaからDBにアクセスする標準APIはJDBC。JVM・JavaBeans・アプレットは別物。
  • カーソル=検索結果を1行ずつプログラムに渡す仕組み。OPEN(先頭の手前に置く)→FETCH(次の行へ進めて取り出す)→WHERE CURRENT OF(その行を更新・削除)→CLOSE。
  • クエリ処理は 構文解析 → 最適化 → コード生成 → 実行。
  • 効率の良いアクセス経路を選ぶ機能はオプティマイザ。

ひっかけ

  • ストアドプロシージャの利点に「DBファイルへのアクセス量」「メモリ使用量」「格納領域」の削減が並ぶ。減るのはクライアントとサーバ間の通信量だけ。
  • 通信負荷を減らす仕組みを聞く問題に2相コミットメント・グループコミットメントが並ぶ。どちらもトランザクションの確定方法の話で、通信負荷とは無関係。
  • クエリ処理の順番で、最適化とコード生成を入れ替えた選択肢が出る。「作戦(実行計画)を決めてから、実行用の手続きを作る」で最適化が先。
  • 埋込みSQLのXの正体に、テーブル・ビュー・スキーマが並ぶ。OPEN・FETCH・CLOSEできるのはカーソルだけ。
  • 「1行ずつ引き渡す」の字句にORDER BY・UNION・UNIQUEが並ぶ。並べ替え・和・重複禁止は別の目的なので、答えはCURSOR。

用語(17)

ストアドプロシージャ すとあどぷろしーじゃ(stored procedure)
よく使う一連のSQL処理をDBMSに登録しておき、クライアントからは呼び出すだけで実行できるようにしたもの。
⚠ 2相コミットメントやグループコミットメントと並べて出る。「あらかじめDBMSに格納」「通信量・ネットワーク負荷の削減」ならストアドプロシージャ。
2相コミットメント にそうこみっとめんと(two-phase commitment)
複数のDBにまたがるトランザクションを、準備確認と確定の2段階で行い、全部確定か全部取消しにそろえる方式。
⚠ 目的は分散DBの整合性で、通信負荷の軽減ではない。
グループコミットメント ぐるーぷこみっとめんと(group commitment)
複数のトランザクションのコミット時のログ書込みをまとめて1回で行い、ディスク書込みの回数を減らす方式。
⚠ 減らすのはディスクへの書込み回数で、クライアントとサーバ間の通信量ではない。
JDBC Java Database Connectivity
Javaのプログラムからデータベースにアクセスするための標準API。
⚠ JVM(実行環境)、JavaBeans(部品化の仕様)、Javaアプレット(ブラウザで動くプログラム)、SQL(DB言語)と混ぜて出る。「Java+DBアクセス」ならJDBC。
JVM Java Virtual Machine
Javaのプログラムを実行する仮想マシン。
⚠ JDBCと取り違えやすい。JVMは「動かす土台」、JDBCは「DBにつなぐ窓口」。
JavaBeans じゃばびーんず
Javaのプログラムを再利用しやすい部品として作るための仕様。
⚠ DBアクセスのAPIではない。DBならJDBC。
埋込みSQL うめこみえすきゅーえる(embedded SQL)
COBOLやCなどのプログラムの中に、EXEC SQL で始まるSQL文を直接書き込む方式。
カーソル かーそる(cursor)
検索結果の複数行の表の上で、いまどの行を指しているかを示し、1行ずつプログラムに渡すための仕組み。
⚠ テーブル・ビュー・スキーマと並べて出る。OPEN/FETCH/CLOSE/WHERE CURRENT OF の対象になるのはカーソルだけ。
ホスト変数 ほすとへんすう
埋込みSQLで、SQLとプログラムの間で値を受け渡すためのプログラム側の変数で、SQL文中では先頭にコロン(:)を付けて書く。
OPEN おーぷん
カーソルに対応するSELECTを実行し、カーソルを結果の最初の行の手前に置く操作。
⚠ OPEN直後はまだどの行も指していない。行を指すのはFETCHの後。
FETCH ふぇっち
カーソルを次の行に進め、その行の値をホスト変数に取り出す操作で、取り出した行がカレント行になる。
⚠ 「取り出してから次へ進む」ではない。進めてから取り出すので、FETCH後のカーソルは取り出した行を指している。
WHERE CURRENT OF ほえあ かれんと おぶ
UPDATEやDELETEで、カーソルが指しているカレント行(直前にFETCHした行)だけを対象にする指定。
CLOSE くろーず
使い終わったカーソルを閉じ、検索結果を解放する操作。
構文解析 こうぶんかいせき
SQL文の文法や表名・列名の正しさを調べ、DBMSが扱える内部の形に分解する処理。
⚠ クエリ処理の最初の段階。最適化やコード生成より前。
オプティマイザ おぷてぃまいざ(optimizer)
SQL文を実行するとき、索引の使い方や結合の順番などを比べ、効率の良いアクセス経路を選ぶRDBMSの機能。
⚠ ガーベジコレクション(メモリ回収)、クラスタリング(データの物理配置)、マージソート(整列法)と並べて出る。「アクセス経路の選択」ならオプティマイザ。
コード生成 こーどせいせい
最適化で決めた実行計画を、実際に実行できる手続きに変換する処理。
⚠ 最適化と順番を入れ替えるひっかけが多い。実行計画が決まってから作るので、最適化の後。
ガーベジコレクション がーべじこれくしょん(garbage collection)
プログラムが使わなくなったメモリ領域を自動で回収する機能。
⚠ DBのアクセス経路選択とは無関係。

このレッスンの過去問

このレッスンで稽古する