| Symfoware Server SQLビギナーズガイド - FUJITSU - |
目次
索引
![]()
|
| 第7章 アプリケーションの実行時に動的SQL文を実行する方法 | > 7.2 SQL文を動的に変更して実行する | > 7.2.2 SQL文の準備とSQL記述子域の操作 |
データの取り出しを連続的に行う場合には、動的SELECT文を準備して実行します。SQL記述子域を使用して、動的SELECT文を実行するアプリケーションの例を以下に示します。
例
端末から入力した動的SELECT文の例です。
#include <stdio.h>
#include <string.h>
EXEC SQL BEGIN DECLARE SECTION;
char SQLSTATE[6];
char SQLMSG[256];
VARCHAR str[1024]; /* SQL文変数 */ …(1)
short vartype; /* データ型 */ …(2)
short varleng; /* 文字数 */ …(2)
short varolen; /* バイト数 */ …(2)
short varprec; /* 精度 */ …(2)
short varscal; /* 位取り */ …(2)
char varname[39]; /* 列の名前 */ …(2)
char varchar[39]; /* 文字セット名 */ …(2)
short vardcod; /* 日時,時間隔 */ …(2)
short vardpre; /* 時間隔精度 */ …(2)
short varocount; /* 選択リストの数 */
short i; /* SQL記述子域のカウンタ */
char ocdata[15]; /* CHARACTER型 */ …(3)
char CHARACTER SET IS NCHAR oncdata[21]; /* NCHAR型 */ …(3)
long oidata; /* 真数型 */ …(3)
double ofdata; /* 概数型 */ …(3)
VARCHAR oddata[20]; /* 日時,時間隔 */ …(3)
EXEC SQL END DECLARE SECTION;
void main()
{
memset(SQLSTATE, 0x00, 6); …(4)
memset(SQLMSG, 0x00, 256); …(4)
memset(&str, 0x00, sizeof(str)); …(4)
memset(varname, 0x00, 39); …(4)
memset(varchar, 0x00, 39); …(4)
memset(ocdata, 0x00, 15); …(4)
memset(oncdata, 0x00, 21); …(4)
memset(&oddata, 0x00, sizeof(oddata)); …(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 ALLOCATE DESCRIPTOR 'OUTDESC' WITH MAX 100; …(10)
EXEC SQL DESCRIBE OUTPUT STMID USING SQL DESCRIPTOR 'OUTDESC'; …(11)
/**************/
/* 選択リスト */
/**************/
EXEC SQL GET DESCRIPTOR 'OUTDESC' :varocount = COUNT; …(12)
for( i = 1; i <= varocount; i++ ) {
EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i …(13)
:vartype = TYPE, …(13)
:varleng = LENGTH, …(13)
:varolen = OCTET_LENGTH, …(13)
:varprec = PRECISION, …(13)
:varscal = SCALE, …(13)
:varchar = CHARACTER_SET_NAME, …(13)
:vardcod = DATETIME_INTERVAL_CODE, …(13)
:vardpre = DATETIME_INTERVAL_PRECISION;…(13)
/* CHAR型かNCHAR型 */ …(14)
if( vartype == 1 || vartype == 12 ) { …(14)
/* 文字列型 */ …(14)
if( strncmp( varchar, "BASIC", 5 ) == 0 ) { …(14)
EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i …(14)
TYPE = 1, …(14)
LENGTH = 14, …(14)
OCTET_LENGTH = 14, …(14)
CHARACTER_SET_NAME = 'BASIC'; …(14)
} …(14)
/* 各国語文字列型 */ …(14)
else { …(14)
EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i …(14)
TYPE = 1, …(14)
LENGTH = 10, …(14)
OCTET_LENGTH = 20, …(14)
CHARACTER_SET_NAME = 'NCHAR'; …(14)
} …(14)
} …(14)
/* INTEGER型かSMALLINT型 */ …(14)
else if( vartype == 4 || vartype == 5 ) { …(14)
EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i …(14)
TYPE = 4, …(14)
PRECISION = 31, …(14)
SCALE = 0; …(14)
} …(14)
/* NUMERIC型かDECIMAL型かREAL型かDOUBLE PRECISION型 */ …(14)
else if( vartype == 2 || vartype == 3 || …(14)
vartype == 7 || vartype == 8 ) { …(14)
EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i …(14)
TYPE = 8, …(14)
PRECISION = 52, …(14)
SCALE = 0; …(14)
} …(14)
/* 日時型かINTERVAL型 */ …(14)
else if( vartype == 9 || vartype == 10 ) { …(14)
EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i …(14)
TYPE = 12, …(14)
LENGTH = 19, …(14)
OCTET_LENGTH = 19, …(14)
CHARACTER_SET_NAME = 'BASIC'; …(14)
} …(14)
}
EXEC SQL OPEN CUR1; …(15)
EXEC SQL WHENEVER NOT FOUND GOTO :NOTFND; …(16)
for(;;) {
EXEC SQL FETCH CUR1 INTO SQL DESCRIPTOR 'OUTDESC'; …(17)
/************/
/* 実行結果 */
/************/
for( i = 1; i <= varocount; i++ ) {
EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i …(18)
:vartype = TYPE, …(18)
:varchar = CHARACTER_SET_NAME; …(18)
/* CHAR型かNCHAR型 */ …(18)
if( vartype == 1 ) { …(18)
/* 文字列型 */ …(18)
if( strncmp( varchar, "BASIC", 5 ) == 0 ) { …(18)
EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i …(18)
:varname = NAME, …(18)
:ocdata = DATA; …(18)
} …(18)
/* 各国語文字列型 */ …(18)
else { …(18)
EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i …(18)
:varname = NAME, …(18)
:oncdata = DATA; …(18)
} …(18)
} …(18)
/* 真数型 */ …(18)
else if( vartype == 4 ) { …(18)
EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i …(18)
:varname = NAME, …(18)
:oidata = DATA; …(18)
} …(18)
/* 概数型 */ …(18)
else if( vartype == 8 ) { …(18)
EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i …(18)
:varname = NAME, …(18)
:ofdata = DATA; …(18)
} …(18)
/* 日時型かINTERVAL型 */ …(18)
else if( vartype == 12 ) { …(18)
EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i …(18)
:varname = NAME, …(18)
:oddata = DATA; …(18)
oddata.sqlvar[oddata.sqllen] = \0; …(18)
printf( "%s -> %s \n", varname, oddata.sqlvar ); …(18)
} …(18)
}
}
NOTFND:
EXEC SQL CLOSE CUR1; …(19)
EXEC SQL DEALLOCATE DESCRIPTOR 'OUTDESC'; …(20)
EXEC SQL DEALLOCATE PREPARE STMID; …(21)
EXEC SQL COMMIT WORK; …(22)
EXEC SQL DISCONNECT DEFAULT; …(23)
return;
ERR:
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf( "SQLERROR SQLSTATE = %s SQLMSG = %s\n", SQLSTATE, SQLMSG );
EXEC SQL ROLLBACK WORK;
EXEC SQL DISCONNECT DEFAULT;
return;
} |
(1) SQL文変数はSQL文を格納する領域です。可変長文字列は、コンパイル時に以下の構造体に展開されます。
struct {
short sqllen; /* 長さ領域の変数 */
char sqlvar[1024]; /* 文字列領域の変数 */
}str;
(2) SQL記述子域
(3) 相手指定
(4) ホスト変数を初期化します。
(5) コネクションを接続します。
(6) SQL文の実行でデータなし以外のエラーが生じた場合にERRへ進み、エラー情報を出力してプログラムは終了します。
(7) 端末から入力された動的SELECT文を読み込み、strに格納します。
(8) カーソルCUR1を宣言します。カーソル指定としてSQL文識別子STMIDを指定します。
(9) strのSQL文を実行できるようにするための準備処理を行います。
(10) 相手指定のためのSQL記述子域OUTDESCを割り当てます。
(11) 入力した動的SELECT文の選択リストの情報をSQL記述子域OUTDESCに取り込みます。
(12) OUTDESCに設定されている選択リストの個数(COUNTの値)を取得します。
(13) OUTDESCに設定されているそれぞれの選択リストの情報(TYPE、LENGTH、OCTET_LENGTH、PRECISION、SCALE、CHARACTER_SET_NAMEの値)を取得します。
(14) OUTDESCに実行結果を取り出す相手指定のデータ型を設定します。
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は文字列の長さ)
(15) カーソルCUR1をオープンします。
(16) 検索の結果データが見つからない場合にNOTFNDに進み、プログラムは終了します。
(17) カーソルCUR1の位置づけおよびデータの読込みを行います。このとき、OUTDESCのDATAに実行結果の値が設定されます。
(18) SQL記述子域OUTDESCからNAMEとDATAの値を取得し、それぞれ相手指定のデータ型に一致したホスト変数に格納します。
(19) カーソルCUR1をクローズします。
(20) SQL記述子域OUTDESCを解放します。
(21) SQL文識別子STMIDに対応する被準備文を解放します。
(22) 現行のトランザクションを終了します。
(23) コネクションを切断します。
目次
索引
![]()
|