日本語PDF

E Oracle ODBC Driverの使用

この付録では、Oracle ODBC Driverの使用方法について説明します。

内容は次のとおりです。

関連項目:

ODBCドライバの動作保証情報は、各プラットフォームの『Oracle Databaseインストレーション・ガイド』を参照してください。

E.1 サポートされていないOracle ODBCの機能

Oracle ODBC Driverは次のOracle ODBC 3.0機能をサポートしていません。

  • 間隔データ型

  • SQL_C_UBIGINTおよびSQL_C_SBIGINT Cデータ型識別子

  • 共有接続

  • 共有環境

  • SQLSetConnectAttrSQL_LOGIN_TIMEOUT属性

  • 期限切れパスワード・オプション

Oracle ODBC Driverは、次の表に示すSQL関数をサポートしていません。

文字列関数 数値関数 時間関数、日付関数および間隔関数

BIT_LENGTH

ACOS

CURRENT_DATE

CHAR_LENGTH

ASIN

CURRENT_TIME

CHARACTER_LENGTH

ATAN

CURRENT_TIMESTAMP

DIFFERENCE

ATAN2

EXTRACT

OCTET_LENGTH

COT

TIMESTAMPDIFF

POSITION

DEGREES

RADIANS

RAND

ROUND

E.2 データ型の実装

この項では、DATETIMESTAMPおよび浮動小数点の各データ型について説明します。

DATEおよびTIMESTAMP

OracleのDATEおよびTIMESTAMPデータ型のセマンティクスは、同名のODBCデータ型と必ずしも正確に対応していません。OracleのDATEデータ型には、日付と時間の両方の情報が格納されています。これに対して、SQL_DATEデータ型に格納されているのは、日付情報のみです。OracleのTIMESTAMPデータ型にも日付と時間の情報が格納されていますが、その小数秒の精度は他方に比較して高くなります。Oracle ODBC Driverは、情報が失われるのを防ぐために、OracleのDATE列とTIMESTAMP列の両方のデータ型をSQL_TIMESTAMPとして報告します。同様に、Oracle ODBC DriverはSQL_TIMESTAMPパラメータをOracleのTIMESTAMP値としてバインドします。

関連項目:

パフォーマンスとチューニングに関するDATEおよびTIMESTAMPデータ型の詳細は、DATEおよびTIMESTAMPデータ型を参照してください

浮動小数点データ型

Oracle Database 12cリリース2 (12.2)以上に接続すると、Oracle ODBC Driverは、Oracleの浮動小数点データ型BINARY_FLOATBINARY_DOUBLEをODBCデータ型SQL_REALSQL_DOUBLEにそれぞれマップします。これより前のリリースでは、SQL_REALSQL_DOUBLEがOracleの汎用数値データ型にマップされていました。

E.3 データ型に関する制限事項

Oracle ODBC DriverおよびOracle Databaseには、データ型に関する制限事項があります。次の表に制限事項を示します。

制限されるデータ型 説明

リテラル

Oracle Databaseでは、SQL文のリテラルは4000バイトに制限されています。

SQL_LONGVARCHARおよびSQL_WLONGVARCHAR

Oracleでは、列型がLONGSQL_LONGVARCHARデータは2,147,483,647バイトに制限されます。また、Oracleでは、列型がCLOBSQL_LONGVARCHARデータは4GBに制限されます。これは、クライアント・ワークステーションのメモリーによる制限です。

SQL_LONGVARCHARおよびSQL_LONGVARBINARY

Oracle Databaseで使用できるのは、表ごとに1列のLONGデータ列のみです。LONGデータ型とは、SQL_LONGVARCHAR(LONG)およびSQL_LONGVARBINARY(LONG RAW)です。かわりに、CLOBおよびBLOB列の使用をお薦めします。1つの表で使用できるCLOBおよびBLOBの列数に制限はありません。

E.4 SQLDriverConnect関数の接続文字列の書式

SQLDriverConnect関数は、Oracle ODBC Driverによって実装される関数の1つです。次の表に、SQLDriverConnect関数コールの接続文字列の引数に含めることができるキーワードを示します。

キーワード 意味

DSN

ODBCデータソース名

ユーザー指定名

これは必須のキーワードです。

DBQ

TNSサービス名

ユーザー指定名

これは必須のキーワードです。

UID

ユーザーIDまたはユーザー名

ユーザー指定名

これは必須のキーワードです。

PWD

パスワード

ユーザー指定名

パスワードがない場合はPWD=;と指定します。

これは必須のキーワードです。

DBA

データベース属性

Wは書込みアクセスを意味します。

Rは読取り専用アクセスを意味します。

APA

アプリケーション属性

Tはスレッド・セーフティを有効にすることを意味します。

Fはスレッド・セーフティを無効にすることを意味します。

RST

結果セット

Tは結果セットを有効にすることを意味します。

Fは結果セットを無効にすることを意味します。

QTO

問合せタイムアウト・オプション

Tは問合せタイムアウトを有効にすることを意味します。

Fは問合せタイムアウトを無効にすることを意味します。

CSR

カーソルのクローズ

Tはカーソルのクローズを有効にすることを意味します。

Fはカーソルのクローズを無効にすることを意味します。

BAM

バッチ自動コミット・モード

IfAllSuccessfulは、すべての文が成功した場合のみコミットすることを意味します(古い動作)。

UpToFirstFailureは、最初に失敗した文までコミットすることを意味します。これはODBCバージョン7の動作です。

AllSuccessfulは、成功したすべての文をコミットすることを意味します。

FBS

フェッチ・バッファ・サイズ

ユーザー指定の数値(0バイト以上の値を指定します)。デフォルトは60,000バイトです。

FEN

フェイルオーバー

Tはフェイルオーバーを有効にすることを意味します。

Fはフェイルオーバーを無効にすることを意味します。

FRC

フェイルオーバー再試行数

ユーザー指定の数値。

デフォルトは10です。

FDL

フェイルオーバーの遅延。

ユーザー指定の数値。

デフォルトは10です。

LOB

LOB書込み

TはLOBを有効にすることを意味します。

FはLOBを無効にすることを意味します。

FWC

SQL_WCHAR強制サポート

TForce SQL_WCHARを有効にすることを意味します。

FForce SQL_WCHARを無効にすることを意味します。

EXC

EXEC構文

TEXEC構文を有効にすることを意味します。

FEXEC構文を無効にすることを意味します。

XSM

スキーマ・フィールド

Defaultはデフォルト値が使用されることを意味します。

Databaseはデータベース名が使用されることを意味します。

Ownerは所有者名が使用されることを意味します。

MDI

METADATA IDデフォルトの設定

TSQL_ATTR_METADATA_IDのデフォルト値がSQL_TRUEであることを意味します。

FSQL_ATTR_METADATA_IDのデフォルト値がSQL_FALSEであることを意味します。

DPM

SQLDescribeParamの無効化

TSQLDescribeParamを無効にすることを意味します。

FSQLDescribeParamを有効にすることを意味します。

BTD

TIMESTAMPDATEとしてバインド

TSQL_TIMESTAMPがOracleのDATEとしてバインドされることを意味します。

FSQL_TIMESTAMPがOracleのTIMESTAMPとしてバインドされることを意味します。

NUM

数値の設定

NLSは、グローバリゼーション・サポートの数値の設定が使用されることを意味します(小数点およびグループのセパレータを判断するため)。

E.5 プログラムでのロック・タイムアウトの削減

Oracle Databaseは、トランザクション間のロックの競合が解決されるまで無期限に待機します。ただし、Oracle Databaseがロックの解決を待機する時間は制限できます。制限するには、ODBCのSQLSetStmtAttr関数のコール時にSQL_ATTR_QUERY_TIMEOUT属性を設定してから、データソースに接続します。

E.6 ODBCアプリケーションのリンク

プログラムをリンクする場合は、そのプログラムをDriver Managerライブラリlibodbc.soにリンクする必要があります。

E.7 ROWIDに関する情報の取得

ODBCのSQLSpecialColumns関数は、表内の列に関する情報を返します。Oracle ODBC Driverで使用すると、この関数はOracle表に関連付けられたOracle ROWIDに関する情報を返します。

E.8 WHERE句のROWID

ROWIDは、SQL文のWHERE句で使用できます。ただし、ROWID値はパラメータ・マーカー内に存在している必要があります。

E.9 結果セットの有効化

Oracle参照カーソル(結果セットとも呼ばれます)によって、アプリケーションでは、ストアド・プロシージャとストアド・ファンクションを使用してデータを取得できます。ここでは、参照カーソルを使用してODBCを介して結果セットを有効にする方法を説明します。

  • ストアド・プロシージャをコールするには、ODBC構文を使用する必要があります。システム固有のPL/SQLは、ODBCを介してサポートされていません。次のコード例は、プロシージャまたはファンクションを、パッケージなしでコールする方法、およびパッケージ内でコールする方法を示します。このコード例でのパッケージ名はRSETです。

    Procedure call:
    {CALL Example1(?)}
    {CALL RSET.Example1(?)}
    Function Call:
    {? = CALL Example1(?)}
    {? = CALL RSET.Example1(?)} 
    
  • PL/SQLの参照カーソル・パラメータは、プロシージャのコール時には省略されます。たとえば、プロシージャExample2には4つのパラメータが定義されているとします。パラメータ1と3は参照カーソル・パラメータで、パラメータ2と4は文字列です。コールは、次のように指定されます。

    {CALL RSET.Example2("Literal 1", "Literal 2")}
    

次のサンプル・アプリケーションは、Oracle ODBC Driverを使用して結果セットを返す方法を示します。

/*
* Sample Application using Oracle reference cursors through ODBC
*
* Assumptions:
*
* 1) Oracle Sample database is present with data loaded for the EMP table.
*
* 2) Two fields are referenced from the EMP table, ename and mgr.
*
* 3) A data source has been setup to access the sample database.
*
*
* Program Description:
*
* Abstract:
*
* This program demonstrates how to return result sets using
* Oracle stored procedures
*
* Details:
*
* This program:
* Creates an ODBC connection to the database.
* Creates a Packaged Procedure containing two result sets.
* Executes the procedure and retrieves the data from both result sets.
* Displays the data to the user.
* Deletes the package then logs the user out of the database.
*
*
* The following is the actual PL/SQL this code generates to
* create the stored procedures.
*  
DROP PACKAGE   ODBCRefCur;
CREATE PACKAGE ODBCRefCur AS
     TYPE ename_cur IS REF CURSOR;
     TYPE mgr_cur   IS REF CURSOR;
PROCEDURE EmpCurs(Ename IN OUT ename_cur, Mgr IN OUT mgr_cur, pjob IN VARCHAR2); 

END; 

/
CREATE PACKAGE BODY ODBCRefCur AS
PROCEDURE EmpCurs(Ename IN OUT ename_cur, Mgr IN OUT mgr_cur, pjob IN VARCHAR2)
     AS
       BEGIN
          IF NOT Ename%ISOPEN
          THEN
              OPEN Ename for SELECT ename from emp;
          END IF; 

          IF NOT Mgr%ISOPEN
          THEN
              OPEN Mgr for SELECT mgr from emp where job = pjob;
          END IF;
       END;
END;
/ 


*
*  End PL/SQL for Reference Cursor. 
*/

/*
 * Include Files
 */
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
/*
 * Defines
 */
#define JOB_LEN 9
#define DATA_LEN 100
#define SQL_STMT_LEN 500
/*
 * Procedures
 */
void DisplayError( SWORD HandleType, SQLHANDLE hHandle, char *Module );
/*
 * Main Program
 */
int main()
{
SQLHENV hEnv;
SQLHDBC hDbc;
SQLHSTMT hStmt;
SQLRETURN rc;
char *DefUserName ="jones";
char *DefPassWord ="password";
SQLCHAR ServerName[DATA_LEN];
SQLCHAR *pServerName=ServerName;
SQLCHAR UserName[DATA_LEN];
SQLCHAR *pUserName=UserName;
SQLCHAR PassWord[DATA_LEN];
SQLCHAR *pPassWord=PassWord;
char Data[DATA_LEN];
SQLINTEGER DataLen;
char error[DATA_LEN];
char *charptr;
SQLCHAR SqlStmt[SQL_STMT_LEN];
SQLCHAR *pSqlStmt=SqlStmt;
char *pSalesMan = "SALESMAN";
SQLINTEGER sqlnts=SQL_NTS;
/*
 * Allocate the Environment Handle
 */
rc = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv );
if (rc != SQL_SUCCESS)
{
  printf( "Cannot Allocate Environment Handle\n");
  printf( "\nHit Return to Exit\n");
  charptr = gets ((char *)error);
  exit(1);
}
/*
 * Set the ODBC Version
 */
rc = SQLSetEnvAttr( hEnv,SQL_ATTR_ODBC_VERSION,(void *)SQL_OV_ODBC3,0);
if (rc != SQL_SUCCESS)
{
  printf( "Cannot Set ODBC Version\n");
  printf( "\nHit Return to Exit\n");
  charptr = gets ((char *)error);
  exit(1);
}
/*
 * Allocate the Connection handle
 */
rc = SQLAllocHandle( SQL_HANDLE_DBC, hEnv, &hDbc );
if (rc != SQL_SUCCESS)
{
  printf( "Cannot Allocate Connection Handle\n");
  printf( "\nHit Return to Exit\n");
  charptr = gets ((char *)error);
  exit(1);
}
/*
 * Get User Information
 */
strcpy ((char *) pUserName, DefUserName );
strcpy ((char *) pPassWord, DefPassWord );
/*
 * Data Source name
 */
printf( "\nEnter the ODBC Data Source Name\n" );
charptr = gets ((char *) ServerName);
/*
 * User Name
 */
printf ( "\nEnter User Name Default [%s]\n", pUserName);
charptr = gets ((char *) UserName);
if (*charptr == '\0')
{
  strcpy ((char *) pUserName, (char *) DefUserName );
}
/*
 * Password
 */
printf ( "\nEnter Password Default [%s]\n", pPassWord);
charptr = gets ((char *)PassWord);
if (*charptr == '\0')
{
  strcpy ((char *) pPassWord, (char *) DefPassWord );
}
/*
 * Connection to the database
 */
rc = SQLConnect( hDbc,pServerName,(SQLSMALLINT) strlen((char  *)pServerName),pUserName,(SQLSMALLINT) strlen((char *)pUserName),pPassWord,(SQLSMALLINT) strlen((char *)pPassWord));
if (rc != SQL_SUCCESS)
{
  DisplayError(SQL_HANDLE_DBC, hDbc, "SQLConnect");
}
/*
 * Allocate a Statement
 */
rc = SQLAllocHandle( SQL_HANDLE_STMT, hDbc, &hStmt );
if (rc != SQL_SUCCESS)
{
  printf( "Cannot Allocate Statement Handle\n");
  printf( "\nHit Return to Exit\n");
  charptr = gets ((char *)error);
  exit(1);
}
/*
 * Drop the Package
 */
strcpy( (char *) pSqlStmt, "DROP PACKAGE ODBCRefCur");
rc = SQLExecDirect(hStmt, pSqlStmt, strlen((char *)pSqlStmt));
/*
 * Create the Package Header
 */
strcpy( (char *) pSqlStmt, "CREATE PACKAGE ODBCRefCur AS\n");
strcat( (char *) pSqlStmt, " TYPE ename_cur IS REF CURSOR;\n");
strcat( (char *) pSqlStmt, " TYPE mgr_cur IS REF CURSOR;\n\n");
strcat( (char *) pSqlStmt, " PROCEDURE EmpCurs (Ename IN OUT ename_cur,");
strcat( (char *) pSqlStmt, "Mgr IN OUT mgr_cur,pjob IN VARCHAR2);\n\n");
strcat( (char *) pSqlStmt, "END;\n");
rc = SQLExecDirect(hStmt, pSqlStmt, strlen((char *)pSqlStmt));
if (rc != SQL_SUCCESS)
{
  DisplayError(SQL_HANDLE_STMT, hStmt, "SQLExecDirect");
}
/*
 * Create the Package Body
 */
strcpy( (char *) pSqlStmt, "CREATE PACKAGE BODY ODBCRefCur AS\n");
strcat( (char *) pSqlStmt, " PROCEDURE EmpCurs (Ename IN OUT ename_cur,");
strcat( (char *) pSqlStmt, "Mgr IN OUT mgr_cur, pjob IN VARCHAR2)\n AS\n  BEGIN\n");
strcat( (char *) pSqlStmt, " IF NOT Ename%ISOPEN\n THEN\n");
strcat( (char *) pSqlStmt, " OPEN Ename for SELECT ename from emp;\n");
strcat( (char *) pSqlStmt, " END IF;\n\n");
strcat( (char *) pSqlStmt, " IF NOT Mgr%ISOPEN\n THEN\n");
strcat( (char *) pSqlStmt, " OPEN Mgr for SELECT mgr from emp where job = pjob;\n");
strcat( (char *) pSqlStmt, " END IF;\n");
strcat( (char *) pSqlStmt, " END;\n");
strcat( (char *) pSqlStmt, "END;\n");
rc = SQLExecDirect(hStmt, pSqlStmt, strlen((char *)pSqlStmt));
if (rc != SQL_SUCCESS)
{
  DisplayError(SQL_HANDLE_STMT, hStmt, "SQLExecDirect");
}
/*
 * Bind the Parameter
 */
rc = SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,JOB_LEN,0,pSalesMan,0,&sqlnts);
/*
 * Call the Store Procedure which executes the Result Sets
 */
strcpy( (char *) pSqlStmt, "{CALL ODBCRefCur.EmpCurs(?)}");
rc = SQLExecDirect(hStmt, pSqlStmt, strlen((char *)pSqlStmt));
if (rc != SQL_SUCCESS)
{
  DisplayError(SQL_HANDLE_STMT, hStmt, "SQLExecDirect");
}
/*
 * Bind the Data
 */
rc = SQLBindCol( hStmt,1,SQL_C_CHAR,Data,sizeof(Data),&DataLen);
if (rc != SQL_SUCCESS)
{
  DisplayError(SQL_HANDLE_STMT, hStmt, "SQLBindCol");
}
/*
 * Get the data for Result Set 1
 */
printf( "\nEmployee Names\n\n");
while ( rc == SQL_SUCCESS )
{
  rc = SQLFetch( hStmt );
  if ( rc == SQL_SUCCESS )
  {
    printf("%s\n", Data);
  }
  else
  {
    if (rc != SQL_NO_DATA)
    {
      DisplayError(SQL_HANDLE_STMT, hStmt, "SQLFetch");
    }
  }
}
printf( "\nFirst Result Set - Hit Return to Continue\n");
charptr = gets ((char *)error);
/*
 * Get the Next Result Set
 */
rc = SQLMoreResults( hStmt );
if (rc != SQL_SUCCESS)
{
  DisplayError(SQL_HANDLE_STMT, hStmt, "SQLMoreResults");
}
/*
 * Get the data for Result Set 2
 */
printf( "\nManagers\n\n");
while ( rc == SQL_SUCCESS )
{
  rc = SQLFetch( hStmt );
  if ( rc == SQL_SUCCESS )
  {
    printf("%s\n", Data);
  }
  else
  {
    if (rc != SQL_NO_DATA)
    {
    DisplayError(SQL_HANDLE_STMT, hStmt, "SQLFetch");
    }
  }
}
printf( "\nSecond Result Set - Hit Return to Continue\n");
charptr = gets ((char *)error);
/*
 * Should Be No More Results Sets
 */
rc = SQLMoreResults( hStmt );
if (rc != SQL_NO_DATA)
{
  DisplayError(SQL_HANDLE_STMT, hStmt, "SQLMoreResults");
}
/*
 * Drop the Package
 */
strcpy( (char *) pSqlStmt, "DROP PACKAGE ODBCRefCur");
rc = SQLExecDirect(hStmt, pSqlStmt, strlen((char *)pSqlStmt));
/*
 * Free handles close connections to the database
 */
SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
SQLDisconnect( hDbc );
SQLFreeHandle( SQL_HANDLE_DBC, hDbc );
SQLFreeHandle( SQL_HANDLE_ENV, hEnv );
printf( "\nAll Done - Hit Return to Exit\n");
charptr = gets ((char *)error);
return(0);
}
/*
 * Display Error Messages
 */
void DisplayError( SWORD HandleType, SQLHANDLE hHandle, char *Module )
{
SQLCHAR MessageText[255];
SQLCHAR SQLState[80];
SQLRETURN rc=SQL_SUCCESS;
long NativeError;
SWORD RetLen;
SQLCHAR error[25];
char *charptr;
rc =
SQLGetDiagRec(HandleType,hHandle,1,SQLState,&NativeError,MessageText,255,&RetLen);
printf( "Failure Calling %s\n", Module );
if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
{
  printf( "\t\t\t State: %s\n", SQLState);
  printf( "\t\t\t Native Error: %d\n", NativeError );
  printf( "\t\t\t Error Message: %s\n", MessageText );
}
printf( "\nHit Return to Exit\n");
charptr = gets ((char *)error);
exit(1);
}

E.10 EXEC構文の有効化

使用しているSQL ServerのEXEC文の構文を変更せずに同等のOracleプロシージャ・コールに容易に変換できる場合、その構文は、このオプションを有効にすると、Oracle ODBC Driverで変換できます。

SQL Serverプロシージャの完全な名前は、次に示す最大4つの識別子で構成されます。

  • サーバー名

  • データベース名

  • 所有者名

  • プロシージャ名

この名前の書式は次のとおりです。

[[[server.][database].][owner_name].]procedure_name

Microsoft SQL ServerデータベースからOracle Databaseに移行する際、各SQL Serverプロシージャまたはファンクションの定義は同等のOracle Database構文に変換され、Oracle Databaseのスキーマで定義されます。移行したプロシージャは、多くの場合、次のいずれかの方法で再編成(およびスキーマで作成)されます。

  • すべてのプロシージャが1つのスキーマに移行されます(デフォルト・オプション)。

  • 1つのSQL Serverデータベースに定義されているすべてのプロシージャが、そのデータベース名の付いたスキーマに移行されます。

  • 特定のユーザーが所有するすべてのプロシージャが、そのユーザー名の付いたスキーマに移行されます。

移行したプロシージャを編成するこれら3通りの方法をサポートするためには、いずれかのスキーマ名オプションを指定してプロシージャ名を変換できます。変換したOracleプロシージャ・コールのオブジェクト名では、大/小文字が区別されません。

E.11 サポートされている機能

この項では、Oracle ODBC Driverでサポートされている機能について説明します。内容は次のとおりです。

E.11.1 APIへの準拠

Oracle ODBC Driverリリース10.2.0.1.0以上では、コア、レベル2およびレベル1のすべての関数をサポートしています。

E.11.2 ODBC API関数の実装

次の表に、Oracle ODBC Driverが特定の関数を実装する方法を示します。

機能 説明

SQLConnect

SQLConnectで必要なのは、DBQ、ユーザーIDおよびパスワードのみです。

SQLDriverConnect

SQLDriverConnectでは、DSNDBQUIDおよびPWDの各キーワードが使用されます。

SQLSpecialColumns

SQL_BEST_ROWID属性を指定してSQLSpecialColumnsをコールすると、常にROWID列を返します。

SQLProceduresおよびSQLProcedureColumns

次の項の説明を参照してください。

すべてのカタログ・ファンクション

SQL_ATTR_METADATA_ID文の属性がSQL_TRUEに設定されている場合、文字列の引数は、識別子の引数として処理されますが、このケースはあまり重要ではありません。この場合、アンダースコア(_)およびパーセント記号(%)は検索用パターン文字ではなく、実際の文字として処理されます。これに対して、この属性をSQL_FALSEに設定すると、文字列の引数は、通常の引数またはパターン値の引数となり、リテラルに処理されるため、このケースは重要です。

SQLProceduresおよびSQLProcedureColumns

SQLProceduresコールおよびSQLProcedureColumnsコールは、パッケージ内に含まれている場合でも、すべてのプロシージャおよびファンクションに関する情報を検索して返すように変更されました。これより前のリリースでは、これらのコールで検索されるのは、パッケージ外のプロシージャとファンクションのみでした。次の例では、SQL_ATTR_METADATA_ID属性をSQL_FALSEに設定した場合に返されるプロシージャまたはファンクションを示します。

この例では、次のストアド・プロシージャがあるとします。

"BAR"
"BARX"
"XBAR"
"XBARX"
"SQLPROCTEST.BAR" 
"SQLPROCTEST.BARX" 
"SQLPROCTEST.XBAR" 
"SQLPROCTEST.XBARX" 

%または%%%%%%と指定して検索すると、これら8つのプロシージャがすべて返されます。

%_または_%と指定して検索すると、次のプロシージャが返されます。

BAR 
BARX 
XBAR 
XBARX 

..%%.%SQLPROC%.またはSQLPROC%.%と指定して検索すると、次のプロシージャが返されます。

SQLPROCTEST.BAR
SQLPROCTEST.BARX 
SQLPROCTEST.XBAR 
SQLPROCTEST.XBARX 

%BARと指定して検索すると、次のプロシージャが返されます。

BAR
XBAR

.%BARまたは%.%BARと指定して検索すると、次のプロシージャが返されます。

SQLPROCTEST.BAR
SQLPROCTEST.XBAR 

SQLPROC%または.SQLPROC%と指定して検索すると、次のプロシージャが返されます。

nothing (0 rows)

E.11.3 ODBC SQL構文の実装

比較述語で比較の2番目の式としてパラメータ・マーカーが使用され、そのパラメータの値がSQLBindParameterを使用してSQL_NULL_DATAに設定されている場合、比較は失敗します。これは、ODBC SQLのNULL述語構文と一致しています。

E.11.4 データ型の実装

プログラマがデータ型を実装する際に最も考慮する必要があるのは、CHARVARCHARおよびVARCHAR2の各データ型です。

SQL_VARCHARの値がfSqlTypeの場合、SQLGetTypeInfoはOracle Databaseデータ型VARCHAR2を返します。SQL_CHARの値がfSqlTypeの場合、SQLGetTypeInfoはOracle Databaseデータ型CHARを返します。

E.12 Unicodeのサポート

この項では、Unicodeのサポートについて説明します。次の項目が含まれます。

E.12.1 ODBC環境内でのUnicodeのサポート

ODBC Driver Managerを使用すると、すべてのODBCドライバは、Unicodeをサポートしているかどうかに関係なくUnicode準拠と同様に動作します。これによって、ODBCアプリケーションは、基礎となるODBCドライバのUnicode機能に関係なく記述できます。

Driver ManagerがANSI ODBCドライバに対するUnicodeサポートをエミュレートできる範囲は、Unicodeデータとローカル・コード・ページ間で可能な変換内容によって制限されます。Driver ManagerがデータをUnicodeからローカル・コード・ページに変換する際、データが失われる場合があります。基礎となるODBCドライバがUnicodeをサポートしていないかぎり、Unicodeの完全なサポートは不可能です。Oracle ODBC Driverは、Unicodeを完全にサポートしています。

E.12.2 ODBC APIでのUnicodeのサポート

ODBC APIは、WおよびA接尾辞の変換を使用して、UnicodeおよびANSIエントリ・ポイントの両方をサポートします。ODBCアプリケーション開発者は、接尾辞を指定してエントリ・ポイントを明示的にコールすることはありません。UNICODEおよび_UNICODEプリプロセッサ定義を使用してコンパイルされたODBCアプリケーションによって、適切なコールが生成されます。たとえば、SQLPrepareへのコールは、SQLPrepareWとしてコンパイルされます。

Cデータ型のSQL_C_WCHARがODBCインタフェースに追加されたため、アプリケーションでは、入力パラメータをUnicodeとしてエンコードするように指定するか、またはUnicodeとして返された列データを要求できます。マクロのSQL_C_TCHARは、UnicodeおよびANSIの両方で作成する必要があるアプリケーションで有効です。SQL_C_TCHARマクロは、Unicodeアプリケーションの場合はSQL_C_WCHARとして、ANSIアプリケーションの場合はSQL_C_CHARとしてコンパイルされます。

SQLデータ型のSQL_WCHARSQL_WVARCHARおよびSQL_WLONGVARCHARがODBCインタフェースに追加され、表内で定義された列がUnicodeで表現されるようになりました。これらの値は、SQLDescribeColSQLColAttributeSQLColumnsおよびSQLProcedureColumnsへのコールから返すことも可能です。

Unicodeエンコーディングは、SQL列型のNCHAR、NVARCHAR2およびNCLOBに対してサポートされています。さらに、文字セマンティクスが列定義で指定されている場合、UnicodeエンコーディングはSQL列型のCHARおよびVARCHAR2に対してもサポートされています。

Oracle ODBC Driverは、これらのSQL列型をサポートしてODBC SQLデータ型にマップします。次の表に、サポートされているSQLデータ型および対応するODBC SQLデータ型を示します。

SQLデータ型 ODBC SQLデータ型

CHAR

SQL_CHARまたはSQL_WCHAR

VARCHAR2

SQL_VARCHARまたはSQL_WVARCHAR

NCHAR

SQL_WCHAR

NVARCHAR2

SQL_WVARCHAR

NCLOB

SQL_WLONGVARCHAR

E.12.3 SQLGetDataのパフォーマンス

SQLGetData関数を使用すると、ODBCアプリケーションはデータ型を指定して、データのフェッチ後に列を取得できます。OCIでは、Oracle ODBC Driverはデータ型を指定してからフェッチする必要があります。この場合、Oracle ODBC Driverは(データベースで定義された)列のデータ型に関する情報を使用し、OCIを介して列をフェッチする最適なデフォルト方法を判断します。

文字データを含む列がSQLBindColによってバインドされていない場合、Oracle ODBC Driverは、その列をUnicodeとしてフェッチするか、またはローカル・コード・ページとしてフェッチするかを判断する必要があります。ドライバは、列をUnicodeとして受け入れるように常にデフォルト設定できます。ただし、この設定では、2回の不要な変換が実行されます。たとえば、データベース内のデータがANSIとしてエンコードされた場合、データをOracle ODBC DriverにフェッチするためにANSIからUnicodeへの変換が実行されます。次に、ODBCアプリケーションがそのデータをSQL_C_CHARとして要求すると、データを元のエンコーディングに戻すための変換が実行されます。

Oracle Database Clientのデフォルト・エンコーディングは、データをフェッチする際に使用されます。しかし、ODBCアプリケーションは、WCHARデータ型として列またはパラメータをバインドすることにより、このデフォルトを上書きして、Unicodeとしてデータをフェッチする場合があります。

E.12.4 Unicodeのサンプル

Oracle ODBC Driver自体がTCHARマクロを使用して実装されているため、ODBCアプリケーション・プログラムでは、TCHARを使用して、このドライバを利用することをお薦めします。

次の例では、UNICODEおよび_UNICODEを指定してコンパイルするとWCHARデータ型になるTCHARの使用方法を示します。

例E-1 データベースへの接続

このコードを使用するには、SQLConnectにUnicodeリテラルのみ指定する必要があります。

HENV         envHnd;
HDBC         conHnd;
HSTMT        stmtHnd;
RETCODE      rc;

rc  = SQL_SUCCESS;

// ENV is allocated
rc = SQLAllocEnv(&envHnd);
// Connection Handle is allocated
rc = SQLAllocConnect(envHnd, &conHnd);
rc = SQLConnect(conHnd, _T("stpc19"), SQL_NTS, _T("jones"), SQL_NTS, _T("password"), SQL_NTS);
.
.
.
if (conHnd)
  SQLFreeConnect(conHnd);
if (envHnd)
  SQLFreeEnv(envHnd);

例E-2 単純な取得

次の例では、EMP表から従業員名と役職名を取得します。すべてのODBC関数にTCHAR準拠のデータを指定する必要があることを除いて、ANSIの場合と違いはありません。Unicodeアプリケーションの場合は、SQLBindColのコール時にバッファ長をBYTE長に指定する必要があります。たとえば、sizeof(ename)の場合は次のとおりです。

/*
** Execute SQL, bind columns, and Fetch.
** Procedure:
**
**   SQLExecDirect
**   SQLBindCol
**   SQLFetch
** 
*/
static SQLTCHAR *sqlStmt = _T("SELECT ename, job FROM emp");
SQLTCHAR   ename[50];
SQLTCHAR     job[50];
SQLINTEGER enamelen, joblen;
 
_tprintf(_T("Retrieve ENAME and JOB using SQLBindCol 1.../n[%s]/n"), sqlStmt);
 
// Step 1: Prepare and Execute
rc = SQLExecDirect(stmtHnd, sqlStmt, SQL_NTS); // select
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
// Step 2: Bind Columns
rc = SQLBindCol(stmtHnd,
                1,
                SQL_C_TCHAR,
                ename,
                sizeof(ename),
                &enamelen);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
rc = SQLBindCol(stmtHnd,
                2,
                SQL_C_TCHAR,
                job,
                sizeof(job),
                &joblen);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
do 
{
  // Step 3: Fetch Data
  rc = SQLFetch(stmtHnd);
  if (rc == SQL_NO_DATA)
    break;
  checkSQLErr(envHnd, conHnd, stmtHnd, rc);
  _tprintf(_T("ENAME = %s, JOB = %s/n"), ename, job);
} while (1);
_tprintf(_T("Finished Retrieval/n/n"));

例E-3 SQLGetDataを使用した取得(フェッチ後のバインド)

この例では、SQLGetDataの使用方法を示します。Unicode固有の事項に関しては、ANSIアプリケーションとの違いはありません。

/*
** Execute SQL, bind columns, and Fetch.
** Procedure:
**
**   SQLExecDirect
**   SQLFetch
**   SQLGetData
*/
static SQLTCHAR *sqlStmt = _T("SELECT ename,job FROM emp"); // same as Case 1.
SQLTCHAR         ename[50];
SQLTCHAR         job[50];
 
_tprintf(_T("Retrieve ENAME and JOB using SQLGetData.../n[%s]/n"), sqlStmt);
if (rc != SQL_SUCCESS)
{
  _tprintf(_T("Failed to allocate STMT/n"));
  goto exit2;
}
 
// Step 1: Prepare and Execute
rc = SQLExecDirect(stmtHnd, sqlStmt, SQL_NTS); // select
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
do 
{
 
  // Step 2: Fetch
  rc = SQLFetch(stmtHnd);
  if (rc == SQL_NO_DATA)
    break;
  checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
  // Step 3: GetData
  rc = SQLGetData(stmtHnd, 
    1,
    SQL_C_TCHAR,
    (SQLPOINTER)ename,
    sizeof(ename), 
    NULL);
  checkSQLErr(envHnd, conHnd, stmtHnd, rc);
  rc = SQLGetData(stmtHnd, 
    2,
    SQL_C_TCHAR, 
    (SQLPOINTER)job,
    sizeof(job), 
    NULL);
  checkSQLErr(envHnd, conHnd, stmtHnd, rc);
  _tprintf(_T("ENAME = %s, JOB = %s/n"), ename, job);
} while (1);
_tprintf(_T("Finished Retrieval/n/n"));

例E-4 単純な更新

この例では、データの更新方法を示します。SQLBindParameterのデータ長は、UnicodeアプリケーションでもBYTE長で指定する必要があります。

/*
** Execute SQL, bind columns, and Fetch.
** Procedure:
**
**   SQLPrepare
**   SQLBindParameter
**   SQLExecute
*/
static SQLTCHAR *sqlStmt = _T("INSERT INTO emp(empno,ename,job) VALUES(?,?,?)");
static SQLTCHAR *empno   = _T("9876");      // Emp No
static SQLTCHAR *ename   = _T("ORACLE");    // Name
static SQLTCHAR *job     = _T("PRESIDENT"); // Job
 
_tprintf(_T("Insert User ORACLE using SQLBindParameter.../n[%s]/n"), sqlStmt);
 
// Step 1: Prepare
rc = SQLPrepare(stmtHnd, sqlStmt, SQL_NTS); // select
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
// Step 2: Bind Parameter
rc = SQLBindParameter(stmtHnd, 
                      1, 
                      SQL_PARAM_INPUT,
                      SQL_C_TCHAR,
                      SQL_DECIMAL,
                      4,               // 4 digit
                      0,
                      (SQLPOINTER)empno,
                      0,
                      NULL);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
rc = SQLBindParameter(stmtHnd, 
                      2, 
                      SQL_PARAM_INPUT,
                      SQL_C_TCHAR,
                      SQL_CHAR,
                      lstrlen(ename)*sizeof(TCHAR),
                      0,
                      (SQLPOINTER)ename,
                      lstrlen(ename)*sizeof(TCHAR),
                      NULL);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
rc = SQLBindParameter(stmtHnd, 
                      3, 
                      SQL_PARAM_INPUT,
                      SQL_C_TCHAR,
                      SQL_CHAR,
                      lstrlen(job)*sizeof(TCHAR),
                      0,
                      (SQLPOINTER)job,
                      lstrlen(job)*sizeof(TCHAR),
                      NULL);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
// Step 3: Execute
rc = SQLExecute(stmtHnd);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);

例E-5 長いデータ(CLOB)の更新と取得

ここでは、CLOBなどの長いデータをOracle Databaseで更新および取得する最も複雑な例を示します。データ長は常にBYTE長であるため、BYTE長を導出するには式lstrlen(TCHAR data)*sizeof(TCHAR)が必要です。

/*
** Execute SQL, bind columns, and Fetch.
** Procedure:
**
**   SQLPrepare
**   SQLBindParameter
**   SQLExecute
**   SQLParamData
**   SQLPutData
**
**   SQLExecDirect
**   SQLFetch
**   SQLGetData
*/
static SQLTCHAR *sqlStmt1  = _T("INSERT INTO clobtbl(clob1) VALUES(?)");
static SQLTCHAR *sqlStmt2  = _T("SELECT clob1 FROM clobtbl");
SQLTCHAR         clobdata[1001];
SQLTCHAR         resultdata[1001];
SQLINTEGER       ind = SQL_DATA_AT_EXEC;
SQLTCHAR        *bufp;
int              clobdatalen, chunksize, dtsize, retchklen;
 
_tprintf(_T("Insert CLOB1 using SQLPutData.../n[%s]/n"), sqlStmt1);
 
// Set CLOB Data
{
  int i;
  SQLTCHAR ch;
  for (i=0, ch=_T('A'); i< sizeof(clobdata)/sizeof(SQLTCHAR); ++i, ++ch)
  {
    if (ch > _T('Z'))
      ch = _T('A');
    clobdata[i] = ch;
  }
  clobdata[sizeof(clobdata)/sizeof(SQLTCHAR)-1] = _T('/0');
}
clobdatalen = lstrlen(clobdata);  // length of characters
chunksize   = clobdatalen / 7;    // 7 times to put

// Step 1: Prepare
rc = SQLPrepare(stmtHnd, sqlStmt1, SQL_NTS);
checkSQLErr(envHnd, conHnd, stmtHnd, rc); 
// Step 2: Bind Parameter with SQL_DATA_AT_EXEC
rc = SQLBindParameter(stmtHnd, 
                      1, 
                      SQL_PARAM_INPUT,
                      SQL_C_TCHAR,
                      SQL_LONGVARCHAR,
                      clobdatalen*sizeof(TCHAR),
                      0,
                      (SQLPOINTER)clobdata,
                      clobdatalen*sizeof(TCHAR),
                      &ind);
checkSQLErr(envHnd, conHnd, stmtHnd, rc); 
// Step 3: Execute
rc = SQLExecute(stmtHnd);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
// Step 4: ParamData (initiation)
rc = SQLParamData(stmtHnd, (SQLPOINTER*)&bufp); // set value
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
for (dtsize=0, bufp = clobdata;
     dtsize < clobdatalen;
     dtsize += chunksize, bufp += chunksize)
{
  int len;
  if (dtsize+chunksize<clobdatalen)
    len = chunksize;
  else
    len = clobdatalen-dtsize;
 
  // Step 5: PutData
  rc = SQLPutData(stmtHnd, (SQLPOINTER)bufp, len*sizeof(TCHAR));
  checkSQLErr(envHnd, conHnd, stmtHnd, rc);
}
 
// Step 6: ParamData (temination)
rc = SQLParamData(stmtHnd, (SQLPOINTER*)&bufp);
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
rc = SQLFreeStmt(stmtHnd, SQL_CLOSE);
_tprintf(_T("Finished Update/n/n"));
rc = SQLAllocStmt(conHnd, &stmtHnd);
if (rc != SQL_SUCCESS)
{
  _tprintf(_T("Failed to allocate STMT/n"));
  goto exit2;
}
 
// Clear Result Data
memset(resultdata, 0, sizeof(resultdata));
chunksize   = clobdatalen / 15;   // 15 times to put
 
// Step 1: Prepare
rc = SQLExecDirect(stmtHnd, sqlStmt2, SQL_NTS); // select
checkSQLErr(envHnd, conHnd, stmtHnd, rc);
 
// Step 2: Fetch
rc = SQLFetch(stmtHnd);
checkSQLErr(envHnd, conHnd, stmtHnd, rc); 
for(dtsize=0, bufp = resultdata;
    dtsize < sizeof(resultdata)/sizeof(TCHAR) && rc != SQL_NO_DATA;
    dtsize += chunksize-1, bufp += chunksize-1)
{
  int len; // len should contain the space for NULL termination
  if (dtsize+chunksize<sizeof(resultdata)/sizeof(TCHAR))
    len = chunksize;
  else
    len = sizeof(resultdata)/sizeof(TCHAR)-dtsize;
 
  // Step 3: GetData
  rc = SQLGetData(stmtHnd, 
    1,
    SQL_C_TCHAR,
    (SQLPOINTER)bufp,
    len*sizeof(TCHAR), 
    &retchklen);
}
if (!_tcscmp(resultdata, clobdata))
{
  _tprintf(_T("Succeeded!!/n/n"));
}
else
{
  _tprintf(_T("Failed!!/n/n"));
}

E.13 パフォーマンスとチューニング

この項では、次の項目について説明します。

E.13.1 ODBCプログラミングの一般的なガイドライン

ODBCアプリケーションのパフォーマンスを向上させるには、次のプログラミング・ガイドラインを適用してください。

  • アプリケーションがデータソースに頻繁に接続したり切断する場合は、接続プーリングを使用可能にします。プールされた接続の再利用は、接続の再確立に比べて非常に効率的です。

  • 文を準備する回数を最小限にします。可能な場合は、バインド・パラメータを使用し、別のパラメータ値に対して文を再利用できるようにします。SQLExecuteごとに文を準備するよりも、1つの文を1回準備して複数回実行する方が効率的です。

  • アプリケーションが取得しないことが判明している列、特にLONG列をSELECT文に含めないでください。LONG列がSELECT文に含まれていると、データベース・サーバー・プロトコルの特性上、アプリケーションが列をバインドするかSQLGetData操作を実行するかに関係なく、Oracle ODBC Driverでは列全体をフェッチする必要があるためです。

  • データソースを更新しないトランザクションを実行する場合は、ODBCのSQLSetConnectAttr関数のSQL_ATTR_ACCESS_MODE属性をSQL_MODE_READ_ONLYに設定します。

  • ODBCのエスケープ句を使用しない場合は、そのODBCのSQLSetConnectAttr関数またはSQLSetStmtAttr関数のSQL_ATTR_NOSCAN属性をtrueに設定します。

  • 行数の多い表からデータを取得する場合は、ODBCのSQLFetch関数のかわりにODBCのSQLFetchScroll関数を使用します。

E.13.2 データソース構成オプション

この項では、次のODBCデータソース構成オプションを使用した場合のパフォーマンスへの影響を説明します。

  • 結果セットの有効化

    このオプションによって、プロシージャ・コールから結果セット(RefCursorなど)を返すサポートが有効になります。デフォルトでは、結果セットを返すサポートが有効です。

    Oracle ODBC Driverでは、RefCursorパラメータが存在するかどうかを判断するために、データベース・サーバーを問い合せてプロシージャのパラメータ・セットとそのデータ型を判別する必要があります。この問合せによって、最初にプロシージャが準備完了になり実行されると、追加のネットワーク・ラウンド・トリップが発生します。

  • LOBの有効化

    このオプションによって、LOBを挿入および更新するサポートが有効になります。デフォルトは有効です。

    Oracle ODBC Driverでは、LOBパラメータがあるかどうかを判断するために、データベース・サーバーを問い合せて、INSERT文またはUPDATE文の各パラメータのデータ型を判別する必要があります。この問合せによって、最初にINSERTまたはUPDATEが準備完了になり実行されると、追加のネットワーク・ラウンドトリップが発生します。

    関連項目:

    LOBの詳細は、『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』を参照してください。

    ノート:

    LOBデータ圧縮を行うと、SecureFilesを圧縮して、ディスク、入出力およびREDOログを節約できます。この場合、圧縮により領域の使用効率が上がるため、コストが低減されます。また、圧縮により入出力およびREDOログが縮小するため、SecureFilesのパフォーマンスが向上します。

    LOBデータを暗号化すると、データベースのセキュリティが強化されます。ランダムな読取りおよび書込みに対して暗号化データが使用可能になっている間、データのセキュリティは向上します。

    データを圧縮および暗号化する場合、追加のメモリーが消費されます。

  • TIMESTAMPDATEとしてバインド

    SQL_TIMESTAMPパラメータを適切なOracle Databaseデータ型としてバインドします。このオプションをTRUEに設定すると、SQL_TIMESTAMPはOracleのDATEデータ型としてバインドされます。このオプションをFALSEに設定すると、SQL_TIMESTAMPはOracleのTIMESTAMPデータ型としてバインドされます。これがデフォルトです。

  • カーソル・クローズの有効化

    ODBC関数SQLFreeStmtSQL_CLOSEオプションは、関連するカーソルを文とともにクローズし、保留中のすべての結果を廃棄します。アプリケーションでは文を再度実行することによってカーソルを再オープンでき、SQLPrepareを再度実行する必要はありません。このオプションを使用する典型的な例は、しばらくの間アイドル状態になり、後で同じSQL文を再利用するアプリケーションの場合です。この場合、アプリケーションがアイドル状態になっている間、関連するサーバー・リソースを解放できます。

    Oracle ODBC Driverが位置するOCIでは、カーソルをクローズする機能をサポートしていません。したがって、デフォルトでは、SQL_CLOSEオプションはOracle ODBC Driverに影響を与えません。カーソルおよび関連するリソースはデータベース上でオープンしたままです。

    このオプションを有効にすると、データベース・サーバー上の関連するカーソルがクローズします。ただし、その結果、SQL文の解析コンテキストが失われます。ODBCアプリケーションは文を再度実行でき、SQLPrepareをコールする必要はありません。ただし、内部的には、Oracle ODBC Driverは文全体を準備して実行する必要があります。このオプションを有効にすると、文を1回準備して繰り返し実行するアプリケーションのパフォーマンスに大きな影響を与えます。

    このオプションは、サーバー上のリソースを解放する必要がある場合のみ有効にしてください。

  • フェッチ・バッファ・サイズ

    odbc.iniファイルのフェッチ・バッファ・サイズ(FetchBufferSize)を、バイト単位で指定した値に設定します。この値は、Oracle ODBC DriverがOracle Databaseからクライントのキャッシュに1回にプリフェッチするデータの行数を決定するのに必要なメモリー量で、アプリケーション・プログラムが1回の問合せで要求する行数とは関係ありません。これによって、パフォーマンスが向上します。

    また、1回にフェッチするデータが20行未満であることが多いアプリケーションで、特に、速度の遅いネットワーク接続である場合や負荷の大きいサーバーからフェッチする場合は、アプリケーションの応答時間が改善されます。この設定値が高すぎると、応答時間に悪影響が生じたり、大量のメモリーが消費される可能性があります。デフォルトは64,000バイトです。アプリケーションに対して最適な値を選択してください。

    LONGおよびLOBデータ型がある場合、Oracle ODBC Driverがプリフェッチする行数はこのフェッチ・バッファ・サイズで決まりません。LONGおよびLOBデータ型が含まれると、パフォーマンスの向上は最小限になり、過剰にメモリーが使用される可能性があります。Oracle ODBC Driverはこのフェッチ・バッファ・サイズを無視し、LONGおよびLOBデータ型が存在する場合は一定の行数のみプリフェッチします。

E.13.3 DATEおよびTIMESTAMPデータ型

WHERE句でデータベースのDATE列が使用され、その列に索引がある場合は、パフォーマンスに影響を与える可能性があります。たとえば:

SELECT * FROM EMP WHERE HIREDATE = ?

この例では、HIREDATE列の索引を使用して、問合せを迅速に実行できます。ただし、HIREDATEDATE値で、Oracle ODBC Driverはこのパラメータ値をTIMESTAMPとして提供しているため、Oracle Databaseの問合せオプティマイザは変換関数を適用する必要があります。誤った結果(パラメータ値に0以外の小数秒がある場合に発生する可能性があります)を防ぐために、オプティマイザは、HIREDATE列に変換を適用するため、次のような文になります。

SELECT * FROM EMP WHERE TO_TIMESTAMP(HIREDATE) = ?

ただし、この場合はHIREDATE列で索引を使用できなくなります。かわりに、サーバーでは表の順次スキャンを実行します。したがって、表に多数の行がある場合は時間がかかる可能性があります。このような場合の次善策として、Oracle ODBC DriverにはTIMESTAMPDATEとしてバインドする接続オプションが用意されています。このオプションを有効にすると、Oracle ODBC Driverは、SQL_TIMESTAMPパラメータをOracleのTIMESTAMPデータ型ではなくOracleのDATEデータ型としてバインドします。これによって、問合せオプティマイザはDATE列で索引を使用できます。

ノート:

このオプションは、DATE列をTIMESTAMP列としてバインドするMicrosoft Accessや類似のプログラムで使用することを目的にしています。実際のTIMESTAMP列がある場合、またはデータが失われる可能性がある場合は使用しないでください。Microsoft Accessでは、主キーとして選択されたすべての列を使用してこの問合せを実行します。

E.14 エラー・メッセージ

エラーが発生すると、Oracle ODBC Driverは、システム固有のエラー番号、SQLSTATE(ODBCエラー・コード)およびエラー・メッセージを返します。ドライバは、ドライバが検出したエラーおよびOracle Databaseから返されたエラーの両方からこれらの情報を導出します。

固有のエラー

データソースでエラーが発生した場合、Oracle ODBC Driverは、Oracle Databaseから返されたシステム固有のエラーを返します。Oracle ODBC DriverまたはDriver Managerがエラーを検出した場合、Oracle ODBC Driverはシステム固有のエラー番号として0(ゼロ)を返します。

SQLSTATE

データソースでエラーが発生した場合、Oracle ODBC Driverは、返されたシステム固有のエラーを適切なSQLSTATEにマップします。Oracle ODBC DriverまたはDriver Managerがエラーを検出した場合は、適切なSQLSTATEを生成します。

エラー・メッセージ

データソースでエラーが発生した場合、Oracle ODBC Driverは、Oracle Databaseから返されたメッセージに基づいてエラー・メッセージを返します。Oracle ODBC DriverまたはDriver Managerでエラーが発生した場合、Oracle ODBC Driverは、SQLSTATEに関連付けられたテキストに基づいてエラー・メッセージを返します。

エラー・メッセージの書式は次のとおりです。

[vendor] [ODBC-component] [data-source] error-message

大カッコ([ ])内の接頭辞によって、エラーの発生場所を識別します。次の表に、Oracle ODBC Driverから返される接頭辞の値を示します。データソースでエラーが発生した場合は、vendorおよびODBC-component接頭辞によって、データソースからエラーを受け取ったODBCコンポーネントのベンダーと名前を識別します。

エラー・ソース 接頭辞

ドライバ・マネージャ

[vendor]

[ODBC-component]

[data-source]

[unixODBC]

[Driver Manager]

適用なし

Oracle ODBC Driver

[vendor]

[ODBC-component]

[data-source]

[ORACLE]

[Oracle ODBC Driver]

適用なし

Oracle Database

[vendor]

[ODBC-component]

[data-source]

[ORACLE]

[Oracle ODBC Driver]

[Oracle OCI]

たとえば、次の書式に示すように、エラー・メッセージにOra接頭辞が付いていない場合、そのエラーはOracle ODBC Driverのエラーであることがわかります。

[Oracle][ODBC]Error message text here

また、次の書式に示すように、エラー・メッセージにOra接頭辞が付いている場合、このエラーはOracle ODBC Driverのエラーではありません。

[Oracle][ODBC][Ora]Error message text here

ノート:

エラー・メッセージにORA-接頭辞が付いている場合でも、実際のエラーは複数のソースのいずれかで発生している場合があります。

エラー・メッセージのテキストがORA-接頭辞で始まっている場合、そのエラーの詳細はOracle Databaseのドキュメントを参照してください。