データベース内での格納方法 (DATE、NUMBER、LOB)
Oracle でデータベースに格納可能な データ型 のいくつかは格納するフォーマットが公開されている。
または公開されていた。DATE 型の格納方式の資料はオラクルの公式サイトのリニューアル時に行方不明になってしまった。
公開終了してしまったかもしれない。また SQL の DUMP 関数を使用すると内部の状態が見えるので試してみては?
DATE: 日付型の格納形式
DATE
年月日時分秒(日付型: DATE + TIME) / タイムゾーン情報はなし
データ内部で年(上位2桁)、年(下位2桁)、月、日、時、分、秒をもつ(各 1 バイトで計 7 バイト)
整数部で日付、小数部で時分秒の計 7 バイトで保存しているとの勘違い(※)をたまに見受ける。
俗にいう UNIX タイムのような基準となる日付からの経過秒数(エポック秒)という格納形式ではないため データの格納方法レベルでは XXXX年問題とは無縁である。
(※) 1 日後を SYSDATE + 1、1 時間後を SYSDATE + 1/24 という日付と数値の計算ができ、
期間型のなかったときの Oracle の日付の足し算(引き算)で使用する場合の Tipsとして広く知れ渡ったためだと思われる。
内部処理形式と保存形式でフォーマット異なる。
格納形式(〜10g)
例えば2004年10月12日 14時05分00秒 は 以下のように格納されている。(10進)
2000年問題時に資料は外部公開されていた(1999/9日本向け:URLは消滅)
2004年 10月 12日 14時 05分 00秒 = 120,104,10,12,15,6,1
1 2 3 4 5 6 7
+-----+-----+----+----+----+----+----+
| 120 | 104 | 10 | 12 | 15 | 6 | 1 |
+-----+-----+----+----+----+----+----+
計算式:
100+20 / 100+04 / 10 / 12 / 1+14 / 1+5 / 1+0
(NULL(0) を排除してかつ算術もできるように「げた」をはかせている)
(注意) SYSDATE や TO_DATE の結果は厳密には DATE 型とは異なるデータタイプである。(さらにサイズは 8バイトであり内部の形式も違う)
データタイプのタイプコード参照
NUMBER: 数値の格納形式
NUMBER / NUMBER( p [,s] )
固定小数点 精度p(1〜38桁)、位取りs(-84〜127桁:省略時 0)
格納形式(10g):
- 最大で 21 バイト
- 科学表記にて格納(先行および後続 0 は削除)
- 指数を格納するために1 バイト、仮数を格納するために最大で 20 バイト。
- 負の符号を格納するためには、1 バイトの仮数エリアを使用する。
- 仮数部の数値表現には 100 進数を使用 (=2桁を 1 バイト)している。
※ BCD 表現は1桁が4ビット構成で、2桁で1バイトになるものの内部表現が異なっている。
BCD(Binary-Coded-Decimal:二進化十進表現) ではなく BCC(Binary-Coded-Centezimal:二進化百進表現)というだろうか?
精度以内であれば、常に誤差の無い正確な数値を保持し計算することが可能。
(2進数精度のように表現できない数値が発生することがない。)
浮動小数点の格納形式 (BINARY_FLOAT、BINARY_DOUBLE)
2 進数精度による浮動小数点数値
BINARY_FLOAT
32 ビットの浮動小数点数 ( 4 + 1 バイト)
正の最小値 1.17549E-38、正の最大値 3.40282E+38
格納形式:IEEE形式浮動小数点データ+管理領域 1 バイト
0〜22 bit:仮数
23〜30 bit: 指数
31 bit:符号
±INF(+-無限大)、NaN(Not a Number:オラクルには±の区別はない)を持つ
BINARY_DOUBLE
倍精度 64 ビットの浮動小数点数 ( 8 + 1 バイト)
正の最小値 2.22507485850720E-308、正の最大値 1.79769313486231E+308
格納形式:IEEE形式浮動小数点データ(倍精度)+管理領域 1 バイト
0〜51 bit:仮数
51〜62 bit: 指数
63 bit:符号
±INF(+-無限大)、NaN(Not a Number:オラクルには±の区別はない)を持つ
ラージオブジェクト (CLOB、NCLOB)
最大格納可能サイズ 標準ブロックサイズ×(4G-1)…最大 8T(2KB) 〜 128T(32KB) バイト
「 9i では最大 4G バイト」になる。
日本語環境のデータベースキャラクタセットを使用している場合、
CLOB の格納方式は固定長の UCS-2 互換形式(※)で格納されている。
そして、DBMS_LOB パッケージにはキャラクタ数を数える GET_LENGTH だけである。
バイト数を数える GET_LENGTHB は(存在しても意味がないので)存在しない。
LENGTHB 標準関数も使用は許されていない。(Oracle 10g 時点)
(※) UCS-2 は 2 バイト固定の キャラクタセット
これは CLOB を 複数のVARCHAR2(xx BYTE) に切り分けて代入するのに時間のかかる余計な手間が必要であることを意味する。
非常に地味な制限だが、これはボディーブローのような制限である。
これを知らずに使うと後々、開発フェーズに入ってから悶絶する可能性があるからである。
CLOB を使うならば設計時から注意が必要。
(おそらく CLOB を使用時の最大のデメリットだと思われる)
関連事項