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

第7章 アプリケーションの実行時に動的SQL文を実行する方法> 7.2 SQL文を動的に変更して実行する> 7.2.2 SQL文の準備とSQL記述子域の操作

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

データの取り出しを連続的に行う場合には、動的SELECT文を準備して実行します。SQL記述子域を使用して、動的SELECT文を実行するアプリケーションの例を以下に示します。

端末から入力した動的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に実行結果を取り出す相手指定のデータ型を設定します。

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

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

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

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

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

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

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

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

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


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

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