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

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

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

データの取り出しを連続的に行う場合には、動的SELECT文を準備して実行します。SQLDA構造体を使用して、動的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、SQLPRECISION、SQLSCALEの値)を取得します。

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

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

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

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

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

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

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

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


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

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