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

上へ第7章 応用プログラムの実行時に動的SQL文を実行する方法
上へ7.3 SQL文の条件を動的に変更して実行する
上へ7.3.2 SQL記述子域の操作方法

7.3.2.1 動的SELECT文を準備して実行する(SQL記述子域の場合)

データの取り出しを連続的に行う場合には、動的SELECT文を準備して実行します。

SQL記述子域を使用して、動的パラメタ指定のある動的SELECT文を実行する応用プログラムの例を“図:SQL記述子域(動的パラメタ指定)を使用した応用プログラムの例”に示します。

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

[図:SQL記述子域(動的パラメタ指定)を使用した応用プログラムの例]

#include <stdio.h>
#include <string.h>

EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL INCLUDE varfile.h;                           …(1)
EXEC SQL END DECLARE SECTION;

void main()
 {
  memset(SQLSTATE, 0x00, 6);                          …(2)
  memset(SQLMSG, 0x00, 256);                          …(2)
  memset(str, 0x00, sizeof(str));                       …(2)
  memset(varname, 0x00, 39);                          …(2)
  memset(varchar, 0x00, 39);                          …(2)
  memset(icdata, 0x00, sizeof(icdata));                    …(2)
  memset(incdata, 0x00, sizeof(incdata));                   …(2)
  memset(iddata, 0x00, sizeof(iddata));                    …(2)
  memset(ocdata, 0x00, 15);                          …(2)
  memset(oncdata, 0x00, sizeof(oncdata));                   …(2)
  memset(oddata, 0x00, sizeof(oddata));                    …(2)

  EXEC SQL CONNECT TO DEFAULT;                         …(3)
  EXEC SQL WHENEVER SQLERROR GOTO :ERR;                    …(4)
  printf( "実行する動的SELECT文を指定してください \n" );
  gets( str.sqlvar );                             …(5)
  str.sqllen = strlen( str.sqlvar );
  EXEC SQL DECLARE CUR1 CURSOR FOR STMID;                   …(6)
  EXEC SQL PREPARE STMID FROM :str;                      …(7)
  EXEC SQL ALLOCATE DESCRIPTOR 'INDESC' WITH MAX 100;             …(8)
  EXEC SQL ALLOCATE DESCRIPTOR 'OUTDESC' WITH MAX 100;             …(9)
  EXEC SQL DESCRIBE INPUT STMID USING SQL DESCRIPTOR 'INDESC';         …(10)
  EXEC SQL DESCRIBE OUTPUT STMID USING SQL DESCRIPTOR 'OUTDESC';        …(11)

  /********************/
  /* 動的パラメタ指定 */
  /********************/
  EXEC SQL GET DESCRIPTOR 'INDESC' :varicount = COUNT;             …(12)
  for( i = 1; i <= varicount; i++ ) {
    EXEC SQL GET DESCRIPTOR 'INDESC' VALUE :i                …(13)
                     :vartype = TYPE,            …(13)
                     :varleng = LENGTH,           …(13)
                     :varolen = OCTET_LENGTH,        …(13)
                     :varprec = PRECISION,          …(13)
                     :varscal = SCALE,            …(13)
                     :varname = NAME,            …(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)
        printf( "%sの値を指定してください \n", varname );        …(14)
        scanf( "%s", icdata.sqlvar );                  …(14)
        icdata.sqllen = strlen( icdata.sqlvar );             …(14)
        EXEC SQL SET DESCRIPTOR 'INDESC' VALUE :i            …(14)
                         TYPE = 1,            …(14)
                         LENGTH = 14,          …(14)
                         OCTET_LENGTH = 14,       …(14)
                         CHARACTER_SET_NAME = 'BASIC',  …(14)
                         DATA = :icdata;         …(14)
      }                                  …(14)
      /* 各国語文字列型 */                         …(14)
      else {                                …(14)
        printf( "%sの値を指定してください \n", varname );        …(14)
        scanf( "%s", incdata.sqlvar );                  …(14)
        incdata.sqllen = strlen( incdata.sqlvar );            …(14)
        EXEC SQL SET DESCRIPTOR 'INDESC' VALUE :i            …(14)
                         TYPE = 1,            …(14)
                         LENGTH = 10,          …(14)
                         OCTET_LENGTH = 20,       …(14)
                         CHARACTER_SET_NAME = 'NCHAR',  …(14)
                         DATA = :incdata;        …(14)
      }                                  …(14)
    }                                    …(14)
    /* INTEGER型かSMALLINT型 */                       …(14)
    else if( vartype == 4 || vartype == 5 ) {                …(14)
      printf( "%sの値を指定してください \n", varname );          …(14)
      scanf( "%ld", &iidata );                       …(14)
      EXEC SQL SET DESCRIPTOR 'INDESC' VALUE :i              …(14)
                       TYPE = 4,              …(14)
                       PRECISION = 31,           …(14)
                       SCALE = 0,             …(14)
                       INDICATOR = 0,           …(14)
                       DATA = :iidata;           …(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 );                       …(14)
      EXEC SQL SET DESCRIPTOR 'INDESC' VALUE :i              …(14)
                       TYPE = 8,              …(14)
                       PRECISION = 52,           …(14)
                       SCALE = 0,             …(14)
                       DATA = :ifdata;           …(14)
    }                                    …(14)
    /* 日時型かINTERVAL型 */                         …(14)
    else if( vartype == 9 || vartype == 10 ) {                …(14)
      printf( "%sの値を指定してください \n", varname );          …(14)
      scanf( "%s", iddata.sqlvar );                    …(14)
      iddata.sqllen = strlen( iddata.sqlvar );               …(14)
      EXEC SQL SET DESCRIPTOR 'INDESC' VALUE :i              …(14)
                       TYPE = 12,             …(14)
                       LENGTH = 19,            …(14)
                       OCTET_LENGTH = 19,         …(14)
                       CHARACTER_SET_NAME = 'BASIC',    …(14)
                       DATA = :iddata;           …(14)
    }                                    …(14)
  }
  /**************/
  /* 選択リスト */
  /**************/
  EXEC SQL GET DESCRIPTOR 'OUTDESC' :varocount = COUNT;            …(15)
  for( i = 1; i <= varocount; i++ ) {
    EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i
                     :vartype = TYPE,            …(16)
                     :varleng = LENGTH,           …(16)
                     :varolen = OCTET_LENGTH,        …(16)
                     :varprec = PRECISION,          …(16)
                     :varscal = SCALE,            …(16)
                     :varchar = CHARACTER_SET_NAME,     …(16)
                     :vardcod = DATETIME_INTERVAL_CODE,   …(16)
                     :vardpre = DATETIME_INTERVAL_PRECISION; …(16)
    /* CHAR型かNCHAR型 */                          …(17)
    if( vartype == 1 || vartype == 12 ) {                  …(17)
      /* 文字列型 */                            …(17)
      if( strncmp( varchar, "BASIC", 5 ) == 0 ) {             …(17)
        EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i            …(17)
                         TYPE = 1,           …(17)
                         LENGTH = 14,          …(17)
                         OCTET_LENGTH = 14,       …(17)
                         CHARACTER_SET_NAME = 'BASIC'; …(17)
      }                                  …(17)
      /* 各国語文字列型 */                         …(17)
      else {                                …(17)
        EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i            …(17)
                         TYPE = 1,           …(17)
                         LENGTH = 10,          …(17)
                         OCTET_LENGTH = 20,       …(17)
                         CHARACTER_SET_NAME = 'NCHAR'; …(17)
      }                                  …(17)
    }                                    …(17)
    /* INTEGER型かSMALLINT型 */                       …(17)
    else if( vartype == 4 || vartype == 5 ) {                …(17)
      EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i              …(17)
                       TYPE = 4,             …(17)
                       PRECISION = 31,          …(17)
                       SCALE = 0;             …(17)
    }                                    …(17)
    /* NUMERIC型かDECIMAL型かREAL型かDOUBLE PRECISION型 */          …(17)
    else if( vartype == 2 || vartype == 3 ||                 …(17)
         vartype == 7 || vartype == 8 ) {                …(17)
      EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i              …(17)
                       TYPE = 8,             …(17)
                       PRECISION = 52,          …(17)
                       SCALE = 0;             …(17)
    }                                    …(17)
    /* 日時型かINTERVAL型 */                         …(17)
    else if( vartype == 9 || vartype == 10 ) {                …(17)
      EXEC SQL SET DESCRIPTOR 'OUTDESC' VALUE :i              …(17)
                       TYPE = 12,             …(17)
                       LENGTH = 19,            …(17)
                       OCTET_LENGTH = 19,         …(17)
                       CHARACTER_SET_NAME = 'BASIC';   …(17)
    }                                    …(17)
  }
  EXEC SQL OPEN CUR1 USING SQL DESCRIPTOR 'INDESC';              …(18)
  EXEC SQL WHENEVER NOT FOUND GOTO :NOTFND;                  …(19)
  for(;;) {
    EXEC SQL FETCH CUR1 INTO SQL DESCRIPTOR 'OUTDESC';            …(20)
    /************/
    /* 実行結果 */
    /************/
    for( i = 1; i <= varocount; i++ ) {
      EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i              …(21)
                       :vartype = TYPE,          …(21)
                       :varchar = CHARACTER_SET_NAME;   …(21)
      /* CHAR型かNCHAR型 */                        …(21)
      if( vartype == 1 ) {                         …(21)
        /* 文字列型 */                          …(21)
        if( strncmp( varchar, "BASIC", 5 ) == 0 ) {           …(21)
          EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i          …(21)
                           :varname = NAME,      …(21)
                           :ocdata = DATA;      …(21)
          printf( "%s -> %s  ", varname, ocdata );          …(21)
        }                                …(21)
        /* 各国語文字列型 */                       …(21)
        else {                              …(21)
          EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i          …(21)
                           :varname = NAME,      …(21)
                           :oncdata = DATA;      …(21)
          printf( "%s -> %s  ", varname, oncdata );          …(21)
        }                                …(21)
      }                                  …(21)
      /* 真数型 */                             …(21)
      else if( vartype == 4 ) {                      …(21)
        EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i            …(21)
                         :varname = NAME,        …(21)
                         :oidata = DATA;        …(21)
        printf( "%s -> %d  ", varname, oidata );            …(21)
      }                                  …(21)
      /* 概数型 */                             …(21)
      else if( vartype == 8 ) {                      …(21)
        EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i            …(21)
                         :varname = NAME,        …(21)
                         :ofdata = DATA;        …(21)
        printf( "%s -> %lf  ", varname, ofdata );            …(21)
      }                                  …(21)
      /* 日時型かINTERVAL型 */                       …(21)
      else if( vartype == 12 ) {                      …(21)
        EXEC SQL GET DESCRIPTOR 'OUTDESC' VALUE :i            …(21)
                         :varname = NAME,        …(21)
                         :oddata = DATA;        …(21)
        printf( "%s -> %s  ", varname, oddata.sqlvar );         …(21)
      }                                  …(21)
    }
    printf( "\n" );
  }
NOTFND:
  EXEC SQL CLOSE CUR1;                             …(22)
  EXEC SQL DEALLOCATE DESCRIPTOR 'INDESC';                   …(23)
  EXEC SQL DEALLOCATE DESCRIPTOR 'OUTDESC';                  …(24)
  EXEC SQL DEALLOCATE PREPARE STMID;                      …(25)
  EXEC SQL COMMIT WORK;                            …(26)
  EXEC SQL DISCONNECT DEFAULT;                         …(27)
  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) インクルードファイルvarfile.hのホスト変数を展開します。SQL文変数はSQL文を格納する領域です。可変長文字列は、翻訳時に以下の構造体に展開されます。

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

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

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

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

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

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

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

(8) 動的パラメタ指定のためのSQL記述子域INDESCを割り当てます。

(9) 相手指定のためのSQL記述子域OUTDESCを割り当てます。

(10) 入力した動的SELECT文の動的パラメタ指定の情報をSQL記述子域INDESCに取り込みます。

(11) 入力した動的SELECT文の選択リストの情報をSQL記述子域OUTDESCに取り込みます。

(12) INDESCに設定されている動的パラメタ指定の個数(COUNTの値)を取得します。

(13) INDESCに設定されているおのおのの動的パラメタ指定の情報(TYPE、LENGTH、OCTET_LENGTH、RECISION、SCALE、CHARACTER_SET_NAME、DATETINE_INTERVAL_CODE、DATETIME_INTERVAL_PRECISIONの値)を取得します。

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

(15) OUTDESCに設定されている選択リストの個数(COUNTの値)を取得します。

(16) OUTDESCに設定されているおのおのの選択リストの情報(TYPE、LENGTH、OCTET_LENGTH、PRECISION、SCALE、CHARACTER_SET_NAME、DATETIME_INTERVAL_CODE、DATETIME_INTERVAL_PRECISIONの値)を取得します。

(17) OUTDESCに実行結果を取り出す相手指定のデータ型を設定します。

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

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

(20) カーソルCUR1の位置づけおよびデータの読み込みを行います。このとき、OUTDESCのDATAに実行結果の値が設定されます。

(21) SQL記述子域OUTDESCからNAMEとDATAの値を取得し、それぞれ相手指定のデータ型に一致したホスト変数に格納します。実行結果を端末に出力します。

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

(23) SQL記述子域INDESCを解放します。

(24) SQL記述子域OUTDESCを解放します。

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

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

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

インクルードファイル“varfile.h”

/************************/
/* ホスト変数の定義開始 */
/************************/
  char   SQLSTATE[6];
  char   SQLMSG[256];
  VARCHAR  str[100];            /* SQL文変数       */
  short   vartype;             /* データ型        */ …(1)
  short   varleng;             /* 文字数         */ …(1)
  short   varolen;             /* バイト数        */ …(1)
  short   varprec;             /* 精度          */ …(1)
  short   varscal;             /* 位取り         */ …(1)
  char   varname[39];           /* 列の名前        */ …(1)
  char   varchar[39];           /* 文字セット名      */ …(1)
  short   vardcod;             /* 日時,時間隔      */ …(1)
  short   vardpre;             /* 時間隔精度       */ …(1)
  short   varicount;            /* 動的パラメタ指定の数  */
  short   varocount;            /* 選択リストの数     */
  short   i;                /* SQL記述子域のカウンタ */
  VARCHAR  icdata[15];           /* CHARACTER型      */ …(2)
  VARCHAR CHARACTER SET IS NCHAR incdata[21];/* NCHAR型        */ …(2)
  long   iidata;             /* 真数型         */ …(2)
  double  ifdata;             /* 概数型         */ …(2)
  VARCHAR  iddata[20];           /* 日時,時間隔      */ …(2)
  char   ocdata[15];           /* CHARACTER型      */ …(3)
  char CHARACTER SET IS NCHAR oncdata[21]; /* NCHAR型        */ …(3)
  long   oidata;             /* 真数型         */ …(3)
  double  ofdata;             /* 概数型         */ …(3)
  VARCHAR  oddata[20];           /* 日時,時間隔      */ …(3)
/************************/
/* ホスト変数の定義終了 */
/************************/

(1) SQL記述子域

(2) 動的パラメタ指定

(3) 相手指定

備考.この応用プログラムの実行が正常に終了したときの出力例のイメージを以下に示します。ゴシック体の文字列が入力されたものとします。

実行する動的SELECT文を指定してください
 SELECT * FROM 在庫管理.在庫表 WHERE 在庫数量 < ?

在庫数量の値を指定してください

 10

製品番号 -> 212  製品名 -> テレビ  在庫数量 -> 0  倉庫番号 -> 2
製品番号 -> 215  製品名 -> ビデオ  在庫数量 -> 5  倉庫番号 -> 2
製品番号 -> 226  製品名 -> 冷蔵庫  在庫数量 -> 8  倉庫番号 -> 1

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

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