Symfoware(R) Server RDBユーザーズガイド 応用プログラム開発編 - FUJITSU -
目次 索引 前ページ次ページ

上へ第2章 データベースを処理する応用プログラムの開発の概要
上へ2.1 SQL埋込みCプログラムの作成方法

2.1.6 可変長文字列のデータ操作

ここでは、ホスト変数の可変長文字列をCプログラムで操作するプログラミング例を説明します。ホスト変数の可変長文字列をCプログラムで操作する場合は、文字列の長さが必要です。このため、翻訳時には、可変長文字列を文字列の長さと文字列を持つ構造体形式に変換します。Cプログラムは、変換された構造体の変数でデータ操作を行います。

図:可変長文字列を構造体形式に変換した例に可変長文字列を構造体形式に変換した例を示します。

UNIX系の場合におけるプログラムの処理概要を図:可変長文字列のデータ操作の概要に、プログラミング例を図:可変長文字列のデータ操作のプログラミング例に示します。

Windowsの場合におけるプログラムの処理概要を図:可変長文字列のデータ操作の概要に、プログラミング例を図:可変長文字列のデータ操作のプログラミング例に示します。

[図:可変長文字列を構造体形式に変換した例]

応用プログラム中に以下のように宣言します。
  VARCHAR hcomp_word[13];

            ↓翻訳時に構造体に変換します。

  struct{
          short   sqllen;
          char    sqlvar[13];
  } hcomp_word;

[UNIX系の場合]

[図:可変長文字列のデータ操作の概要]

image

(1) 電話番号の市外局番を、ホスト変数の可変長文字列に対話で入力します。

(2) CONNECT文により、データベース“DB01”の存在するサーバとコネクションを接続します。

(3) カーソル操作により、取引会社表から入力された市外局番に該当する取引先会社のデータを検索します。

(4) 取引先会社のデータを端末に出力します。

(5) DISCONNECT文により、データベース“DB01”の存在するサーバとのコネクションを切断します。

[図:可変長文字列のデータ操作のプログラミング例]

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


EXEC SQL BEGIN DECLARE SECTION;
        char    SQLSTATE[6];
        char    SQLMSG[256];
        VARCHAR hcomp_word[13];                                          …… (1)
        long    hnumber;
        char CHARACTER SET NCHAR  hcompany[21];
        char    harea_code[13];
        char CHARACTER SET NCHAR  hlocation[21];
EXEC SQL END   DECLARE SECTION;

void putmsgx(void);

main(void){
            short   execute;
            short   count;

    EXEC SQL DECLARE 取引先会社 TABLE ON BUSINESS;                          …… (2)
    EXEC SQL DECLARE CSR1 CURSOR FOR
                          SELECT * FROM 取引先会社
                          WHERE 電話番号 LIKE :hcomp_word;              …… (3)

    printf("入力された市外局番に該当する取引先会社のデータを取り出します.\n");
    for(;;){
            printf("市外局番を入力してください >> ");
            gets(hcomp_word.sqlvar);                                 …… (4)
            printf("\n");
            printf("市外局番\"%s\"のデータでよろしいですか?\n",hcomp_word.sqlvar);
            printf("よろしかったら(Y/y)を入力してください >>");
            execute=getchar();
            if(execute=='Y' || execute=='y'){
                    break;

            printf("\n");
    }

    printf("\n");
    strcat(hcomp_word.sqlvar,"%");
    hcomp_word.sqllen = strlen(hcomp_word.sqlvar);                 …… (5)

    EXEC SQL WHENEVER SQLERROR GOTO :CONNECT_ERROR;

    EXEC SQL CONNECT TO 'DB01';                                           …… (6)

    EXEC SQL WHENEVER SQLERROR GOTO :STM_ERROR;
    EXEC SQL WHENEVER NOT FOUND GOTO :NOT_FOUND_ERROR;

    EXEC SQL OPEN CSR1;                                                   …… (7)

    for(count=0;;count++)  {
            memset(hcompany,'\0',sizeof(hcompany));                       …… (8)
            memset(harea_code,'\0',sizeof(harea_code));                   …… (9)
            memset(hlocation,'\0',sizeof(hlocation));                     …… (10)
            EXEC SQL FETCH CSR1 INTO :hnumber,:hcompany,:harea_code,:hlocation;  (11)

            printf("\n取引先番号  会社名                市外局番      所在地\n");
            printf("%010ld  %-20s  %-12s  %-20s\n"                         …… (12)
                            ,hnumber,hcompany,harea_code,hlocation);
    }

NOT_FOUND_ERROR:
        if(count != 0)  printf("\n該当データは%d件です.\n",count);         …… (13)
        else                    printf("\n該当データなし\n");
        EXEC SQL WHENEVER SQLERROR CONTINUE;
        EXEC SQL ROLLBACK WORK;                                            …… (14)
        EXEC SQL DISCONNECT 'DB01';                                        …… (15)
        return 0;

STM_ERROR:                                                                 …… (16)
        putmsgx();
        EXEC SQL WHENEVER SQLERROR CONTINUE;
        EXEC SQL ROLLBACK WORK;                                            …… (17)
        EXEC SQL DISCONNECT 'DB01';                                        …… (18)
        return 1;

CONNECT_ERROR:
        putmsgx();                                                         …… (19)
        return 1;
}

void putmsgx( void )  {                                                   …… (20)
    int i;
    for ( i = sizeof(SQLMSG) - 2 ; SQLMSG[i] == ' ' ; i-- );
    SQLMSG[++i] = '\0';
    SQLSTATE[5]='\0';
    printf( "SQLMSG:%s\n" , SQLMSG );
    printf( "SQLSTATE:%s\n" , SQLSTATE );
    return;
}

(1) 市外局番を可変長文字列のホスト変数として定義します。

(2) 取引先会社を表宣言します。

(3) 取引先会社表のすべての列に対するカーソル“CSR1”を宣言します。

(4) 市外局番を対話入力します。市外局番は、可変長文字列変数“hcomp_word”を翻訳時に構造体に変換した変数“hcomp_word.sqlvar”に入力します。

(5) 入力した市外局番の長さを、可変長文字列のホスト変数“hcomp_word”を翻訳時に構造体に変換した長さの変数“hcomp_word.sqllen”に設定します。

(6) データベース“DB01”の存在するサーバとコネクションを接続します。

(7) カーソル“CSR1”をオープンします。

(8) ホスト変数“hcompany”をナル文字で初期化します。

(9) ホスト変数“harea_code”をナル文字で初期化します。

(10) ホスト変数“hlocation”をナル文字で初期化します。

(11) 入力した市外局番と等しい市外局番の行にカーソルを位置づけ、その行を読み込みます。

(12) 読み込んだ行をprintf関数で表示します。

(13) 取引先会社表のデータをすべて検索した場合は、検索結果をprintf関数で表示します。

(14) トランザクションをROLLBACK文により終了します。

(15) データベース“DB01”の存在するサーバとのコネクションを切断します。

(16) SQL文のエラーの場合に、SQLMSGとSQLSTATEの内容を表示します。

(17) SQL文の実行でエラーが発生した場合は、トランザクションをROLLBACK文により終了します。

(18) データベース“DB01”の存在するサーバとのコネクションを切断します。

(19) コネクションでエラーの場合は、SQLMSGとSQLSTATEの内容を表示します。

(20) SQLMSGとSQLSTATEの内容を表示する関数です。

[Windowsの場合]

[図:可変長文字列のデータ操作の概要]

image

(1) CONNECT文により、データベースへコネクションを接続します。

(2) 市外局番を、ホスト変数の可変長文字列に対話で入力します。

(3) カーソル操作により、取引先会社表から入力された市外局番に該当する取引先会社のデータを検索します。

(4) 取引先会社のデータを出力します。

(5) DISCONNECT文により、コネクションを切断します。

[図:可変長文字列のデータ操作のプログラミング例]

EXEC SQL INCLUDE sample3.h;
    :
long FAR PASCAL WsampleWndProc(hWnd, message, wParam, lParam)
    :
{
    FARPROC         lpProcAbout;
    HDC             hDC;
    PAINTSTRUCT     ps;
    EXEC SQL BEGIN DECLARE SECTION;                                        …… (1)
        char SQLSTATE[6];
        char SQLMSG[256];
        long hnumber;
        char CHARACTER SET IS NCHAR hcompany[21];
        char harea_code[13];
        char CHARACTER SET IS NCHAR hlocation[21];
        VARCHAR hcomp_word[13];                                            …… (2)
    EXEC SQL END DECLARE SECTION;
        char msgno[5];
        short i;

    EXEC SQL DECLARE  取引先会社 TABLE ON BUSINESS;                         …… (3)
    EXEC SQL WHENEVER SQLERROR GOTO :err_exit;
        switch (message){
            case WM_CREATE:
                SQLMSG[255] = '\0';
                EXEC SQL CONNECT TO DEFAULT;                                …… (4)
                DFlag2 = FALSE;
                count = 0;
                break;
            case WM_COMMAND:
                switch (wParam) {
                    case WIN_END:
                         PostMessage(hWnd, WM_CLOSE, 0, 0 );
                        break;
                    case WIN_INPUT:                                        …… (5)
                        lpProcAbout = MakeProcInstance(InputData, hInst); 
                        DFlag = DialogBox(hInst,"InputData",hWnd,lpProcAbout);
                        FreeProcInstance(lpProcAbout);
                        break;
                    case WIN_EXEC:                                         …… (6)
                        count = 0;
                        InvalidateRect(hWnd,NULL,TRUE);
                        if( DFlag == FALSE ){
                            break;
                        }
                        EXEC SQL DECLARE CSR1 CURSOR FOR                     …… (7)
                            SELECT * FROM 取引先会社
                                  WHERE 電話番号 LIKE :hcomp_word;
                        EXEC SQL OPEN CSR1;                                 …… (8)
                        EXEC SQL WHENEVER NOT FOUND GOTO :atend;
                        hcompany[20] = '\0';
                        harea_code[12] = '\0';
                        hlocation[20] = '\0';
                        for(count=0;;count++) {
                            EXEC SQL FETCH CSR1                           …… (9)
                                INTO :hnumber,:hcompany,:harea_code,:hlocation;
                            wsprintf( hbuff[count],"%031d  %-20s  %-12s  %-20s",
                                      hnumber,(char far*)hcompany,        …… (10)
                                      (char far*)harea_code, (char far*)hlocation);
                           DFlag2 = TRUE;
                        }

    atend:
                        EXEC SQL CLOSE CSR1;                               …… (11)
                        EXEC SQL COMMIT WORK;                             …… (12)
                        break;

                    default:
                        break;
                }
                break;
            case WM_PAINT:
                if (DFlag2==TRUE) {
                    hDC = BeginPaint (hWnd, &ps);
                    for( i = 0; i < count; i++ ){
                        TextOut (hDC,10,10+(i*20),
                                        (LPSTR)hbuff,lstrlen((LPSTR)hbuff));
                        EndPaint(hWnd, &ps);
                    }
                    UpdateWindow(hWnd);
                }
                break;
            case WM_DESTROY:
                EXEC SQL DISCONNECT ALL;                                   …… (13)
                PostQuitMessage(0);
                return(0);
    err_exit:
                memset(mes,'\0',512);
                SQLSTATE[5]='\0';
                SQLMSG[255]='\0';
                delspace( SQLMSG );
                wsprintf(mes,"SQL 文実行失敗\nSQLSTATE=%s\nSQLMSG=%s\n",  …… (14)
                    (LPSTR)SQLSTATE,(LPSTR)SQLMSG);
                MessageBox( 0, (LPSTR)mes, "MESSAGE", MB_OK );

                memcpy( msgno , SQLMSG+3 , 4 );
                msgno[4] = '\0';
                WinHelp( hWnd, HLP_PASS, HELP_CONTEXT, (DWORD)atol(msgno) );    (15)

                EXEC SQL WHENEVER SQLERROR CONTINUE;
                EXEC SQL ROLLBACK WORK;                                   …… (16)
                EXEC SQL DISCONNECT ALL;                                   …… (17)
                PostQuitMessage(0);
                return(0);

            default:
                break;
        }
    return (DefWindowProc(hWnd, message, wParam, lParam));
}
    :

(1) ホスト変数を宣言します。

(2) 市外局番が格納される可変長文字列のホスト変数を宣言します。

(3) 取引先会社を表宣言します。

(4) 動作環境ファイルのDEFAULT_CONNECTIONで指定したサーバとコネクションを接続します。

(5) 選択されたメニューに従って、処理を行います。ここでは、市外局番を入力するダイアログボックスを表示し、対話処理で入力します。“InputData”は、可変長文字列変数“hcomp_word”をプレコンパイラが構造体に変換した変数“hcomp_word.sqlvar”および“hcomp_word.sqllen”にデータとその長さを入力する関数です。

(6) 選択されたメニューに従って、処理を行います。ここでは、SQL文の実行を開始します。

(7) 取引先会社表のすべての列に対するカーソル“CSR1”を宣言します。

(8) カーソル“CSR1”をオープンします。

(9) 入力した市外局番と等しい市外局番の行にカーソルを位置づけ、その行を読み込みます。

(10) 検索結果を画面に出力します。

(11) カーソル“CSR1”をクローズします。

(12) トランザクションをCOMMIT文により終了します。

(13) すべてのコネクションを切断します。

(14) SQL文の実行でエラーが発生した場合は、SQLSTATEとSQLMSGの内容を出力します。

(15) エラーに対するヘルプメッセージを表示します。

(16) SQL文の実行でエラーの場合は、トランザクションをROLLBACK文により終了します。

(17) すべてのコネクションを切断します。


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

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