Symfoware(R) Server SQLビギナーズガイド - FUJITSU -
目次 索引 前ページ次ページ

上へ第7章 応用プログラムの実行時に動的SQL文を実行する方法
上へ7.3 SQL文の条件を動的に変更して実行する
上へ7.3.1 SQLDA構造体の操作方法

7.3.1.1 動的SELECT文を準備して実行する(SQLDA構造体の場合)

データの取り出しを連続的に行う場合には、動的SELECT文を準備して実行します。SQLDA構造体を使用して、動的パラメタ指定のある動的SELECT文を実行する応用プログラムの例を“図:SQLDA構造体(動的パラメタ指定)を使用した応用プログラムの例”に示します。

端末から入力した動的SELECT文の例です。端末から入力した動的パラメタ指定の値を探索条件としてデータを検索し、その値を表示します。

[図:SQLDA構造体(動的パラメタ指定)を使用した応用プログラムの例]

 #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_in ;            /* SQLDA構造体       */
   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   varicount;            /* 動的パラメタ指定の数   */
   short   varocount;            /* 選択リストの数      */
   short   i;                /* SQL記述子域のカウンタ  */
   char   icdata[100][15];         /* CHARACTER型       */
   char   incdata[100][21];         /* NCHAR型         */
   long   iidata[100];           /* 真数型    相手指定  */
   double  ifdata[100];           /* 概数型          */
   char   iddata[100][22];         /* 日時,時間隔       */
   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(icdata, 0x00, sizeof(icdata));                    …(2)
   memset(incdata, 0x00, sizeof(incdata));                   …(2)
   memset(iddata, 0x00, sizeof(iddata));                    …(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_in = (SQLDA *)malloc(size);
   sqlda_out = (SQLDA *)malloc(size);
   memset( sqlda_in, 0x00, size );
   memset( sqlda_out, 0x00, size );
   sqlda_in->SQLN = 100;                            …(4)
   sqlda_out->SQLN = 100;
   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 INPUT STMID USING SQL DESCRIPTOR :sqlda_in;        …(10)
   EXEC SQL DESCRIBE OUTPUT STMID USING SQL DESCRIPTOR :sqlda_out;       …(11)

   /********************/
   /* 動的パラメタ指定 */
   /********************/
   varicount = sqlda_in->SQLD;                         …(12)
   for( i = 1; i <= varicount; i++ ) {
    vartype = sqlda_in->SQLVAR[i].SQLTYPE;                  …(13)
    varleng = sqlda_in->SQLVAR[i].SQLLEN;                   …(13)
    varprec = sqlda_in->SQLVAR[i].SQLPRECISION.PRECISION;           …(13)
    varscal = sqlda_in->SQLVAR[i].SQLSCALE;                  …(13)
    vardcod = sqlda_in->SQLVAR[i].SQLSCALE;                  …(13)
    vardpre = sqlda_in->SQLVAR[i].SQLPRECISION.INTERVAL.           …(13)
    DATETIME_INTERVAL_PRECISION;                       …(13)
    memcpy( varname, sqlda_out->SQLVAR[i].SQLNAME.SQLNAMEC,          …(13)
             sqlda_out->SQLVAR[i].SQLNAME.SQLNAMEL );        …(13)
    varname[sqlda_out->SQLVAR[i].SQLNAME.SQLNAMEL] = 0x00;          …(13)
     /* CHAR型 */                               …(14)
     if( vartype == 1 || vartype == 12 ) {                  …(14)
       printf( "%sの値を指定してください \n", varname );          …(14)
       scanf( "%s", &icdata[i][0] );                    …(14)
       sqlda_in->SQLVAR[i].SQLTYPE = 12;                  …(14)
       sqlda_in->SQLVAR[i].SQLLEN = strlen( &icdata[i][0] );        …(14)
       sqlda_in->SQLVAR[i].SQLDATA = (char *)&icdata[i][0];         …(14)
     }                                    …(14)
     else if( vartype == 11 || vartype == 13 ) {               …(14)
       printf( "%sの値を指定してください \n", varname );          …(14)
       scanf( "%s", &incdata[i][0] );                    …(14)
       sqlda_in->SQLVAR[i].SQLTYPE = 13;                  …(14)
       sqlda_in->SQLVAR[i].SQLLEN = strlen( &incdata[i][0] );        …(14)
       sqlda_in->SQLVAR[i].SQLDATA = (char *)&incdata[i][0];        …(14)
     }                                    …(14)
     /* INTEGER型かSMALLINT型 */                       …(14)
     else if( vartype == 4 || vartype == 5 ) {                …(14)
       printf( "%sの値を指定してください \n", varname );          …(14)
       scanf( "%ld", &iidata[i] );                     …(14)
       sqlda_in->SQLVAR[i].SQLTYPE = 4;                   …(14)
       sqlda_in->SQLVAR[i].SQLLEN = 4;                   …(14)
       sqlda_in->SQLVAR[i].SQLPRECISION.PRECISION = 31;           …(14)
       sqlda_in->SQLVAR[i].SQLSCALE = 0;                  …(14)
       sqlda_in->SQLVAR[i].SQLDATA = (char *)&iidata[i];          …(14)
     }                                    …(14)
     /* NUMERIC型かDECIMAL型かREAL型かDOUBLE PRECISION型 */          …(14)
     else if( vartype == 2 || vartype == 3 ||                 …(14)
         vartype == 7 || vartype == 8 ) {                …(14)
       printf( "%sの値を指定してください \n", varname );          …(14)
       scanf( "%lf", &ifdata[i] );                     …(14)
       sqlda_in->SQLVAR[i].SQLTYPE = 8;                   …(14)
       sqlda_in->SQLVAR[i].SQLLEN = 8;                   …(14)
       sqlda_in->SQLVAR[i].SQLPRECISION.PRECISION = 52;           …(14)
       sqlda_in->SQLVAR[i].SQLSCALE = 0;                  …(14)
       sqlda_in->SQLVAR[i].SQLDATA = (char *)&ifdata[i];          …(14)
     }                                    …(14)
     /* 日時型かINTERVAL型 */                         …(14)
     else if( vartype == 9 || vartype == 10 ) {                …(14)
       printf( "%sの値を指定してください \n", varname );          …(14)
       scanf( "%s", &iddata[i][0] );                    …(14)
       sqlda_in->SQLVAR[i].SQLTYPE = 12;                  …(14)
       sqlda_in->SQLVAR[i].SQLLEN = strlen( &iddata[i][0] );        …(14)
       sqlda_in->SQLVAR[i].SQLDATA = (char *)&iddata[i][0];         …(14)
     }                                    …(14)
   }
   /**************/
   /* 選択リスト */
   /**************/
   varocount = sqlda_out->SQLD;                         …(15)
   for( i = 0; i < varocount; i++ ) {                      …(16)
     vartype = sqlda_out->SQLVAR[i].SQLTYPE;                 …(16)
     varleng = sqlda_out->SQLVAR[i].SQLLEN;                  …(16)
     varprec = sqlda_out->SQLVAR[i].SQLPRECISION.PRECISION;          …(16)
     varscal = sqlda_out->SQLVAR[i].SQLSCALE;                 …(16)
   vardcod = sqlda_out->SQLVAR[i].SQLSCALE;                   …(16)
   vardpre = sqlda_out->SQLVAR[i].SQLPRECISION.INTERVAL.            …(16)
        DATETIME_INTERVAL_PRECISION;
     /* CHAR型かVCHAR型 */                          …(17)
     if( vartype == 1 || vartype == 12 ) {                  …(17)
       sqlda_out->SQLVAR[i].SQLTYPE = 1;                  …(17)
       sqlda_out->SQLVAR[i].SQLLEN = 14;                  …(17)
       sqlda_out->SQLVAR[i].SQLDATA = (char *)&ocdata[i][0];        …(17)
     }                                    …(17)
     /* NCHAR型かNVCHAR型 */                         …(17)
     else if( vartype == 11 || vartype == 13 ) {               …(17)
       sqlda_out->SQLVAR[i].SQLTYPE = 11;                  …(17)
       sqlda_out->SQLVAR[i].SQLLEN = 20;                  …(17)
       sqlda_out->SQLVAR[i].SQLDATA = (char *)&oncdata[i][0];        …(17)
     }                                    …(17)
     /* INTEGER型かSMALLINT型 */                       …(17)
     else if( vartype == 4 || vartype == 5 ) {                …(17)
       sqlda_out->SQLVAR[i].SQLTYPE = 4;                  …(17)
       sqlda_out->SQLVAR[i].SQLLEN = 4;                  …(17)
       sqlda_out->SQLVAR[i].SQLPRECISION.PRECISION = 31;          …(17)
       sqlda_out->SQLVAR[i].SQLSCALE = 0;                  …(17)
       sqlda_out->SQLVAR[i].SQLDATA = (char *)&oidata[i];          …(17)
     }                                    …(17)
     /* NUMERIC型かDECIMAL型かREAL型かDOUBLE PRECISION型 */          …(17)
     else if( vartype == 2 || vartype == 3 ||                 …(17)
         vartype == 7 || vartype == 8 ) {                …(17)
       sqlda_out->SQLVAR[i].SQLTYPE = 8;                  …(17)
       sqlda_out->SQLVAR[i].SQLLEN = 8;                  …(17)
       sqlda_out->SQLVAR[i].SQLPRECISION.PRECISION = 52;          …(17)
       sqlda_out->SQLVAR[i].SQLSCALE = 0;                  …(17)
       sqlda_out->SQLVAR[i].SQLDATA = (char *)&ofdata[i];          …(17)
     }                                    …(17)
     /* 日時型かINTERVAL型 */                         …(17)
     else if( vartype == 9 || vartype == 10 ) {                …(17)
       sqlda_out->SQLVAR[i].SQLTYPE = 12;                  …(17)
       sqlda_out->SQLVAR[i].SQLLEN = 21;                  …(17)
       sqlda_out->SQLVAR[i].SQLDATA = (char *)&oddata[i][0];        …(17)
     }                                    …(17)
   }
   EXEC SQL OPEN CUR1 USING SQL DESCRIPTOR :sqlda_in;              …(18)
   EXEC SQL WHENEVER NOT FOUND GOTO :NOTFND;                  …(19)
   for(;;) {
     EXEC SQL FETCH CUR1 INTO SQL DESCRIPTOR :sqlda_out;           …(20)
     /************/
     /* 実行結果 */
     /************/
     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;                            …(21)
   EXEC SQL DEALLOCATE PREPARE STMID;                     …(22)
   EXEC SQL COMMIT WORK;                            …(23)
   EXEC SQL DISCONNECT DEFAULT;                        …(24)
   free( sqlda_in );
   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_in );
   free( sqlda_out );
   return;
 }

(1) SQL文変数はSQL文を格納する領域です。可変長文字列は、翻訳時に以下の構造体に展開されます。

struct { 
  short sqllen; /* 長さ領域の変数 */ 
  char sqlvar[100]; /* 文字列領域の変数 */ 
}str; 

(2) ホスト変数を初期化します。

(3) SQLDA構造体の領域を獲得します。

(4) 配列SQLVARの配列数(SQLNの値)を指定します。

(5) コネクションを接続します。

(6) SQL文の実行でデータなし以外のエラーが生じた場合にERRへ進み、エラー情報を出力してプログラムは終了します。

(7) 端末から入力された動的SELECT文を読み込み、strに格納します。

(8) カーソルCUR1を宣言します。カーソル指定としてSQL文識別子STMIDを指定します。

(9) strのSQL文を実行できるようにするための準備処理を行います。

(10) 入力した動的SELECT文の動的パラメタ指定の情報をSQLDA構造体(sqlda_in)に取り込みます。

(11) 入力した動的SELECT文の選択リストの情報をSQLDA構造体(sqlda_out)に取り込みます。

(12) SQLDA構造体(sqlda_in)に設定されている選択リストの個数(SQLDの値)を取得します。

(13) SQLDA構造体(sqlda_in)に設定されているおのおのの動的パラメタ指定の情報(SQLTYPE、SQLLEN、SQLPRECISION、SQLSCALE、DATETINE_INTERVAL_CODE、DATETIME_INTERVAL_PRECISIONの値)を取得します。

(14) SQLDA構造体(sqlda_in)に設定されている動的パラメタ指定のデータ型を変更し、端末から読み込んだ動的パラメタ指定の値を設定します。

(15) SQLDA構造体に設定されている選択リストの個数(SQLDの値)を取得します。

(16) SQLDA構造体に設定されているそれぞれの選択リストの情報(SQLTYPE、SQLLEN、SQLPRECISION、SQLSCALEの値)を取得します。

(17) SQLDA構造体に実行結果を取り出す相手指定のデータ型や変数アドレスを設定します。

(18) (14)の値を使用して、カーソルCUR1をオープンします。

(19) 検索の結果データが見つからない場合にNOTFNDに進み、プログラムは終了します。

(20) カーソルCUR1の位置づけおよびデータの読み込みを行います。このとき、SQLDA構造体(sqlda_out)のSQLDATAに設定したアドレスに実行結果の値が設定されます。

(21) カーソルCUR1をクローズします。

(22) SQL文識別子STMIDに対応する被準備文を解放します。

(23) 現行のトランザクションを終了します。

(24) コネクションを切断します。


目次 索引 前ページ次ページ

All Rights Reserved, Copyright (C) 富士通株式会社 2003