この項では、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] |
関連項目:
Oracle Database SQL言語リファレンス
選択記述子の場合、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);
説明:
位取りが負の場合は、その絶対値を長さに追加してください。たとえば、精度に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 |
すべての選択リスト列(式は不可)について、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つともアドレスであることに注意してください。