PostgreSQL 9.0.4文書 | ||||
---|---|---|---|---|
前のページ | 巻戻し | 第 33章ECPG - C言語による埋め込みSQL | 早送り | 次のページ |
SQL記述子領域はSELECT、FETCH、DESCRIBE文の結果を処理する、より洗練された手法です。 SQL記述子領域は1行のデータをメタデータ項目と一緒に1つのデータ構造体としてグループ化します。 特に動的SQL文を実行する場合は結果列の性質が前もってわかりませんので、メタデータが有用です。 PostgreSQLは記述子領域を使用するための2つの方法、名前付きSQL記述子領域とC構造化SQLDA、を提供します。
名前付きSQL記述子領域は、記述子全体に関する情報を持つヘッダと、基本的に結果行内の1つの列を記述する、1つ以上の項目記述子領域から構成されます。
SQL記述子領域を使用可能にするためには、それを以下のように割り当てなければなりません。
EXEC SQL ALLOCATE DESCRIPTOR identifier;
この識別子は記述子領域の"変数名"として使用されます。 記述子が不要になったら、以下のように解放してください。
EXEC SQL DEALLOCATE DESCRIPTOR identifier;
記述子領域を使用するには、INTO句内の格納対象として、ホスト変数を列挙するのではなく、記述子領域を指定してください。
EXEC SQL FETCH NEXT FROM mycursor INTO SQL DESCRIPTOR mydesc;
結果セットが空の場合であっても、記述子領域には問い合わせのメタデータ、つまりフィールド名、が含まれます。
まだ実行されていないプリペアド問い合わせでは、結果セットのメタデータを入手するためにDESCRIBEを使用することができます。
EXEC SQL BEGIN DECLARE SECTION; char *sql_stmt = "SELECT * FROM table1"; EXEC SQL END DECLARE SECTION; EXEC SQL PREPARE stmt1 FROM :sql_stmt; EXEC SQL DESCRIBE stmt1 INTO SQL DESCRIPTOR mydesc;
PostgreSQL 9.0より前では、SQLキーワードは省略可能でした。 このためDESCRIPTORおよびSQL DESCRIPTORは名前付きSQL記述子領域を生成しました。 これは強制事項になり、SQLキーワードを省略すると、SQLDA記述子領域を生成します。 項33.9.2を参照してください。
DESCRIBEおよびFETCH文では、INTOおよびUSINGキーワードを同じように使用することができます。 これらは結果セットと記述子領域内のメタデータを生成します。
さて、どうやって記述子領域からデータを取り出すのでしょうか。 この記述子領域を名前付きフィールドを持つ構造体とみなすことができます。 ヘッダからフィールド値を取り出し、それをホスト変数に格納するには、以下のコマンドを使用します。
EXEC SQL GET DESCRIPTOR name :hostvar = field;
今のところ、COUNTというヘッダフィールドが1つだけ定義されています。 これは、記述子領域に存在する項目数を表すものです (つまり、結果内に含まれる列数です)。 このホスト変数は整数型でなければなりません。 項目記述子領域からフィールドを取り出すには、以下のコマンドを使用します。
EXEC SQL GET DESCRIPTOR name VALUE num :hostvar = field;
numはリテラル整数、もしくは整数を持つホスト変数を取ることができます。 取り得るフィールドは以下の通りです。
結果セット内の行数です。
実際のデータ項目です (したがってこのフィールドのデータ型は問い合わせに依存します)。
?
未実装です。
(NULL値や値の切り詰めを示す)指示子です。
実装されていません。
データの文字数です。
列名です。
実装されていません。
データの文字表現のバイト長です。
(numeric型用の)精度です。
データの文字数です。
データの文字表現のバイト長です。
(numeric型用の)桁です。
列のデータ型の数値コードです。
EXECUTE、DECLAREおよびOPEN文では、INTOおよびUSINGの効果は異なります。 また、問い合わせやカーソル用の入力パラメータを提供するために記述子領域は手作業で構築することができます。 USING SQL DESCRIPTOR nameは入力パラメータとパラメータ付きの問い合わせに渡す方法です。 名前付きSQL記述子領域を構築する文は以下の通りです。
EXEC SQL SET DESCRIPTOR name VALUE num field = :hostvar;
PostgreSQLは、1つのFETCH文内の1レコードを複数取り出し、ホスト変数に格納することをサポートします。 この場合ホスト変数は配列であると仮定されます。
EXEC SQL BEGIN DECLARE SECTION; int id[5]; EXEC SQL END DECLARE SECTION; EXEC SQL FETCH 5 FROM mycursor INTO SQL DESCRIPTOR mydesc; EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :id = DATA;
SQLDA記述子領域は、問い合わせの結果セットとメタデータを取り出すために使用可能なC言語の構造体です。 1つの構造体には結果セットの1レコードが格納されます。
EXEC SQL include sqlda.h; sqlda_t *mysqlda; EXEC SQL FETCH 3 FROM mycursor INTO DESCRIPTOR mysqlda;
SQLキーワードが省略されていることに注意してください。 項33.9.1のINTOおよびUSINGの使用状況に関する段落はここで多少追加して適用します。 DESCRIBE文では、INTOが使用されている場合DESCRIPTORキーワードは完全に省略可能です。
EXEC SQL DESCRIBE prepared_statement INTO mysqlda;
SQLDA構造体を以下に示します。
#define NAMEDATALEN 64 struct sqlname { short length; char data[NAMEDATALEN]; }; struct sqlvar_struct { short sqltype; short sqllen; char *sqldata; short *sqlind; struct sqlname sqlname; }; struct sqlda_struct { char sqldaid[8]; long sqldabc; short sqln; short sqld; struct sqlda_struct *desc_next; struct sqlvar_struct sqlvar[1]; }; typedef struct sqlvar_struct sqlvar_t; typedef struct sqlda_struct sqlda_t;
結果セット内のフィールド数に依存しますし、レコード内の文字列データ値の長さにも依存しますので、SQLDA構造体に割り当てられたデータは可変です。 SQLDA構造体の個々のフィールドを以下に示します。
ここには"SQLDA "文字列リテラルが含まれます。
ここにはバイト単位の割り当てられた領域のサイズが含まれます。
USINGキーワードを使用してOPEN、DECLARE、EXECUTE文に渡される場合、ここにはパラメータ付き問い合わせの入力パラメータ数が含まれます。 SELECT、EXECUTE、FETCH文の出力として使用される場合、この値はsqld文と同じです。
ここには結果セットのフィールド数が含まれます。
問い合わせが複数のレコードを返す場合、複数結び付いたSQLDA構造体が返されます。 最初のレコードが返されるSQLDA内に格納されます。
これは結果セット内のフィールドの配列です。 以下にこのフィールドを示します。
ここにはフィールドの型識別子が含まれます。 値についてはecpgtype.hのenum ECPGttypeを参照してください。
フィールドのバイナリ長が含まれます。 例えばECPGt_intでは4バイトです。
(char *)sqldataはデータを指し示します。
(char *)sqlindはデータのNULL指示子を指し示します。 0は非NULLを、-1はNULLを意味します。
struct sqlname sqlnameには構造体内のフィールド名が含まれます。
struct sqlname { short length; char data[NAMEDATALEN]; };
sqlname.lengthにはフィールド名の長さが含まれます。
sqlname.dataには実際のフィールド名が含まれます。