ODBCでのデータベース操作

TimesTenでODBCを使用するための基本的な方法を示します。

SQL文を実行するODBC関数

SQLExecuteおよびSQLExecDirect ODBC関数は、SQL文を実行するために使用します。

  • SQLExecute: SQLPrepareで準備されている文を実行します。実行結果を使用してアプリケーションが実行された後、その結果を破棄して、別のパラメータ値でSQLExecuteを再実行することができます。

    通常、バインド・パラメータを使用するDML文または複数回実行される文に使用します。

  • SQLExecDirect: 文を準備して実行します。

    通常、DDL文、または数回のみ実行される、バインド・パラメータを使用しないDML文に使用します。

これらの関数の詳細は、ODBC APIのリファレンス・マニュアルを参照してください。

ODBCでの問合せの準備と実行およびカーソルの操作の手順

問合せの準備と実行、およびカーソルの操作に使用するODBC関数を示します。

ノート:

TimesTenでは、コミットやロールバックなど、トランザクションを終了する操作は、接続と関連付けられているすべてのカーソルをクローズします。

ODBCでは、カーソルは必ず結果セットに関連付けられています。この関連付けはODBCドライバによって行われます。アプリケーションで、「ODBC 3.5のSQLSetStmtAttrおよびSQLGetStmtAttrでの属性サポート」に記載されているSQLSetStmtAttr属性を使用して、一度にフェッチする行の数など、カーソル特性を制御できます。問合せを実行する場合のステップは、通常は次のとおりです。

  1. SQLPrepareを使用して、SELECT文を実行するための準備をします。
  2. SQLBindParameter(文にパラメータが含まれている場合)を使用して、各パラメータをアプリケーション・アドレスにバインドします。「SQLBindParameter関数」を参照してください。
  3. SQLBindColをコールして結果の列に記憶域およびデータ型を割り当て、列の結果をアプリケーション内のローカル変数記憶域にバインドします。
  4. SQLExecuteをコールして、SELECT文を実行します。「SQL文を実行するODBC関数」を参照してください。
  5. SQLFetchをコールして結果をフェッチします。文ハンドルを指定します。
  6. SQLFreeStmtをコールして文ハンドルを解放します。文ハンドルおよびSQL_CLOSESQL_DROPSQL_UNBINDまたはSQL_RESET_PARAMSのいずれかを指定します。

これらのODBC関数の詳細は、ODBC APIのリファレンス・マニュアルを参照してください。この章全体とTimesTenサンプル・アプリケーションでは例をいくつか示しています。「TimesTenクイック・スタートおよびサンプル・アプリケーションについて」を参照してください。

ノート:

デフォルトでは(接続属性がPrivateCommands=0のとき)、TimesTenは接続間で準備済の文を共有するため、共有以降は複数の接続で同じ文の準備が迅速に実行されます。

ODBCでの表の作成

ODBCで表を作成できます。

次の例では、CustIDおよびCustNameという2つの列がある、NameIDという表を作成します。この表では、名前(文字)が識別子(整数)にマップされます。

#include <timesten.h>
SQLRETURN rc;
SQLHSTMT hstmt;
...
rc = SQLExecDirect(hstmt, (SQLCHAR*)
     "CREATE TABLE NameID (CustID INTEGER, CustName VARCHAR(50))",
     SQL_NTS);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
     ... /* handle error */

ODBCでの問合せの準備と実行

次の例では、問合せを準備して実行します。

わかりやすくするために、エラーのチェックは省略してあります。前述のODBC関数以外に、この例では、SQLNumResultColsを使用して結果セット内の列数を返し、SQLDescribeColを使用して結果セットの1つの列の記述(列名、型、精度、スケールおよびNULL値可能)を返し、SQLBindColを使用して記憶域およびデータ型を結果セット内の列に割り当てます。これらすべての関数の詳細は、ODBC APIのリファレンス・マニュアルを参照してください。

#include <timesten.h>

SQLHSTMT hstmt;
SQLRETURN rc;
int i;
SQLSMALLINT numCols;
SQLCHAR colname[32];
SQLSMALLINT colnamelen, coltype, scale, nullable;
SQLULEN collen [MAXCOLS];
SQLLEN outlen [MAXCOLS];
SQLCHAR* data [MAXCOLS];

/* other declarations and program set-up here */

/* Prepare the SELECT statement */
rc = SQLPrepare(hstmt,
(SQLCHAR*) "SELECT * FROM EMP WHERE AGE>20",
SQL_NTS);
/* ... */

/* Determine number of columns in result rows */
rc = SQLNumResultCols(hstmt, &numCols);

/* ... */

/* Describe and bind the columns */
for (i = 0; i < numCols; i++) {
    rc = SQLDescribeCol(hstmt,
         (SQLSMALLINT) (i + 1),
         colname,(SQLSMALLINT)sizeof(colname), &colnamelen, &coltype, &collen[i],
         &scale, &nullable);

    /* ... */

   data[i] = (SQLCHAR*) malloc (collen[i] +1);  //Allocate space for column data.
   rc = SQLBindCol(hstmt, (SQLSMALLINT) (i + 1),
                   SQL_C_CHAR, data[i],
                   COL_LEN_MAX, &outlen[i]);

   /* ... */

}
/* Execute the SELECT statement */
rc = SQLExecute(hstmt);

/* ... */

/* Fetch the rows */
if (numCols > 0) {
  while ((rc = SQLFetch(hstmt)) == SQL_SUCCESS ||
          rc == SQL_SUCCESS_WITH_INFO) {
    /* ... "Process" the result row */
  } /* end of for-loop */
  if (rc != SQL_NO_DATA_FOUND)
    fprintf(stderr,
            "Unable to fetch the next row\n");

/* Close the cursor associated with the SELECT statement */
  rc = SQLFreeStmt(hstmt, SQL_CLOSE);
}

ODBCでのデータベースに対する変更のコミット

データベースに対する変更を自動コミットするか手動でコミットすることができます。自動コミットを無効にして手動でコミットすることもできます。

実行したDML変更(更新、挿入または削除)が自動的にコミットされるよう、自動コミットはデフォルトで有効になっています(ODBCの指定に従って)。ただし、この機能を無効にして、変更を明示的にコミット(またはロールバック)することをお薦めします。これを設定するには、次のようにSQLSetConnectOptionコールでSQL_AUTOCOMMITオプションを使用します。

rc = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);

自動コミットが無効になっている場合は、次のコミットの例のように、SQLTransact ODBC関数を使用してトランザクションをコミットまたはロールバックできます。

rc = SQLTransact(henv, hdbc, SQL_COMMIT);

これらの関数の詳細は、ODBC APIのリファレンス・マニュアルを参照してください。『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』トランザクションの概要を参照してください。

ノート:

  • 自動コミット・モードは、SQLExecuteまたはSQLExecDirectで実行されるトップレベルの文にのみ適用されます。文の内部での実行内容は認識されないため、ネストされた処理の中間自動コミットの機能はありません。

  • 接続時のすべてのオープン・カーソルは、TimesTenでのトランザクションのコミットまたはロールバック時にクローズされます。

  • SQLRowCount関数を使用すると、SQL処理に関する情報が返されます。UPDATEINSERTおよびDELETE文の場合、出力の引数によって、影響を受けた行数が返されます。「キャッシュ・グループに関する情報の取得」を参照してください。SQLRowCountおよびその引数の全般的な情報については、ODBC APIのリファレンス・マニュアルを参照してください。

この例では、選択した従業員の昇給を行う文を準備して実行した後、手動で変更をコミットします。自動コミットが事前に無効にされていることを前提としています。

update_example(SQLHDBC hdbc)
{
  SQLCHAR*      stmt_text;
  SQLHSTMT      hstmt;
  SQLINTEGER    raise_pct;
  char          hiredate_str[30];
  SQLLEN        hiredate_len;
  SQLLEN        numrows;
 
  /* allocate a statement handle */
  SQLAllocStmt(hdbc, &hstmt);
 
  /* prepare an update statement to give raises to employees hired before a
   * given date */
  stmt_text = (SQLCHAR*)
    "update employees "
    "set salary = salary * ((100 + :raise_pct) / 100.0) "
    "where hire_date < :hiredate";
  SQLPrepare(hstmt, stmt_text, SQL_NTS);
 
  /* bind parameter 1 (:raise_pct) to variable raise_pct */
  SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG,
                   SQL_DECIMAL, 0, 0, (SQLPOINTER)&raise_pct, 0, 0);
 
  /* bind parameter 2 (:hiredate) to variable hiredate_str */
  SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR,
                   SQL_TIMESTAMP, 0, 0, (SQLPOINTER)hiredate_str,
                   sizeof(hiredate_str), &hiredate_len);
 
  /* set parameter values to give a 10% raise to employees hired before
   * January 1, 1996. */
  raise_pct = 10;
  strcpy(hiredate_str, "1996-01-01");
  hiredate_len = SQL_NTS;
 
  /* execute the update statement */
  SQLExecute(hstmt);
 
  /* print the number of employees who got raises  */
  SQLRowCount(hstmt, &numrows);
  printf("Gave raises to %d employees.\n", numrows);
 
  /* drop the statement handle */
  SQLFreeStmt(hstmt, SQL_DROP);

  /* commit the changes */
  SQLTransact(henv, hdbc, SQL_COMMIT);

}