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

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

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

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

端末から入力した動的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、SQLPREC1ION、SQLSCALEの値)を取得します。

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

(14) カーソルCUR1をオープンします。

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

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

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

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

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

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


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

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