
はじめに
こんにちは、Cyber Security Innovation Group(以降CSIG)の姫路康太郎です。2025年2月から新卒としてプロジェクトに配属され、認可整理のチームでアジャイル開発を行っています。
本記事ではまず、OracleDBにおける主要な採番方法であるSEQUENCEとIDENTITY列について、基本的な使い方を説明します。続いて、複数のテーブルへ同時にデータを投入する際に利用できるOracleDB特有のマルチテーブル・インサート構文 (INSERT ALL
) における、それぞれの採番の実装方法と挙動の違いに焦点を当てて解説します。
OracleDBでの開発に携わる方や、効率的な採番方法に関心のある方にとって、本記事が少しでもお役に立てれば幸いです。
OracleDBにおける採番方法の紹介
初めに、軽くIDENTITY列とSEQUENCEについて紹介します。
SEQUENCE
SEQUENCEは一意の整数値を生成するために使用されるスキーマオブジェクトであり、特定のテーブルとは独立したデータベースオブジェクトです。それにより、複数のテーブルで共有したり、SEQUENCEオブジェクト単体を操作することができます。この点で後述するIDENTITY列とは異なり、IDENTITY列よりも柔軟性があると言えます。
IDENTITY列
IDENTITY列は、テーブルの特定の列に対して自動的に一意な数値を生成する機能です。内部的にSEQUENCEオブジェクトを利用して実現されており、IDENTITY列を定義すると対応するシーケンスを暗黙的に作成し、そのシーケンスから値を取得して列に自動的に設定します。そのため、SEQUENCEよりシンプルに使うことができます。
SEQUENCEの使い方
SEQUENCEオブジェクトは独立したオブジェクトとして作成します。
CREATE SEQUENCE TEST_SEQ; |
INSERTをする際に、作成しておいたSEQUENCEオブジェクトを明示的に呼び出すことで採番します。
INSERT INTO M_TEST(ID,VALUE) VALUES(TEST_SEQ.nextval,'data'); |
IDENTITY列の使い方
IDENTITY列は、特定のテーブルの特定のカラムに定義します。
CREATE TABLE M_TEST ( |
INSERTをする際に、採番列の値を明示的に示さなくても暗黙的に採番されます。
INSERT INTO M_TEST(VALUE) VALUES ('data'); |
2つのテーブルに共通の番号を採番をする
いくつか方法はあると思いますが、本記事では、採番にSEQUENCE / IDENTITY列を利用し、2つのテーブル同時のINSERT
に、マルチテーブル・インサート構文INSERT ALL
を利用して投入することを考えます。投入するデータはM_TEST
の様にID
とVALUE
のカラムを持った複数レコードからなるテーブルを想定しています。
>> SELECT * FROM M_TEST |
マルチテーブル・インサート
OracleDB特有の構文で、複数のテーブルに同時にデータを投入することができます。INSERT ALL
を使う基本的な構文は以下のとおりです。
INSERT ALL |
※詳細は以下の記事を参考ください。
SEQUENCEを使ったマルチテーブル・インサート
SEQUENCEオブジェクトを利用した場合、同じSEQUENCEオブジェクトから番号を呼び出すことで、共通の番号を採番できます。そのため、2つのテーブル間でIDは正しく保たれることとなります。
INSERT ALL |
SEQUENCEを使ったマルチテーブル・インサートの落とし穴
INSERT ALL
でSEQUENCEを使って複数のテーブルに採番を行う際には、採番するテーブルに対して すべてに nextval
(SEQUENCEを増加させて次の値を返す)を使用します。公式によるとこれが正規の方法のようです。このnextval
を使用するという点が、私の直感と異なっていたので、共有しようと思いました。
直感的には、上記コードでM_TEST_SEQ2
に採番する際、currval
(SEQUENCEの現在の値を返す)を使うのではないかと感じました。直前の行でnextval
を実行しているため、次のVALUE句ではnextval
されたSEQUENCEを取得するものと考えたからです。
実際にcurrval
で実行したみたところ、1つの環境では成功したものの、別の環境では失敗したので、安全のためにも公式の説明から読み取れるnextval
を推奨します。
IDENTITYを使ったマルチテーブル・インサート
IDENTITY列を利用した場合、データ投入先の2つのテーブルに、それぞれにIDENTITY列を定義することになります。つまり、2つのテーブルがそれぞれ固有のSEQUENCEオブジェクトを持つことになります。そのため、2つのテーブル間でID
の対応を正しく保つためには採番をずらさないための設計や、採番のずれを許容することが必要となります。ID
がずれる可能性を考慮すると、IDENTITY列の利用はあまりいい手段ではなさそうです。
INSERT ALL |
※IDENTITY列の採番方法には、GENERATED ALWAYS AS IDENTITY
、GENERATED BY DEFAULT AS IDENTITY
の2種類があります。詳しく説明している記事の紹介にとどめて、詳細な説明は割愛させていただきますが、本記事ではGENERATED BY DEFAULT AS IDENTITY
を利用しました。
また参考までに、PostgreSQLのIDENTITY列と、基本的な使い方や振る舞いは同様のようです。
おわりに
マルチテーブル・インサートにおける採番方法について触れ、マルチテーブル・インサート構文でIDENTITY列とSEQUENCEはどちらとも利用できることが分かりました。そのうえで、採番にずれが生じないSEQUENCEを利用することが良いと考えましたが、皆さんはどのように考えられますか?
何か疑問点や問題点がある場合には、遠慮なくご指摘いただけますと幸いです。