プライマリ・コンテンツに移動
Pro*C/C++プログラマーズ・ガイド
12c リリース1(12.1)
B71397-03
目次へ移動
目次
索引へ移動
索引

前
次

予備知識

動的SQL方法4を実装するには次の処理についての知識が必要です。

データの変換

この項では、T(データ型)の記述子配列について詳しく説明します。データ型の同値化と動的SQL方法4のどちらも使用しないホスト・プログラムでは、Oracleの内部データ型と外部データ型との変換方法はプリコンパイル時に決定されます。デフォルトでは、プリコンパイラは宣言部内のそれぞれのホスト変数に特定の外部データ型を割り当てます。たとえば、プリコンパイラはint型のホスト変数にINTEGER外部データ型を割り当てます。

しかし方法4を使用すると、データの変換および形式を制御できます。データの変換方法を指定するには、T記述子配列にデータ型コードを設定します。

内部データ型

内部データ型は、Oracleがデータベース表に列値を格納するための形式と、疑似列値を表すための形式を指定します。

DESCRIBE SELECT LISTコマンドを発行すると、Oracleはそれぞれの選択リスト項目に対する内部データ型コードをT記述子配列に戻します。たとえば、i番目の選択リスト項目に対するデータ型コードはT[i]に戻されます。

表15-1に、Oracleの内部データ型とそのコードを示します。

表15-1 Oracle内部データ型

Oracle内部データ型 コード

VARCHAR2

1

NUMBER

2

LONG

8

BINARY_FLOAT

100

BINARY_DOUBLE

101

ROWID

11

DATE

12

RAW

23

LONG RAW

24

CHARACTER (またはCHAR)

96

ユニバーサルROWID

104

外部データ型

外部データ型は、入力ホスト変数と出力ホスト変数に値を格納するための形式を指定します。

DESCRIBE BIND VARIABLESコマンドはデータ型コードのT配列を0(ゼロ)に設定します。このため、OPENコマンドを発行する前に、それらのコードを再設定する必要があります。データ型コードは、様々なバインド変数にどの外部データ型が使用されるかをOracleに知らせます。i番目のバインド変数については、必要な外部データ型をT[i]に再設定してください。

表15-2に、Oracleの外部データ型とそのコード、および各外部データ型で通常使用するC言語のデータ型を示します。

表15-2 Oracle外部データ型とデータ型コード

外部データ型 コード C言語のデータ型

VARCHAR2

1

char[n]

NUMBER

2

char[n] ( n <= 22)

INTEGER

3

int

FLOAT

4

float

STRING

5

char[n+1]

VARNUM

6

char[n] (n <= 22)

DECIMAL

7

float

LONG

8

char[n]

SQLT_BFLOAT

21

float

SQLT_BDOUBLE

22

double

VARCHAR

9

char[n+2]

ROWID

11

char[n]

DATE

12

char[n]

VARRAW

15

char[n]

RAW

23

unsigned char[n]

LONG RAW

24

unsigned char[n]

UNSIGNED

68

unsigned int

DISPLAY

91

char[n]

LONG VARCHAR

94

char[n+4]

LONG VARRAW

95

unsigned char[n+4]

CHAR

96

char[n]

CHARF

96

char[n]

CHARZ

97

char[n+1]

関連項目:

データ型の強制変換

選択記述子の場合、DESCRIBE SELECT LISTはOracleの内部データ型をどれでも戻すことができます。文字データの場合など、ほとんどの場合内部データ型は適切な外部データ型と正確に対応しています。ただし、内部データ型には扱いにくい外部データ型にマップするものもあります。そのため、T記述子配列の一部の要素を再設定する必要がある場合があります。たとえば、NUMBER値をC言語のfloat値に対応するFLOAT値に再設定する場合があります。Oracleは、内部データ型と外部データ型の間の必要な変換をFETCH時に行います。このため、データ型の再設定は必ずDESCRIBE SELECT LISTの、FETCHのに行ってください。

バインド記述子の場合は、DESCRIBE BIND VARIABLESによってバインド変数のデータ型が戻されることはなく、バインド変数の数および名前のみ戻されます。したがって、データ型コードのT配列を明示的に設定することで、それぞれのバインド変数の外部データ型をOracleに通知する必要があります。Oracleは、内部データ型と外部データ型の間の必要な変換をOPEN時に行います。

T記述子配列でデータ型コードを再設定すると、データ型を強制変換することになります。たとえば、i番目の選択リスト値をSTRINGに強制変換するには、次の文を使用します。

/* Coerce select-list value to STRING. */ 
select_des->T[i] = 5; 

データ表示用にNUMBERの選択リスト値をSTRINGに強制変換するときは、値の精度と位取りのバイトを抽出し、それらを使用して最大表示長を算出する必要もあります。FETCHの前に、L (長さ)記述子配列の該当する要素を再設定し、使用するバッファの長さをOracleに通知する必要があります。

たとえば、DESCRIBE SELECT LISTによってi番目の選択リスト項目のデータ型がNUMBER型であるとわかっているとします。このときfloat型で宣言されているC変数に戻り値を格納する場合は、T[i]には4を、L[i]にはシステムが定めるfloatの長さを設定するのみで済みます。

警告:

DESCRIBE SELECT LISTによって戻される内部データ型が、目的に合わない場合もあります。DATE型およびNUMBER型がその例です。DATE型の選択リスト項目をDESCRIBEすると、Oracleではデータ型コード12がT記述子配列に戻されます。FETCHの前にコードを再設定しないかぎり、日付の値はその7バイト内部形式で戻されます。日付を文字形式(DD-MON-YY)で取得するには、12に設定されているデータ型コードを1(VARCHAR2)または5(STRING)に変更し、7に設定されているL値を9または10に増やします。

NUMBER型の選択リスト項目を同じ要領でDESCRIBEすると、Oracleではデータ型コード2がT配列に戻されます。FETCHの前にコードを再設定しないかぎり、数値はその内部形式で戻されるため、おそらく求めている値とは異なります。そのときは、2に設定されているコードを1(VARCHAR2)、3(INTEGER)、4(FLOAT)、5(STRING)またはその他の適切なデータ型に変更します。

精度および位取りの抽出

ライブラリ関数SQLNumberPrecV6()(従来のsqlprc())は、精度と位取りを抽出します。この関数は通常、DESCRIBE SELECT LISTの後に使用します。その最初の引数はL[i]です。次の構文で、SQLNumberPrecV6()をコールします。

注意:

プラットフォームの正しいプロトタイプは、プラットフォーム固有のSQLNumberPrecV6ヘッダー・ファイルを参照してください。

SQLNumberPrecV6(dvoid *runtime_context, int *length, int *precision,
                int *scale); 

説明:

構文 説明

runtime_context

ランタイム・コンテキストへのポインタ

length

OracleのNUMBER値を格納する長い整変数へのポインタ。長さはL[i]に格納されます。値の位取りおよび精度はそれぞれ、下位バイトおよびその上のバイトに格納されます。

precision

NUMBER値の精度を戻す整変数へのポインタ。精度とは有効桁数を指します。サイズが未指定のNUMBERが選択リスト項目によって参照される場合は、precisionの値は0 (ゼロ)に設定されます。この場合、サイズが未指定なので、最大精度の38とみなされます。

scale

NUMBER値の位取りを戻す整変数へのポインタ。位取りには四捨五入する位置を指定します。たとえば位取りが2のときは、1/100の倍数の近似値に値が四捨五入される(3.456は3.46になる)ことを意味します。また位取りが-3のときは、1000の倍数の近似値に値が四捨五入される(3456が3000になる)ことを意味します。

位取りが負の場合は、その絶対値を長さに追加してください。たとえば、精度に3、位取りに-2を指定すると、99900までの値が有効になります。

次の例に、SQLNumberPrecV6()を使用して、STRINGに強制変換するNUMBER値の最大値表示長を計算する方法を示します。

/* Declare variables for the function call. */ 
sqlda         *select_des;  /* pointer to select descriptor */ 
int            prec;        /* precision                    */ 
int            scal;        /* scale                        */ 
extern void SQLNumberPrecV6();  /* Declare library function. */ 
/* Extract precision and scale. */ 
SQLNumberPrecV6(SQL_SINGLE_RCTX, &(select_des->L[i]), &prec, &scal); 
/* Allow for maximum size of NUMBER. */ 
if (prec == 0) 
    prec = 38; 
/* Allow for possible decimal point and sign. */ 
select_des->L[i] = prec + 2; 
/* Allow for negative scale. */ 
if (scal < 0) 
    select_des->L[i] += -scal; 

この関数コールの最初の引数は長さの配列のi番目の要素を指します。また、パラメータは3つともすべてアドレスであることに注意してください。

SQLNumberPrecV6()関数では、一部のSQLデータ型の精度と位取りの値に0(ゼロ)が戻されます。SQLNumberPrecV7()関数も同様で、次に示すSQLデータ型の場合を除けば引数リストも戻り値も同じです。

表15-3 SQLデータ型の精度と位取り

SQLデータ型 2進数精度 位取り

FLOAT

126

-127

FLOAT(N)

N(範囲は1から126)

-127

REAL

63

-127

DOUBLE PRECISION

126

-127

NULLまたはNOT NULLデータ型の処理

すべての選択リスト列(式は不可)について、DESCRIBE SELECT LISTは選択記述子のデータ型配列TにNULL/NOT NULLインジケータを戻します。i番目の選択リスト列にNOT NULL制約が指定されていると、T[i]の上位ビットはオフにされます。それ以外の場合は上位ビットが設定されます。

OPEN文またはFETCH文でデータ型を使用する前に、すでにNULL/NOT NULLビットが設定されているときは、そのビットをオフにする必要があります。(このビットは絶対にオンにしないでください。)

列にNULLが有効かどうかを調べ、データ型のNULL/NOT NULLビットを消去するには、ライブラリ関数SQLColumnNullCheck()(従来のsqlnul())を使用します。次の構文で、SQLColumnNullCheck()をコールします。

SQLColumnNullCheck(dvoid *context, unsigned short *value_type, 
      unsigned short *type_code, int *null_status);

説明:

構文 説明

context

ランタイム・コンテキストへのポインタ

value_type

選択リスト列のデータ型コードを格納する符号なしshort int型変数へのポインタ。データ型はT[i]に格納されます。

type_code

選択リスト列のデータ型コードを戻す符号なしshort int型変数へのポインタ。上位ビットはオフにされています。

null_status

選択リスト列のNULL状態を戻すint型変数へのポインタ。1は列がNULLを許可し、0は許可しないことを意味します。

次の例に、SQLColumnNullCheck()の使用方法を示します。

/* Declare variables for the function call. */ 
sqlda  *select_des;      /* pointer to select descriptor */ 
unsigned short   dtype;  /* datatype without null bit    */ 
int   nullok;            /* 1 = null, 0 = not null       */ 
extern void SQLColumnNullCheck();    /* Declare library function.    */ 
/* Find out whether column is not null. */ 
SQLColumnNUllCheck(SQL_SINGLE_RCTX, (unsigned short *)&(select_des->T[i]), &dtype, &nullok); 
if (nullok) 
{ 
    /* Nulls are allowed. */ 
    ... 
    /* Clear the null/not null bit. */ 
SQLColumnNullCheck(SQL_SINGLE_RCTX, &(select_des->T[i]), &(select_des->T[i]), &nullok); 
} 

SQLColumnNullCheck()関数の2回目のコールで指定されている1番目と2番目の引数は、データ型配列のi番目の要素を指します。また、パラメータは3つともアドレスであることに注意してください。