ヘッダーをスキップ

Oracle Rdb SQLリファレンス・マニュアル リリース7.2 E06178-01 |
| 目次 | 索引

戻る | 次へ |

## 2.3.3 DECIMALデータ型およびNUMERICデータ型

SQLでは、パック10進数データ型（DECIMAL）および符号付き数値データ型（NUMERIC）が限定的にサポートされています。

- 列定義における、整数または浮動小数点への変換
  SQLで使用されるデータベースでこれらのデータ型がサポートされていない場合があるため、列にDECIMALデータ型またはNUMERICデータ型を指定すると、警告メッセージが表示され、指定された精度引数に応じたデータ型で列が作成されます。次に例を示します。

      SQL> CREATE TABLE T (C DECIMAL(3));
      %SQL-I-NO_DECIMAL, C is being converted from DECIMAL to SMALLINT.

  SQLで変換されるデータ型のリストを次に示します。

  - DECIMAL(1)〜DECIMAL(4)は、SMALLINTに変換されます。
    NUMERIC(1)〜NUMERIC(4)は、SMALLINTに変換されます。

  - DECIMAL(5)（DECIMALのデフォルト）〜DECIMAL(9)は、INTEGERに変換されます。
    NUMERIC(5)（NUMERICのデフォルト）〜NUMERIC(9)は、INTEGERに変換されます。

  - DECIMAL(10)〜DECIMAL(18)は、BIGINTに変換されます。
    NUMERIC(10)〜NUMERIC(18)は、BIGINTに変換されます。

  - DECIMAL(19)およびそれ以上は、FLOATに変換されます。
    NUMERIC(19)およびそれ以上は、FLOATに変換されます。

- 仮パラメータまたはホスト言語パラメータにおける、パック10進数データ型または符号付き数値データ型への変換
  SQLモジュール内の仮パラメータにはDECIMALまたはNUMERICを指定できます。また、ホスト言語パラメータをパック10進数または符号付き数値の記憶域形式で宣言できます。SQLでは、データベース上の値のデータ型と、それに対応するパラメータおよびホスト言語パラメータで指定されているDECIMAL表現またはNUMERIC表現の間の変換が行われます。
  Oracle Rdb V6.0より前のSQLでは、指定された精度を超える値を列に挿入できました。この動作は、Oracle Rdb V6.0より前に作成されたデータベースでは現在も保持されています。
  ANSI/ISO SQL規格への準拠のため、Oracle Rdb V6.0以降では、指定された精度を超える処理を実行しようとすると、エラー・メッセージが生成されます。次に例を示します。

      SQL> INSERT INTO T (C) VALUE (9999);
      %RDB-E-VALOUTRANGE, value outside the specified precision (3) for
      column "C"

## 2.3.4 NUMBERデータ型

Oracle Rdbでは、Oracleサーバーとの互換性を維持するためにNUMBERデータ型がサポートされていますが、これらのデータ型には相違点があります。Oracleサーバーでは、最大38桁までの精度がサポートされ、スケールは-84〜127に制限されています。一方、Oracle Rdbリリース7.1でサポートされている精度は18桁、スケールは-128〜127です。

NUMBERデータ型には、次の特徴があります。

- NUMBER
  精度が指定されていない場合、DOUBLE PRECISIONにマップされます。

- NUMBER (p)またはNUMBER (p, d)（p: 精度、d: 小数精度）
  精度（p）が指定されている場合、その精度が整数データ型のマッピングに使用されます。また、指定された値が18を超える場合は、DOUBLE PRECISIONが使用されます。

  > p <= 2の場合、TINYINTにマップされます。
  > 2 < p <= 4の場合、SMALLINTにマップされます。
  > 4 < p <= 9の場合、INTEGERにマップされます。
  > 9 < p <= 18の場合、BIGINTにマップされます。
  > p > 18の場合、DOUBLE PRECISIONにマップされます。

- NUMBER (*)またはNUMBER (*, d)
  アスタリスク（*）は、スケールが最大のバイナリ値を表す短縮形です。Oracle Rdbリリース7.1では、これは18桁の指定と同等であり、BIGINTにマップされます。

- NUMBER(p, -d)
  NUMBERでは、負数の小数精度dを指定できます。スケールが負の場合、小数点の左側が指定された桁数まで丸められます。たとえば、(10,-2)と指定すると、100の位に丸められます。

## 2.3.5 固定小数点数データ型

SQLでは、TINYINT、SMALLINT、INTEGERおよびBIGINTの4種類の固定小数点数データ型が提供されています。この4種類すべてに対して、符号なし整数（n）を任意に指定できます。この整数は、小数部の桁数を示すスケール変更係数です。

スケール変更係数は、0〜127の範囲の整数である必要があります。nを指定しない場合は、0（小数部分なし）がデフォルトとして使用されます。

- TINYINT
  列が符号付きバイトであることを指定します。（1バイトは連続する8ビットです。）TINYINTデータ型には、--128〜127の範囲の値を格納できます。

- SMALLINT
  列が16ビットの符号付きワードであることを指定します。SMALLINTデータ型には、--32,768〜32,767の範囲の値を格納できます。

- INTEGER
  列が32ビットの符号付きロングワードであることを指定します。INTEGERデータ型には、--2**31〜(2**31) --1の範囲の値を格納できます。

- BIGINT
  列が64ビットの符号付きクワッドワードであることを指定します。BIGINTデータ型には、--2**63〜(2**63) --1の範囲の値を格納できます。

## 2.3.6 浮動小数点数データ型

SQLでは、次の3種類の浮動小数点数データ型が提供されています。

- FLOAT
  正の数（n）で指定された精度に応じて、列が32ビットの浮動小数点数（REAL）または64ビットの浮動小数点数（DOUBLE PRECISION）であることを指定します。nが25未満の場合、FLOATは32ビットの浮動小数点数になります。nが25以上の場合、FLOATは64ビットの浮動小数点数になります。
  nの最大値は53です。FLOATにnを指定しない場合、FLOATは64ビットの浮動小数点数になります。

- REAL
  列が、24ビットまでの精度を持つ32ビットの浮動小数点数であることを指定します。

- DOUBLE PRECISION
  列が、53ビットまでの精度を持つ64ビットの浮動小数点数であることを指定します。

## 2.3.7 LIST OF BYTE VARYINGデータ型

LIST OF BYTE VARYINGデータ型は、セグメント化された内部構造を使用したラージ・データ・オブジェクトの処理用に設計されています。LIST OF BYTE VARYINGデータ型は、次のデータ型と同等です。

- セグメント化された文字列

- バイナリ・ラージ・オブジェクト（BLOB）（特定の産業で実装）

- LIST OF VARBYTE（SQL構文における代替名）

通常、LIST OF BYTE VARYINGデータ型のオブジェクトは、リストとして参照されます。リストとは、データ・セグメントの連結リストのことであり、各セグメントは異なるページに格納されています。

リストの例は、サンプルの人事データベースのRESUMES表で確認できます。RESUMES表には、RESUMEというLIST列およびEMPLOYEE_IDというCHARACTER列の2つの列が含まれています。図2-2は、RESUMES表の概念図を示しています。

図2-2 LIST列を持つ表

リストには、大量のテキスト、データ収集デバイスからバイナリ入力された長い文字列、図形データなど、構造化されていないデータを格納できます。どのようなデータ型でも、リストに格納し、またリストから取得できます。データは、構造化されていないバイトで格納されます。たとえば、リストに文字データを格納し、これを16進数データとして解釈できます。Oracle Rdbでは、セグメントの長さを除き、リストに含まれているデータの型は認識されません。

リスト内のセグメント数に制限はありません。

ページに格納されている各セグメントは、ワード・オフセットおよびワードの長さを使用する、行索引構造によって参照されます。このページ構造により、セグメントのサイズが符号なしの65,535バイトに制限されます。

符号なし整数（n）を使用して、LIST OF BYTE VARYINGデータ型の列のオクテット数（バイト数）を指定します。nを省略すると、SQLでは1オクテットの列が作成されます。連鎖リスト形式におけるnの最大サイズは、最初のセグメントでは65,508、それ以降のセグメントではそれぞれ65,522です。索引リスト形式におけるnの最大サイズは、オーバーヘッドのための5バイトを残した65,530です。リストの連鎖形式および索引形式の詳細は、第2.3.7.1項を参照してください。

リスト・セグメントのユーザー・データ部分は、BYTE VARYINGデータ型のフィールドです。BYTE VARYINGデータ型は、符号なし8ビット・バイトの文字列です。BYTE VARYINGデータ型は、今後の使用のために予約されていますが、現時点では、リスト・セグメント内でのみ有効です。

リストは表の行内に格納されるため、リストを作成するにはCREATE TABLE文を使用する必要があります。実際には、セグメント化された文字列識別子がLIST OF BYTE VARYINGデータ型の列に格納されます。セグメント化された文字列識別子とは、プライマリ・リスト・セグメントの位置を指定する数値のことです。索引リスト形式では、セグメント化された文字列識別子は最初のポインタ・セグメントを指し示します。連鎖リスト形式では、セグメント化された文字列識別子は最初のリスト・セグメントを指し示します。リスト自体ではなくリスト表を指し示すポインタを格納するため、リストはOracle Rdbの表サイズの制限による制約を受けません。リストを含む表を作成する例は、「CREATE TABLE文」を参照してください。

リストの使用方法の詳細は、「DECLARE CURSOR文」を参照してください。他の表情報に基づいた、異なる記憶域へのリストの格納の詳細は、「CREATE STORAGE MAP文」を参照してください。

LIST OF BYTE VARYINGデータ型では、サブタイプとしてBINARYおよびTEXTがサポートされています。これらのサブタイプを使用して、LIST OF BYTE VARYINGデータ型内に含まれるデータを指定します。サブタイプTEXTは、データ型に印刷可能文字が保持されることを示します。サブタイプBINARYは、データ型に16進数表記で表される、RAWバイナリ・データが保持されることを示します。

### 2.3.7.1 リストのディスク上の形式

Oracle Rdbでは、リストに対して次の3種類のディスク上の形式を使用できます。

- 連鎖形式

- 索引形式

- 単一セグメント形式

最初の連鎖形式では、リストはセグメントの連鎖リストになっています。最初のセグメントには2番目のセグメントを指すポインタ、2番目のセグメントには3番目のセグメントを指すポインタ、というように順にポインタが格納されます。最後のセグメントにはNULLポインタが格納されます。

各セグメントには、ユーザー・データ用の65,522バイト以外に、次のセグメントを指す8バイトのデータベース・キー（dbkey）が格納されます。

最初のセグメントには、セグメント化された文字列を記述する、次のような14バイトのオーバーヘッドが含まれます。

- 文字列全体の長さを格納するクワッドワード

- セグメントの合計数を格納するロングワード

- 最も長いセグメントの長さを格納するワード

このオーバーヘッドのため、最初のセグメントに保持できるユーザー・データは65,508バイトまでになります。

最初のセグメントに保持されるこれらの情報は、リスト・カーソルをオープンするときにSQLを使用すると、SQLCA構造体で返されます。図2-3は、連鎖リスト形式を示しています。

図2-3 連鎖リスト形式

この連鎖リスト形式の最初のセグメントには、すべてのセグメントがディスクに書き込まれるまで有効にならない情報が保持されます。この形式は、その性質上更新が必要となります。この問題を解決するため、索引リスト形式が開発されました。

索引リスト形式では、次のセグメントを指し示すポインタはデータ・セグメントに含まれません。かわりに、ポインタはポインタ・セグメントと呼ばれる専用のセグメントに保持されます。ポインタ・セグメントには、データ・セグメントを指し示すポインタのみが格納されます。図2-4は、索引リスト形式の構造を示しています。

図2-4 索引リスト形式

ポインタ・セグメントを使用すると、Oracle Rdbでデータ・セグメントへの書込みが可能になります。これは後で修正する必要はありません。ポインタ・セグメントのサイズは、記憶域のページ上の空き領域によって設定されます。ページにデータ・セグメントを格納する空き領域がなくなると、ポインタは新しいポインタ・セグメントに連鎖されます。この形式では、バッファ・サイズと大規模なページ・サイズを組み合せ、実質的なページ修正の必要性を削減できます。

索引リスト形式は、Oracle Rdbによって作成されるすべてのリストのデフォルトです。

デフォルトとして連鎖リスト形式を保持するには、論理名RDMS$USE_OLD_SEGMENTED_STRINGを定義する必要があります。

    $ DEFINE RDMS$USE_OLD_SEGMENTED_STRING YES

この論理名が定義されると、アプリケーションでは、すべての読取り/書込みメディアへの書込みは、連鎖リスト形式になります。

後で新しい索引リスト形式を使用する場合は、論理名RDMS$USE_OLD_SEGMENTED_STRINGの設定を解除する必要があります。

同一表内で連鎖リスト形式と索引リスト形式を混在させることができます。ただし、連鎖リスト形式を索引リスト形式に変換する必要がある場合があります。たとえば、スクロール可能リスト・カーソルでFETCH LAST文を実行する場合は、形式を変換することをお薦めします。連鎖リスト形式でFETCH LAST文を使用すると、Oracle Rdbでは、目的のセグメントに到達するまですべてのセグメントを読み取りますが、これは最適な方法ではありません。索引リスト形式でFETCH LAST文を使用すると、Oracle Rdbでは、ポインタ・セグメントおよび最後のデータ・セグメントのみを読み取ります。

連鎖リスト形式でFETCH LAST文が実行されないようにするには、論理名RDMS$SET_FLAGSを定義するか、またはSET FLAGSにNOSCROLL_EMULATIONを指定して使用します。この論理名を定義して、連鎖リスト形式でSCROLLリスト・カーソルをオープンしようとすると、OPEN CURSOR文が失敗します。

サンプル・ディレクトリにあるサンプル・プログラムsql_convert_lists.scで、連鎖リスト形式を索引リスト形式に変換するプロセスの実例を確認できます。

また、データ量がセグメント化された文字列のバッファに収まる場合、リストを単一セグメントに書式設定することもできます。単一セグメント・リストは、論理名RDMS$BIND_SEGMENTED_STRING_BUFFERで制御されます。

単一セグメント・リストは、プライマリ・セグメントおよびデータ・セグメントの区別に使用されるフィールドで構成されています。これにより、ポインタおよびその他のオーバーヘッドが省略されるため、ディスク・ストレージを節約できます。セグメントの読取りでは、I/Oは1回のみです。単一セグメント・リストを利用する場合は、論理名RDMS$USE_OLD_SEGMENTED_STRINGを定義しないでください。

## 2.3.8 データ型の変換

値をSQLからホスト言語パラメータに、またはホスト言語パラメータからSQLに代入する場合、2レベルのデータ型変換を実行できます。

- データベースまたはホスト言語でサポートされていないデータ型から、サポートされているデータ型への変換
  SQLでは、SQLで使用されるデータベースでサポートされていないデータ型を使用した、プログラムによるホスト言語パラメータの宣言が可能です。（たとえば、SQLにはCOBOLのCOMP-2またはCOMP-3のデータに対応するデータ型はありません。）同様に、SQLでサポートされているデータ型でも、言語によっては対応するデータ型がないものがあります。（たとえば、PL/IではBIGINTデータはサポートされていません。）いずれの場合でも、データはサポートされていないソース・データ型からサポートされているターゲット・データ型に変換されます。
  このレベルの具体的な変換は、ホスト言語によって異なります。このレベルの変換の詳細は、第2.3.8.1項を参照してください。

- 1つのデータ型から別のデータ型への変換
  SQLでは通常、サポートされている2つの異なるデータ型間（CHARやDATEなど）で値を代入できます。このレベルの変換は、ホスト言語に依存しません。

サポートされているデータ型間のデータ変換規則の詳細は、第2.3.8.2項を参照してください。

注意 Oracle Rdbでは、整数値およびテキスト値の比較の際に頻出する問題を回避するため、アプリケーション・プログラムでCASTファンクションを使用して、データを明示的に、一環した比較可能な形式に変換することをお薦めします。

### 2.3.8.1 サポートされていないデータ型からの変換

SQLプリコンパイラまたはモジュール言語プロセッサでサポートされているデータベース、および様々なホスト言語では、必ずしも同じデータ型セットはサポートされていません。SQLでは、データベース間、および異なる言語間におけるこの非互換性に対して、次の方法のいずれかで対処します。

- データベース値はホスト言語データ型に変換され、ホスト言語値はサポート対象のデータ型に変換されます。この変換は、有効なホスト言語宣言のサブセットについてのみ行われます。

- プログラムのプリコンパイル時にエラーが生成されます。

プリコンパイラのサポート対象の言語について、SQLで相互に変換されるホスト言語宣言の詳細は、第4.4節を参照してください。SQLモジュールで宣言されたパラメータと互換性のあるホスト言語宣言を示す表は、第3.5節を参照してください。このようなホスト言語パラメータ宣言は、SQLモジュール・ファイル内の対応する仮パラメータ宣言に正確に対応している必要があります。対応していない場合は、実行時に予期しない結果が生じる可能性があります。動的SQLにおけるプログラムおよびデータベースのデータ型の変換の詳細は、付録Dを参照してください。

注意 SQLプリコンパイラを使用するホスト言語では、DATEデータ型はサポートされません。SQLでは、DATE、TIME、TIMESTAMPまたはINTERVALの値は、表4-3〜表4-10に示すホスト言語データ型の値には変換されません。かわりに、DATE、TIME、TIMESTAMPまたはINTERVALの列に格納されている64ビットの値が、これらの表に示す宣言済のパラメータに代入されます。 値がパラメータに格納されると、プログラムではLIB$FORMAT_DATE_TIMEランタイム・ライブラリ・ルーチンにより、この64ビット値がDATE、TIME、TIMESTAMPおよびINTERVALの各データ型に対するASCII文字列に変換されます。

### 2.3.8.2 サポートされているデータ型間の変換

通常、SQLでは、サポートされているデータ型間で値を代入できます。このような代入では、基底データベース・システムにより、ソース列またはソース・パラメータのデータ型から、ターゲット列またはターゲット・パラメータのデータ型に変換されます。

文字データ型間の変換は、次のルールに従います。

- 自動変換が無効の場合、ソース文字列およびターゲット文字列のキャラクタ・セットは同じである必要があります。

- ソース文字列がターゲット文字列より長い場合、MIA、SQL89およびSQLV40の各言語では、結果は左詰めされて右側が切捨てられ、エラーはレポートされません。
  SQL99などの最新の言語を使用している場合、データ格納時にエラーが返されます。ただし、切り捨てられる文字が空白文字のみである場合、エラーは返されません。データの取得中に切捨てが発生すると、警告が返されます。この場合、切り捨てられた文字列が空白かどうかにかかわらず、警告が返されます。
  切捨てによって、混合数の複数のオクテット・キャラクタ・セットの複数のオクテット文字が分割される場合、不完全な文字のバイトは、ターゲット文字列上でASCIIの空白文字に置き換えられます。
  切捨てによって、固定数の複数のオクテット・キャラクタ・セットの複数のオクテット文字が分割される場合、不完全な文字のバイトは、ターゲット文字列上で、複数のオクテット・キャラクタ・セットの適切な空白文字の下位オクテットに置き換えられます。

- ソース文字列がターゲット文字列より短い場合、変換結果は左詰めされ、余った右側部分には適切な空白文字で充填されます。このルールには例外があります。C言語で表の列がCHARまたはCHAR(1)として定義されている場合、ターゲット文字列には空白文字が充填されずにヌル文字で終了し、長さ1の文字列が生成されます。

- 空白文字で後詰めされているテキスト・データ項目を可変文字列データ項目に割り当てる場合、後詰めの空白はフィールド長の一部とみなされます。

固定小数点数データ型間の変換は、次のルールに従います。

- ソースの精度がターゲットより大きい場合、変換結果は丸め処理されます。

- ソースで使用されている整数部がターゲットより大きい場合、演算エラーが返されます。

- 小数部の丸め処理により、整数部がターゲットでオーバーフローする場合、演算エラーが返されます。

- ターゲットの整数部または小数部がソースより大きい場合、必要に応じて、変換結果の値の右側または左側にゼロが追加されます。

浮動小数点数データ型間の変換は、次のルールに従います。

- ソースの精度がターゲットより大きい場合、ソースの下位部分は丸め処理されます。

- ソースの値の大きさがターゲットで表現できない場合、演算エラーが返されます。

LIST OF BYTE VARYINGデータ型の変換はサポートされていません。ただし、使用している言語でCHARまたはVARCHARの各データ型がサポートされている場合は、LIST OF BYTE VARYINGデータ型の要素をCHARまたはVARCHARに変換できます。

データ型の異なるデータ間の変換は、次のルールに従います。

- 数値データ型に変換するテキストには、カンマなしの10進数形式または科学表記法のいずれかで数値を表したテキストが格納されている必要があります。
  テキストに変換する数値データでは、固定小数点データからは10進数形式、浮動小数点データからは科学表記法形式の数値が生成されます。

- 数値データ型からINTERVALデータ型への変換では、CAST演算子を使用する必要があります。出力されるデータ型は、時間隔修飾子に単一の日時フィールドのみを含むINTERVAL型に制限されます。

- DATEデータ型からCHARまたはVARCHARへの代入では、2つの異なる出力形式を使用できます。このドキュメントでは、これらの形式をVMS形式およびANSI形式と表記します。

  - テキストからDATE VMSへの代入では、テキスト式にdd-mmm-yyyy hh:mm:ss.ccという形式で日付を表すASCII数字が含まれている必要があります。これは、表2-12に示すように変換されます。

  - DATE VMSからテキストへの代入では、表2-12に示すテキスト形式に変換されます。テキスト・フィールドが16文字より短い場合、出力は右側から順に（100分の1秒の数字が最初で、年の最初の数字が最後）切り捨てられます。たとえば、テキスト・フィールドが12文字のみの場合、日付1990112523053488（リテラルでは'25-Nov-1990 23:05:34.88'と表現される）は、199011252305に切り捨てられます。
    テキスト・フィールドが16文字より長い場合、フィールドは左詰めされ、空白が充填されます。テキスト式は、表2-12に示す形式で表されます。
    DATE VMS形式の例を次に示します。

        SQL> --  Oracle Rdb  supports another internal format for
        SQL> -- DATE VMS.  This format is similar to the TIMESTAMP format
        SQL> -- except that the punctuation is omitted.  This example assigns
        SQL> -- the CHAR column (A) to the DATE VMS (G) column and then
        SQL> -- displays the result.  In an application, the CHAR column could
        SQL> -- be a CHAR host variable or module language parameter.
        SQL> --
        SQL> INSERT INTO DATE_TEST (G) VALUE ('1957020100000000');
        1 row inserted
        SQL> UPDATE DATE_TEST
        cont>   SET A=G
        cont>   WHERE G IS NOT NULL;
        1 row updated
        SQL> SELECT A, G
        cont>   FROM DATE_TEST
        cont>   WHERE G IS NOT NULL;
         A                         G
          1-FEB-1957 00:00:00.00   1957020100000000
        1 row selected
        SQL> ROLLBACK;

  - テキストからDATE VMSへの代入では、日付を表すASCII数字が、表2-12に示す形式でテキスト式に格納されている必要があります。
    入力テキスト式が16文字より長い場合、最初の16文字のみが使用されます。入力の残りの部分は無視されます。
    入力テキスト式が8〜15文字の場合、ASCIIのゼロを右側に充填して16文字となる場合と同様に処理されます。

    表2-12 DATE VMSデータ型と相互に変換されるテキスト文字列の形式
    文字列 | 意味
    --- | ---
    yyyy | 1857〜9999の間の4桁の年
    nn | 1月〜9月では先行ゼロを含む、01〜12の間の2桁の月
    dd | 右詰めで先行ゼロを含む、01〜31の間の2桁の日
    hh | 右詰めで先行ゼロを含む、00〜23の間の24時間表示の2桁の時間
    mm | 右詰めで先行ゼロを含む、00〜59の間の2桁の分
    ss | 右詰めで先行ゼロを含む、00〜59の間の2桁の秒
    cc | 右詰めで先行ゼロを含む、00〜99の間の2桁の秒の小数

    入力テキスト式が8文字より短い場合、代入によって変換エラーが返されます。

  - テキストからANSI形式のDATEへの代入では、日付を表すASCII数字が、次の形式でテキスト式に格納されている必要があります。

    - TIME: hh:mm:ss.cc

    - DATE: yyyy-nn-dd

    - TIMESTAMP: yyyy-nn-dd hh:mm:ss.cc

    - INTERVAL (YEAR-MONTH): y-m

    - INTERVAL (DAY-TIME): d:hh:mm:ss.cc

- プリコンパイラ、モジュール言語または動的SQLを使用する場合、CHAR型のホスト変数とともにCASTまたはEXTRACTを使用して、日時データをバイナリ・データから変換する必要があります。