| Symfoware Server SQLビギナーズガイド - FUJITSU - |
目次
索引
![]()
|
| 第7章 アプリケーションの実行時に動的SQL文を実行する方法 | > 7.2 SQL文を動的に変更して実行する | > 7.2.1 SQL文の準備とSQLDA構造体の操作 |
データの取り出しを連続的に行う場合には、動的SELECT文を準備して実行します。SQLDA構造体を使用して、動的SELECT文を実行するアプリケーションの例を以下に示します。
例
端末から入力した動的SELECT文の例です。
#include <stdio.h>
#include <string.h>
#include "qdbnosis.h"
EXEC SQL BEGIN DECLARE SECTION;
char SQLSTATE[6];
char SQLMSG[256];
VARCHAR str[1024]; /* SQL文変数 */ …(1)
SQLDA *sqlda_out; /* SQLDA構造体 */
EXEC SQL END DECLARE SECTION;
void main()
{
short vartype; /* データ型 */
short varleng; /* 文字数 */
short varolen; /* バイト数 */
short varprec; /* 精度 */
short varscal; /* 位取り SQL記述子域 */
char varname[129]; /* 列の名前 */
short vardcod; /* 日時,時間隔 */
short vardpre; /* 時間隔精度 */
short varocount; /* 選択リストの数 */
short i; /* SQL記述子域のカウンタ */
char ocdata[100][15]; /* CHARACTER型 */
char oncdata[100][21]; /* NCHAR型 */
long oidata[100]; /* 真数型 相手指定 */
double ofdata[100]; /* 概数型 */
char oddata[100][22]; /* 日時,時間隔 */
short inddata[100]; /* 標識変数 */
size_t size; /* SQLDAのサイズ */
memset(SQLSTATE, 0x00, 6); …(2)
memset(SQLMSG, 0x00, 256); …(2)
memset(&str, 0x00, sizeof(str)); …(2)
memset(varname, 0x00, sizeof(varname)); …(2)
memset(ocdata, 0x00, sizeof(ocdata) ); …(2)
memset(oncdata, 0x00, sizeof(oncdata) ); …(2)
memset(oddata, 0x00, sizeof(oddata)); …(2)
size = sizeof(SQLDA) + sizeof(sqlvar) * (100 - 1); …(3)
sqlda_out = (SQLDA *)malloc(size);
memset( sqlda_out, 0x00, size );
sqlda_out->SQLN = 100; …(4)
EXEC SQL CONNECT TO DEFAULT; …(5)
EXEC SQL WHENEVER SQLERROR GOTO :ERR; …(6)
printf( "実行する動的SELECT文を指定してください \n" );
gets( str.sqlvar ); …(7)
str.sqllen = strlen( str.sqlvar );
EXEC SQL DECLARE CUR1 CURSOR FOR STMID; …(8)
EXEC SQL PREPARE STMID FROM :str; …(9)
EXEC SQL DESCRIBE OUTPUT STMID USING SQL DESCRIPTOR :sqlda_out; …(10)
/**************/
/* 選択リスト */
/**************/
varocount = sqlda_out->SQLD; …(11)
for( i = 0; i < varocount; i++ ) {
vartype = sqlda_out->SQLVAR[i].SQLTYPE; …(12)
varleng = sqlda_out->SQLVAR[i].SQLLEN; …(12)
varprec = sqlda_out->SQLVAR[i].SQLPRECISION.PRECISION; …(12)
varscal = sqlda_out->SQLVAR[i].SQLSCALE; …(12)
vardcod = sqlda_out->SQLVAR[i].SQLSCALE; …(12)
vardpre = sqlda_out->SQLVAR[i].SQLPRECISION.INTERVAL. …(12)
DATETIME_INTERVAL_PRECISION;
/* CHAR型かVCHAR型 */ …(13)
if( vartype == 1 || vartype == 12 ) { …(13)
sqlda_out->SQLVAR[i].SQLTYPE = 1; …(13)
sqlda_out->SQLVAR[i].SQLLEN = 14; …(13)
sqlda_out->SQLVAR[i].SQLDATA = (char *)&ocdata[i][0]; …(13)
} …(13)
/* NCHAR型かNVCHAR型 */ …(13)
else if( vartype == 11 || vartype == 13 ) { …(13)
sqlda_out->SQLVAR[i].SQLTYPE = 11; …(13)
sqlda_out->SQLVAR[i].SQLLEN = 20; …(13)
sqlda_out->SQLVAR[i].SQLDATA = (char *)&oncdata[i][0]; …(13)
} …(13)
/* INTEGER型かSMALLINT型 */ …(13)
else if( vartype == 4 || vartype == 5 ) { …(13)
sqlda_out->SQLVAR[i].SQLTYPE = 4; …(13)
sqlda_out->SQLVAR[i].SQLLEN = 4; …(13)
sqlda_out->SQLVAR[i].SQLPRECISION.PRECISION = 31; …(13)
sqlda_out->SQLVAR[i].SQLSCALE = 0; …(13)
sqlda_out->SQLVAR[i].SQLDATA = (char *)&oidata[i]; …(13)
} …(13)
/* NUMERIC型かDECIMAL型かREAL型かDOUBLE PRECISION型 */ …(13)
else if( vartype == 2 || vartype == 3 || …(13)
vartype == 7 || vartype == 8 ) { …(13)
sqlda_out->SQLVAR[i].SQLTYPE = 8; …(13)
sqlda_out->SQLVAR[i].SQLLEN = 8; …(13)
sqlda_out->SQLVAR[i].SQLPRECISION.PRECISION = 52; …(13)
sqlda_out->SQLVAR[i].SQLSCALE = 0; …(13)
sqlda_out->SQLVAR[i].SQLDATA = (char *)&ofdata[i]; …(13)
} …(13)
/* 日時型かINTERVAL型 */ …(13)
else if( vartype == 9 || vartype == 10 ) { …(13)
sqlda_out->SQLVAR[i].SQLTYPE = 12; …(13)
sqlda_out->SQLVAR[i].SQLLEN = 21; …(13)
sqlda_out->SQLVAR[i].SQLDATA = (char *)&oddata[i][0]; …(13)
} …(13)
}
EXEC SQL OPEN CUR1; …(14)
EXEC SQL WHENEVER NOT FOUND GOTO :NOTFND; …(15)
for(;;) {
EXEC SQL FETCH CUR1 INTO SQL DESCRIPTOR :sqlda_out; …(16)
/************/
/* 実行結果 */
/************/
for( i = 0; i < varocount; i++ ) {
vartype = sqlda_out->SQLVAR[i].SQLTYPE;
memcpy( varname, sqlda_out->SQLVAR[i].SQLNAME.SQLNAMEC,
sqlda_out->SQLVAR[i].SQLNAME.SQLNAMEL );
varname[sqlda_out->SQLVAR[i].SQLNAME.SQLNAMEL] = 0x00;
/* CHAR型 */
if( vartype == 1 ) {
printf( "%s -> %s ", varname, &ocdata[i][0] );
}
/* NCHAR型 */
else if( vartype == 11 ) {
printf( "%s -> %s ", varname, &oncdata[i][0] );
}
/* 真数型 */
else if( vartype == 4 ) {
printf( "%s -> %d ", varname, oidata[i] );
}
/* 概数型 */
else if( vartype == 8 ) {
printf( "%s -> %lf ", varname, ofdata[i] );
}
/* 日時型かINTERVAL型 */
else if( vartype == 12 ) {
printf( "%s -> %s ", varname, &oddata[i][2] );
}
}
printf( "\n" );
}
NOTFND:
EXEC SQL CLOSE CUR1; …(17)
EXEC SQL DEALLOCATE PREPARE STMID; …(18)
EXEC SQL COMMIT WORK; …(19)
EXEC SQL DISCONNECT DEFAULT; …(20)
free( sqlda_out );
return;
ERR:
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf( "SQLERROR SQLSTATE = %s SQLMSG = %s\n", SQLSTATE, SQLMSG );
EXEC SQL ROLLBACK WORK;
EXEC SQL DISCONNECT DEFAULT;
free( sqlda_out );
return;
} |
(1) SQL文変数はSQL文を格納する領域です。可変長文字列は、コンパイル時に以下の構造体に展開されます。
struct {
short sqllen; /* 長さ領域の変数 */
char sqlvar[1024]; /* 文字列領域の変数 */
}str;
(2) 変数を初期化します。
(3) SQLDA構造体の領域を獲得します。
(4) 配列SQLVARの配列数(SQLNの値)を指定します。
(5) コネクションを接続します。
(6) SQL文の実行でデータなし以外のエラーが生じた場合にERRへ進み、エラー情報を出力しプログラムは終了します。
(7) 端末から入力された動的SELECT文を読み込み、strに格納します。
(8) カーソルCUR1を宣言します。カーソル指定としてSQL文識別子STMIDを指定します。
(9) strのSQL文を実行できるようにするための準備処理を行います。
(10) 入力した動的SELECT文の選択リストの情報をSQLDA構造体に取り込みます。
(11) SQLDA構造体に設定されている選択リストの個数(SQLDの値)を取得します。
(12) SQLDA構造体に設定されているそれぞれの選択リストの情報(SQLTYPE、SQLLEN、SQLPRECISION、SQLSCALEの値)を取得します。
(13) SQLDA構造体に実行結果を取り出す相手指定のデータ型や変数のアドレスを設定します。
CHARACTER(n)、CHARACTER VARYING(n)をCHARACTER(14)に変更します。(nは文字列の長さ)
NATIONAL CHARACTER(n)、NATIONAL CHARACTER VARYING(n)をNATIONAL CHARACTER(10)に変更します。(nは文字列の長さ)
INTEGER、SMALLINTをINTEGERに変更します。
NUMERIC(p,q)、DECIMAL(p,q)、REAL、DOUBLE PRECISIONをDOUBLE PRECISIONに変更します。(pは精度、qは位取り)
DATE、TIME、TIMESTAMPおよびINTERVALをCHARACTER VARYING(19)に変更します。(nは文字列の長さ)
(14) カーソルCUR1をオープンします。
(15) 検索の結果データが見つからない場合にNOTFNDに進み、プログラムは終了します。
(16) カーソルCUR1の位置づけおよびデータの読込みを行います。このとき、SQLDA構造体のSQLDATAに設定したアドレスに実行結果の値が設定されます。
(17) カーソルCUR1をクローズします。
(18) SQL文識別子STMIDに対応する被準備文を解放します。
(19) 現行のトランザクションを終了します。
(20) コネクションを切断します。
目次
索引
![]()
|