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

3.1.3 ホスト変数および標識変数の指定方法

ホスト変数は、アプリケーションとデータベースの間でデータの受渡しをするのに使用する変数です。SQL文中でホスト変数と対にして指定し、データの内容がNULL値かどうかを表すために使用する変数を、標識変数と呼びます。アプリケーションで参照するデータをデータベースから取り出す場合、標識変数には、取り出したデータがNULL値かどうかを表す情報が設定されます。逆に、アプリケーションで設定したデータをデータベースに格納する場合には、標識変数には、格納するデータがNULL値かどうかを表す情報を設定しておきます。標識変数は、埋込みSQL宣言節で宣言します。宣言の記述方法はホスト変数と同じです。なお、標識変数のデータ型はSQLのSMALLINTに対応するデータ型であることが必要です。

参照

各ホスト言語でのデータ型と、SQLのデータ型との対応については、“SQLリファレンス”を参照してください。

ホスト変数および標識変数をSQL文中に指定する場合には、変数の前にコロン“:”を付けて指定します。以下にその指定例を示します(ゴシック部がホスト変数または標識変数です)。ただし、SQL文以外の、C言語のステートメント中では、一般のC言語の変数と同じで、コロン“:”は付けません。

標識変数には、SQL文の処理結果が以下のように格納されます。

なお、標識変数を指定していない場合、取り出すデータがNULL値になると、SQL文の処理はエラーになります。

1

ホスト変数の指定例

STOCKおよびHOUSEをホスト変数、QFLAGをSTOCKの標識変数、そして、WFLAGをHOUSEの標識変数として指定します。SQL文中にホスト変数および標識変数を指定する場合は、コロン“:”を付けます。

EXEC SQL SELECT 在庫数量,倉庫番号
     INTO :STOCK  INDICATOR :QFLAG,
          :HOUSE  INDICATOR :WFLAG
      FROM 在庫表 WHERE  製品番号 = 110;

2

SQL文以外のC言語のステートメント上のホスト変数の指定例

STOCKをホスト変数、QFLAGをSTOCKの標識変数として使用しています。C言語のステートメントでは、これらの変数にコロン“:”は付けません。

EXEC SQL FETCH CU1 INTO :STOCK INDICATOR :QFLAG;
if( QFLAG == -1) goto p_null ;
if( STOCK == 0) goto p_loop ;

ホスト変数を使用する場合の注意事項

文字列型または各国語文字列型の場合、NULL文字(\0)はデータ受渡しの対象にはなりません。そのため、アプリケーションで文字列の終わりを認識するような処理を行う場合、NULL文字を設定しなければなりません。以下に例を示します。

SQLSTATE[5]='\0';
printf( "SQLSTATE:%s\n" , SQLSTATE );

ホスト変数へ入出力するデータの文字コード系の考慮

ホスト変数へ入出力するデータの文字コード系がSymfoware/RDBの文字コード系と異なる場合は、そのホスト変数に格納するデータの文字コード系を、クライアント用の動作環境ファイルまたは環境変数に設定します。

以下に、ホスト変数へ入出力するデータの文字コード系がSymfoware/RDBの文字コード系と異なる場合の例、および、ホスト変数へ入出力するデータの文字コード系とSymfoware/RDBの文字コード系が同じ場合の例を示します。

1

ホスト変数へ入出力するデータの文字コードとSymfoware/RDBの文字コード系が異なる場合

以下の例では、Symfoware/RDBの文字コード系がシフトJISコード、また、SELECT文(1)でホスト変数に格納されたデータの文字コード系がUNICODEであるとします。そして、このデータを格納するデータベースの文字コード系はUNICODEであるとします。

この場合、クライアント用の動作環境ファイルまたは環境変数には、ホスト変数に格納されているデータがUNICODEであることを示すパラメタを設定します。

参照

設定するパラメタについての詳細は、“アプリケーション開発ガイド(共通編)の“クライアント用の動作環境ファイル”を参照してください。

こうすることによって、サーバでのコード変換の必要がなくなります。

EXEC SQL BEGIN DECLARE SECTION;
  char    SQLSTATE[6];
  char    SQLMSG[256];
           :
  char CHARACTER SET NCHAR    H1[10];
EXEC SQL END DECLARE SECTION;
           :
memset(H1,'\0',sizeof(H1));
EXEC SQL SELECT COL1 INTO :H1 FROM S1.T0 WHERE COL0=3;    …… (1)
EXEC SQL INSERT INTO S1.T1 VALUES(3,:H1);                 …… (2)

(1) データベースよりUNICODEなどのSymfoware/RDBの文字コード系と異なるコードのデータが取得できます。

(2) 上記の単一行SELECT文で取得したデータのコードのまま、INSERT文が実行できます。このように、アプリケーションにおいて、Symfoware/RDBの文字コード系と異なるコード系のデータが操作可能です。


2

ホスト変数へ入出力するデータの文字コードがSymfoware/RDBの文字コード系と同じ場合

以下の例では、Symfoware/RDBの文字コード系がシフトJISコードであるとします。この場合、ホスト変数に入出力するデータの文字コード系はシフトJISコードになります。

EXEC SQL BEGIN DECLARE SECTION;
  char    SQLSTATE[6];
  char    SQLMSG[256];
           :
  char CHARACTER SET NCHAR    H1[10];
EXEC SQL END DECLARE SECTION;
           :
memset(H1,'\0',sizeof(H1));
memcpy(H1,"日本語",6);                            …… (1)
EXEC SQL INSERT INTO S1.T1 VALUES(:H1);           …… (2)

(1) Symfoware/RDBの文字コード系の“日本語”がホスト変数H1に格納されます。

(2) Symfoware/RDBの文字コード系の“日本語”でINSERT文を実行します。このように、Symfoware/RDBの文字コード系を使用してデータ操作を行う場合に適しています。

マルチスレッド環境でのホスト変数の宣言

マルチスレッド環境で実行するアプリケーションでは、ホスト変数にはauto変数を使用することを推奨します。extern変数およびstatic変数などを使用した場合は、スレッド間でホスト変数が共有されるため、複数のスレッドから同時にデータベースをアクセスすると、参照および更新が正しくできない場合があります。extern変数およびstatic変数などを使用する場合は、セマフォを利用するなどして、並列に動作するスレッド間の排他制御を考慮したアプリケーションを作成してください。

参照

セマフォの詳細については、OSのシステム関数について説明されているマニュアルを参照してください。

long long型および、8バイトで実装されるlong型のホスト変数の利用について

long型は、コンパイラにより、4バイトになる場合と8バイトになる場合があります。

8バイトで実装されるlong型および、long long型のホスト変数を利用した場合、ホスト変数には最大20桁のデータを代入できます。

一方、データベースで扱えるデータの最大桁数は18桁です。

このため、19桁以上の値を代入したホスト変数をSQL文中の検索条件などで利用した場合、データベースアクセス時にエラーとなります。検索条件などに19桁以上の値を指定することで、データベースアクセス時のエラーが発生することを防ぎたい場合は、アプリケーション中で事前にホスト変数の値が18桁以下であるかをチェックしてください。

条件値以下のすべての値を取り出すための条件値が18桁を超えている場合に、アプリケーションにて条件値を18桁の最大数に変更するプログラム例を以下に示します。

下記の表にアクセスし、列VALUE1の値が検索条件の値以下の行の列CODE1をすべて取り出す例を示します。

スキーマ:SCH1

表:TBL1

列:CODE1:SMALLINT UNIQUE NOT NULL

    VALUE1:DECIMAL(18,0)

18桁以下の場合に、真を返却するマクロ(sample1.h)

#define CheckGetPrecision18(data) ((long long)(data) <= 999999999999999999LL ) 

検索条件の組立て(C言語)

short gyoumu1() {
  long long condition;
  short code[65536];
  int count;

  condition = 123456789012345678LL;  /*実際は、画面入力などを元にデータを組み立てます。*/
  count = dba_KINGAKU_SETTEI( code , condition );
  return 0;
}

データベースアクセスアプリケーション(SQL埋込みCプログラム)

#include “sample1.h”

short dba_KINGAKU_SETTEI( short *para1 , long long para2 ) {
  EXEC SQL BEGIN DECLARE SECTION;
     char SQLSTATE[6];
     char SQLMSG[256];
     short code1;
     long long  condition;
  EXEC SQL END DECLARE SECTION;

  int count;

  EXEC SQL WHENEVER SQLERROR GOTO :ERROR;
  EXEC SQL WHENEVER NOT FOUND GOTO :NOTFOUND;

  condition = para2;

/* データベースの対応カラムの精度と比較 */
  if ( !CheckGetPrecision18( condition ) ) { 
     condition  = 999999999999999999LL; /* 条件値を18桁の最大値に変更 */
  }

/* カーソル宣言 */
  EXEC SQL DECLARE CUR1 CURSOR FOR SELECT CODE1 
     FROM SCH1.TBL1 WHERE VALUE1 <= :condition;
  EXEC SQL OPEN CUR1;

  for ( count = 0 ;; count++ ) {
    EXEC SQL FETCH CUR1 INTO :code1;
    para1[count] = code1;
  } 

NOTFOUND:
  EXEC SQL CLOSE CUR1;
  return(count);

ERROR:
  EXEC SQL CLOSE CUR1;
  return(-1);
}