プライマリ・コンテンツに移動
Pro*C/C++プログラマーズ・ガイド
12c リリース1(12.1)
B71397-03
目次へ移動
目次
索引へ移動
索引

前
次

暗黙的なバッファ済INSERTの使用について

パフォーマンスを高めるために、Pro*C/C++アプリケーション開発者は、埋め込んだSQL文のホスト配列を参照できます。これにより、データベースへの1回のラウンドトリップでSQL文の配列を実行できます。配列の実行によってパフォーマンスが大幅に向上するにもかかわらず、ANSI規格ではないため、この機能を使用しない開発者もいます。たとえば、Oracle製品で配列の実行を使用するように記述されたアプリケーションは、IBMのプリコンパイラを使用してプリコンパイルすることはできません。

対処方法として、バッファ済INSERT文を使用すると、ANSI規格の埋込みSQL構文を保持しながらパフォーマンスを向上させることができます。

コマンドライン・オプション「max_row_insert」は、INSERT文の実行前にバッファする行の数を制御します。このオプションのデフォルトは0で、機能は無効化されています。この機能を有効化するには、0よりも大きい任意の数を指定します。

挿入バッファを有効化すると、プリコンパイラのランタイムが対応するカーソルにフラグを付け、次を実行します。

新しい埋込みSQL文が実行され、バッファ挿入文がフラッシュされる場合、次のことが実行されます。

アプリケーションには、標準のプリコンパイラ・エラー・メカニズム(Pro*Cのsqlcaなど)を介して、エラーが知らされます。

「implicit_svpt」オプションは、新しくバッチ処理された挿入を開始する前に、暗黙的なセーブポイントを設定するかどうかを制御します。

バッファ済INSERT中に発生する可能性のあるエラーの一部を次に示します。

例8-2 表へのバッファ行の挿入

このプログラムでは、EMP表に行のLOOPCNT数を挿入します。loop counter=5の場合、このプログラムは無効なempnoの挿入を試行します。max_row_insertオプションを使用しないと、プログラムでは無効な行を除くすべての行が挿入されます。max_row_insertオプションをLOOPCNTに設定すると、最初の4行のみが挿入されます。

max_row_insertオプションを使用すると、間違った文が削除されるときに、プログラムは配列INSERTプログラムと同様に動作します。

/* 
 * bufinsdemo.pc 
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlda.h>
#include <sqlcpr.h>
#include <sqlca.h>

/* Number of rows to be inserted into the table */
#define LOOPCNT 100

/* Define a host structure
   for inserting data into the table 
   and for fetching data from the table */
struct emprec
{
  int empno;
  varchar ename[10];
  varchar job[9];
  int mgr;
  char hiredate[10];
  float sal;
  float comm;
  int deptno;
};
typedef struct emprec buffinstyp;

/* Function prototypes */
void sql_error();
void insertdata();
void fetchdata();
void printempdata(buffinstyp);

void main()
{

  exec sql begin declare section;
    char *uid = "scott/tiger";
  exec sql end declare section;

  exec sql whenever sqlerror do sql_error();
  exec sql connect :uid;

  printf("\nInserting %d rows into EMP table.\n", LOOPCNT);
  insertdata();
  printf("\nFetching inserted data from EMP table.\n");
  fetchdata();

  exec sql delete from emp where empno < 1000;

  exec sql commit work release;
  exit(EXIT_SUCCESS);
}

/* Inserting data into the table */
void insertdata() 
{
  int i, cnt;
  char *str;
  buffinstyp emp_in;

  /* To store temporary strings */
  str = (char *)malloc (25 * sizeof(char));

  /*
   * When max_row_insert option is set to LOOPCNT and when the errorneous
   * statement is removed, all the rows will be inserted into the database in
   * one stretch and hence maximum performance gain will be achieved.
 */
  for (i = 1; i <= LOOPCNT; i++)
  {
    if (i != 5)
      emp_in.empno = i;
    else
    /* Errorneous statement. In emp table, empno is defined as number(4). */
      emp_in.empno = 10000;

    sprintf(str, "EMP_%03d", i);
    strcpy (emp_in.ename.arr, str);
    emp_in.ename.len = strlen (emp_in.ename.arr);
    sprintf(str, "JOB_%03d", i);
    strcpy (emp_in.job.arr, str);
    emp_in.job.len = strlen (emp_in.job.arr);
    emp_in.mgr = i+1001;
    sprintf(str, "%02d-MAY-06", (i%30));
    strcpy (emp_in.hiredate, str);
    emp_in.sal = (i) * 10;
    emp_in.comm = (i) * 0.1;
    emp_in.deptno = 10;

    exec sql insert into emp values (:emp_in);
  }

  free (str);

  exec sql commit;

  exec sql select count(*) into :cnt from emp where ename like 'EMP_%';
  printf ("Number of rows successfully inserted into emp table: %d\n", cnt);
}

/* Fetches data from the table*/
void fetchdata()
{
  buffinstyp emp_out;

  /* Declares cursor to fetch only the rows that are inserted */
  exec sql declare c1 cursor for
         select empno, ename, job, mgr, hiredate, sal, comm, deptno
         from emp where ename like 'EMP_%' order by empno;
  
  exec sql open c1;

  exec sql whenever not found do break;
  while(1)
  {
    /* Fetches single row at each call */
    exec sql fetch c1 into :emp_out;
    printempdata(emp_out);
  }
  exec sql whenever not found do sql_error();

  exec sql close c1;
}

/* Prints the fetched employee data */
void printempdata(buffinstyp emp_out)
{
  emp_out.ename.arr[emp_out.ename.len] = '\0';
  emp_out.job.arr[emp_out.job.len] = '\0';
  printf("Empno=%d, Ename=%s, Job=%s, Mgr=%d, Hiredate=%s, Sal=%6.2f,\n"
         "Comm=%5.2f, Deptno=%d\n", emp_out.empno, emp_out.ename.arr,
 emp_out.job.arr, emp_out.mgr, emp_out.hiredate, emp_out.sal,
 emp_out.comm, emp_out.deptno);
}

/* Error handling function. */
void sql_error()
{
   printf("Error %s\n", sqlca.sqlerrm.sqlerrmc);
   printf(" Rows Processed: %d\n", sqlca.sqlerrd[2]);
   printf(" Rows Rolled Back: %d\n", sqlca.sqlerrd[0]);
}