ページの先頭行へ戻る
Symfoware Server V10.0.0/V10.0.1 アプリケーション開発ガイド(埋込みSQL編)

A.1 可変長文字列のデータ操作例

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

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

アプリケーション中に以下のように宣言します。
  VARCHAR hcomp_word[13];

            ↓コンパイル時に構造体に変換します。

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

SolarisLinuxプログラムの処理概要を図A.1 可変長文字列のデータ操作の概要に示します。

SolarisLinux図A.1 可変長文字列のデータ操作の概要

(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    htel_number[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(htel_number,'\0',sizeof(htel_number));                   …… (9)
            memset(hlocation,'\0',sizeof(hlocation));                     …… (10)

            EXEC SQL FETCH CSR1 INTO :hnumber,:hcompany,:htel_number,:hlocation;  (11)

            printf("\n取引先番号  会社名                電話番号      所在地\n");
            printf("%010ld  %-20s  %-12s  %-20s\n"                         …… (12)
                            ,hnumber,hcompany,htel_number,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”をNULL文字で初期化します。

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

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

(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プログラムの処理概要を図A.2 可変長文字列のデータ操作の概要に示します。

Windows図A.2 可変長文字列のデータ操作の概要

(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 htel_number[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';
                        htel_number[12] = '\0';
                        hlocation[20] = '\0';
                        for(count=0;;count++) {
                            EXEC SQL FETCH CSR1                           …… (9)
                                INTO :hnumber,:hcompany,:htel_number,:hlocation;
                            wsprintf( hbuff[count],"%031d  %-20s  %-12s  %-20s",
                                      hnumber,(char far*)hcompany,        …… (10)
                                      (char far*)htel_number, (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) すべてのコネクションを切断します。