データベーススペシャリスト 2024年 午前2 問01
問題文
SQLのシーケンスに関する説明のうち、適切なものはどれか。
選択肢
ア:現在基底値が0→1→2→0→1→2→0→...のように、周期的に繰り返すシーケンスを定義することはできない。
イ:シーケンスの現在基底値を、最小値と最大値との間の任意の整数値に変更することはできない。
ウ:シーケンスの増分を、負の整数値にすることはできない。
エ:トランザクション開始後のシーケンスの値の取得による現在基底値の変更は、トランザクションのロールバックでその変更を取り消すことができない。(正解)
🔒 解説は解答すると表示されます
シーケンス値の永続性【午前2解説】
正解の理由
シーケンスから値を取得する操作(たとえば NEXTVAL 相当)は、その時点でシーケンスの現在値を進める副作用を持ち、通常トランザクションのロールバックでは元に戻りません。したがって、シーケンスの値取得による現在基底値の変更はトランザクションの取り消しで元に戻らない、という記述が正しく、よって エ が正解です。
補足すると、シーケンスは多くのDBMSでトランザクション非依存(非トランザクション性)に設計されており、値の割り当てによる「ギャップ」は通常発生し得ます。DBMSごとにキャッシュや衝突時の動作は異なりますが、ロールバックで NEXTVAL の効果が取り消されることは基本的に期待できません。
解法ステップ
- 各選択肢が「必ず成り立つ一般的な性質」を主張しているかを確認する(「できない」「できない」「できない」「戻らない」などの否定型に注意)。
- シーケンスの一般的な性質(CYCLE の有無、INCREMENT の符号、ALTER/RESTART の可否、トランザクションとの関係)を思い出すか文献で確認する。
- DBMSによる差異があるポイント(CYCLE可否、現在値の再設定方法など)は「DBMS依存」であることを意識して排除基準に使う。
- トランザクションとの関係は多くのDBMSで共通の理解(値取得は即時反映かつ不可逆)なので、これが最も確実に正しい記述であると判断する。
選択肢別の誤答解説
ア: 「周期的に繰り返すシーケンスを定義することはできない」
- 誤り。多くのDBMSは CYCLE 指定で循環するシーケンスを作成できます(例:Oracle, PostgreSQL など)。したがって「できない」と断定するのは間違いです。なお、CYCLE の有無や既定値はDBMS依存です。
イ: 「シーケンスの現在基底値を、最小値と最大値との間の任意の整数値に変更することはできない」
- 誤り。多くのDBMSではシーケンスの再始動(Restart/RESTART WITH)や ALTER 操作で次に返される値を設定できます(例:PostgreSQL の ALTER SEQUENCE ... RESTART WITH n)。ただし、DBMS によって直接の操作方法や制約は異なる(Oracle では直接 RESTART WITH がないバージョンもあり、一時的に INCREMENT を変更して調整する等の手順が必要)ため「できない」との断定は誤りです。
ウ: 「シーケンスの増分を、負の整数値にすることはできない」
- 誤り。ほとんどの主要DBMSは負の増分(減少するシーケンス)を許容します。たとえば CREATE SEQUENCE ... INCREMENT BY -1 のようにして降順に値を生成できます。範囲(MINVALUE/MAXVALUE)を適切に設定する必要があります。
エ: 「トランザクション開始後のシーケンスの値の取得による現在基底値の変更は、トランザクションのロールバックでその変更を取り消すことができない」
- 正しい。シーケンスの NEXTVAL 相当の操作はシーケンス自身が持つ状態を即時に移行させ、トランザクションの成功・失敗に依存せず永続的に進みます。したがってロールバックしてもシーケンスのカウンタは戻りません。
よくある誤解
- シーケンスのギャップは異常ではない:トランザクションのロールバックやサーバ再起動(キャッシュの喪失)で値が飛ぶことがあり、これは正常動作の一部と理解すべきです。
- 「CYCLE がない=値のラップは不可能」ではない:CYCLE を明示していない場合はラップしませんが、多くのDBMSは CYCLE 指定で循環が可能です(DBMS依存)。
- DBMSによる操作性の差:あるDBMSでは RESTART が簡単にできるが、別のDBMSでは回避手順が必要という点を混同しやすいです。
補足コラム
- 典型的な SQL 例(DBMS により書式が異なる点に注意):
-- PostgreSQL: 循環シーケンス
CREATE SEQUENCE seq_cycle START 0 INCREMENT 1 MINVALUE 0 MAXVALUE 2 CYCLE;
-- PostgreSQL: 再始動(次に返す値を指定)
ALTER SEQUENCE seq_cycle RESTART WITH 100;
-- 取得
SELECT nextval('seq_cycle');
-- Oracle: NEXTVAL の例(Oracleでは .NEXTVAL を使用)
SELECT seq_cycle.NEXTVAL FROM DUAL;
-- 負の増分(降順)
CREATE SEQUENCE seq_desc START 10 INCREMENT -1 MINVALUE 1;
- 性能面:シーケンスはロックを最小化するために内部でキャッシュや専用アルゴリズムを使います。そのため高頻度の連続値取得に適しており、同時実行性能が高い一方で「連続性」が保証されない(ギャップが発生する)点に注意してください。
- シーケンス値を「トランザクション中に確保して後で取り消したい」要件がある場合は、シーケンスではなくトランザクショナルな予約テーブルなど別設計を検討します。
FAQ
Q1: ロールバックでシーケンス値を戻す方法はありますか?
A1: 基本的にはありません。必要ならばシーケンスを手動で調整(ALTER/RESTART または一時的な INCREMENT 変更→NEXTVAL→戻す等)するか、設計段階で「予約」用テーブルを用意するなど別手段で管理します。
A1: 基本的にはありません。必要ならばシーケンスを手動で調整(ALTER/RESTART または一時的な INCREMENT 変更→NEXTVAL→戻す等)するか、設計段階で「予約」用テーブルを用意するなど別手段で管理します。
Q2: CYCLE を使うと何が起きますか?
A2: シーケンスが最大(または最小)に達したときに、定義された範囲の反対側に戻って繰り返し値を発行します(ただし使用中の値や重複に注意が必要)。
A2: シーケンスが最大(または最小)に達したときに、定義された範囲の反対側に戻って繰り返し値を発行します(ただし使用中の値や重複に注意が必要)。
Q3: CURRVAL はロールバックで影響を受けますか?
A3: CURRVAL はそのセッションで一度 NEXTVAL を呼んでいれば参照できますが、CURRVAL 自体は単に現在のシーケンス値を返すだけで、シーケンスの状態変更を行うものではありません。NEXTVAL の変更はロールバックで戻りません。
A3: CURRVAL はそのセッションで一度 NEXTVAL を呼んでいれば参照できますが、CURRVAL 自体は単に現在のシーケンス値を返すだけで、シーケンスの状態変更を行うものではありません。NEXTVAL の変更はロールバックで戻りません。
関連キーワード: シーケンス、NEXTVAL、CURRVAL、CYCLE、ALTER SEQUENCE、RESTART、キャッシュ、ロールバック、負の増分、ギャップ、NOCYCLE

\ せっかくなら /
データベーススペシャリストを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

