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

第7章 アプリケーションの実行時に動的SQL文を実行する方法> 7.3 SQL文の条件を動的に変更して実行する> 7.3.1 SQLDA構造体の操作方法

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

データの取り出しを連続的に行う場合には、動的SELECT文を準備して実行します。SQLDA構造体を使用して、動的パラメタ指定のある動的SELECT文を実行するアプリケーションの例を以下に示します。

端末から入力した動的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 = 0; 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_in->SQLVAR[i].SQLNAME.SQLNAMEC,                    …(13)
                          sqlda_in->SQLVAR[i].SQLNAME.SQLNAMEL );                 …(13)
        varname[sqlda_in->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、DATETIME_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) 富士通株式会社 2007