この章の項目は次のとおりです。
Unicodeの集中型データベースは、グローバル・インターネット・アプリケーションを開発するためのアプローチの機能として、単一言語と多言語の両方に共通しています。集中型データベースの使用には、次のメリットがあります。
データの完全ビューが実現します。たとえば、全世界の顧客数や、製品の全世界的な在庫レベルを問い合せることができます。
1つの集中型データベースの管理は、複数の分散データベースの管理よりも容易です。
データベース・キャラクタ・セットは、Unicodeである必要があります。Unicodeを使用して、データをいくつかの言語で格納および操作できます。Unicodeは、世界中のほぼすべての言語において文字を定義するユニバーサル・キャラクタ・セットです。Oracleデータベースは、次のいずれかのエンコーディング形式でUnicodeデータを格納できます。
関連項目:
|
インターネット・アプリケーションからOracle Application Serverを介してデータベース・サーバーに接続するには、いくつかの方法があります。Javaサーブレット、JSP、EJBなどのテクノロジを使用するJavaベースのインターネット・アプリケーションの場合、データベースの接続性のためにOracle JDBCドライバを使用します。
Java文字列は常にUnicodeでエンコードされているので、JDBCはテキスト・データをデータベース・キャラクタ・セットとUnicodeとの間で透過的に変換します。Oracleデータベースと通信するJavaサーブレットとJSPでは、必ず次のことを確認する必要があります。
データベースから返されたJava文字列は、構成されたHTMLページのエンコーディングに変換されます。
フォーム入力は、JDBCドライバのコールで使用する前に、HTMLフォームのエンコーディングからUnicodeに変換されます。
Perl、PL/SQL、C/C++などのプログラミング・テクノロジを使用する非Javaインターネット・アプリケーションの場合、データベースから検索したりデータベースに挿入されたテキスト・データは、NLS_LANG
パラメータで指定したキャラクタ・セットでエンコードされます。POSIXロケールで使用するキャラクタ・セットは、アプリケーション内のPOSIXロケールに依存する関数でデータベースのデータを直接処理するために、NLS_LANG
キャラクタ・セットと一致する必要があります。
多言語アプリケーションの場合、NLS_LANG
キャラクタ・セットとページ・エンコーディングは、キャラクタ・セットが変換されデータ損失が発生する可能性を回避するために、両方ともUTF-8にする必要があります。
JSPとJavaサーブレットを使用する場合は、Oracle Application ServerでOracleデータベースへの接続用に提供されているOracle JDBCドライバを使用します。Oracle Application Serverには、中間層アプリケーションに配置可能なクライアント側JDBCドライバが2種類あります。
Oracleクライアント・ライブラリを必要とするJDBC OCIドライバ
Pure JavaドライバであるJDBC Thinドライバ
Oracle JDBCドライバは、文字データをデータベース・キャラクタ・セットからSQL CHAR
データ型とSQL NCHAR
データ型のUnicodeに透過的に変換します。この透過的な変換の結果、Oracle JDBCドライバをコールするJSPとJavaサーブレットは、データベース列をJava文字列にバインドおよび定義し、SQL実行の結果セットからJava文字列にデータをフェッチできます。
Java文字列を使用すると、カスタマ表のNAMEおよびADDRESS列をバインドできます。それぞれVARCHAR2
データ型とNVARCHAR2
データ型として列を定義します。たとえば、次のように設定します。
String cname = request.getParameter("cname") String caddr = request.getParameter("caddress"); OraclePreparedStatement pstmt = conn.prepareStatement("insert into" + "CUSTOMERS (NAME, ADRESS) values (?, ?) "); pstmt.setString(1, cname); pstmt.setFormOfUse(2, OraclePreparedStatement.FORM_NCHAR); pstmt.setString(2, caddr); pstmt.execute();
Java文字列変数をNVARCHAR2
として定義されたADDRESS列にバインドするには、setString()
メソッドの前にsetFormOfUse()
メソッドをコールする必要があります。
Oracle JDBCドライバは、データベース・セッションが初期化されたときに、デフォルトのJavaロケールに該当する値に対してNLS_LANGUAGE
およびNLS_TERRITORY
セッション・パラメータの値を設定します。単一言語アプリケーションの場合、Javaのデフォルト・ロケールは、ユーザーのロケールと一致するように構成されます。このため、データベース接続は必ずユーザーのロケールと一致しています。
関連項目: Oracle Databaseドキュメント・ライブラリ内の『Oracle Database JDBC開発者ガイドおよびリファレンス』 |
PL/SQLプロシージャおよびPSPは、SQLを使用して、ローカルのOracleデータベースのデータにアクセスします。また、SQLおよびデータベース・リンクを使用して、リモートのOracleデータベースのデータにアクセスします。
たとえば、次に示すmod_plsql
モジュールのPL/SQLプロシージャをコールできます。これは、VARCHAR2
として定義された顧客名列とNVARCHAR2
として定義された顧客アドレス列からなるカスタマ表にレコードを挿入します。
procedure addcustomer( cname varchar2 default NULL, caddress nvarchar2 default NULL) is begin .... if (cname is not null) then caddr :=TO_NCHAR(address); insert into customers (name, address) values (cname, caddr); commit; end if; end;
Apache mod_plsql
では、NVARCHAR
引数の受け渡しをサポートしていません。その結果、PL/SQLプロシージャで引数に対してVARCHAR2
を使用して、NVARCHAR
に明示的に変換してからINSERT
文を実行する必要があります。
例では、静的SQLを使用してカスタマ表に接続しています。また、DBMS_SQL
PL/SQLパッケージを使用し、動的SQLによってデータベース内のデータにアクセスすることもできます。
関連項目: Oracle Databaseドキュメント・ライブラリ内の『PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』 |
Perlスクリプトは、Oracle用のDBI/DBDドライバによってOracleデータベースに接続します。DBI/DBDドライバは、Oracle Application Serverの一部です。このドライバは、Oracle Call Interface(OCI)をコールしてデータベースに接続します。データベースから検索したデータやデータベースに挿入したデータは、NLS_LANG
キャラクタ・セットでエンコードされます。Perlスクリプトでは、次の項目を実行できる必要があります。
POSIXロケールをLC_ALL
環境変数で指定されたロケールで初期化します。
NLS_LANG
キャラクタ・セットで使用されているキャラクタ・セットを使用します。
これによって、データベースから検索したデータをPOSIX文字列操作関数で処理できるようになります。
次のコードは、DBI/DBDドライバによってOracleデータベースのカスタマ表に行を挿入する方法を示しています。
Use Apache::DBI; ... # Connect to the database $constr = 'host=dlsun1304.us.oracle.com;sid=icachedb;port=1521' ; $usr = 'system' ; $pwd = 'manager' ; $dbh = DBI->onnect("dbi:Oracle:$constr", $usr, $pwd, {AutoCommit=>1} ) || $r->rint("Failed to connect to Oracle: " . DBI->rrstr ); # prepare the statement $sql = 'insert into customers (name, address) values (:n, :a)'; $sth = $dbh->repare( $sql ); $sth->ind_param(':n' , $cname); $sth->ind_param(':a', $caddress); $sth->xecute(); $sth->inish(); $dbh->isconnect();
ターゲット列がSQL NCHAR
データ型である場合は、各バインド変数の使用フラグのフォームを指定する必要があります。たとえば、アドレス列がNVARCHAR2
データ型である場合は、SQL文を実行する前に$sth->func()
関数を追加する必要があります。
use DBD::Oracle qw(:ora_forms); ... $sql = 'insert into customers (name, address) values (:n, :a)'; $sth = $dbh->repare($sql); $sth->ind_param(':n', $cname); $sth->ind_param(':a', $caddress); $sth->func( { ':a' => ORA_NCHAR }, 'set_form'); $sth->xecute(); $sth->inish(); $dbh->isconnect();
多言語アプリケーションでUTF-8データを適切に処理するために、Perlスクリプトは次のことを行います。
UTF-8キャラクタ・セットに関連付けられたPOSIXロケールを使用します。
UTF-8のPerlモジュールを使用して、Perl文字列内のすべての文字列がUTF-8であることを示します。
C/C++アプリケーションは、OCIまたはPRO*C/C++によってOracleデータベースに接続します。OCIを直接コールするか、PRO*C/C++インタフェースを使用することによって、Unicodeデータの取得および格納をUTF-8データベースおよびSQL NCHAR
データ型において実行できます。
通常、データベースから検索したデータやデータベースに挿入したデータは、NLS_LANG
キャラクタ・セットでエンコードされます。C/C++プログラムでは、NLS_LANG
キャラクタ・セットと同じキャラクタ・セットをPOSIXロケールに使用する必要があります。そうしないと、POSIX文字列関数は、データベースから検索した文字データを使用できず、データベースに挿入されたときにPOSIXロケールでエンコードされた文字データが破損する場合があります。
多言語アプリケーションの場合、NLS_LANG
キャラクタ・セットではなく、OCIライブラリに提供されたUnicode APIを使用することがあります。この代替策は、UTF-16 Unicodeによってwchar_t
データ型を実装するMicrosoft Windowsなどのプラットフォーム用に記述されたアプリケーションにとって好都合です。これらのプラットフォームでUnicode APIを使用すると、通常のOCI APIの使用時に必要なデータ変換が不要になります。
この項の項目は次のとおりです。
データベース接続のためのPro*C/C++でのUnicodeバインドと定義の使用
注意: OCIライブラリは、Oracle Application Serverの一部です。このライブラリを使用するために、Oracleデータベース・クライアントをインストールする必要はありません。 |
次の例は、カスタマ表のVARCHAR2
列とNVARCHAR2
列をC/C++でバインドおよび定義する方法を示しています。この例は、OCIを使用し、NLS_LANG
キャラクタ・セットに基づいています。text
データ型がunsigned char
へのマクロであることに注意してください。
text *sqlstmt= (text *)"SELECT name, address FROM customers WHERE id = :cusid"; text cname[100]; /* Customer Name */ text caddr[200]; /* Customer Address */ text custid[10] = "9876"; /* Customer ID */ ub2 cform = SQLCS_NCHAR; /* Form of Use for NCHAR types */ ... OCIStmtPrepare (stmthp, errhp, sqlstmt, (ub4)strlen ((char *)sqlstmt), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Bind the custid buffer */ OCIBindByName(stmthp, &bnd1p, errhp, (text*)":custid", (sb4)strlen((char *)":custid"), (dvoid *) custid, sizeof(cust_id), SQLT_STR, (dvoid *)&insname_ind, (ub2 *) 0, (ub2 *) 0, (ub4) 0,(ub4 *)0, OCI_DEFAULT); /* Define the cname buffer for VARCHAR */ OCIDefineByPos (stmthp, &dfn1p, errhp, (ub4)1, (dvoid *)cname, (sb4)sizeof(cname), SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT); /* Define the caddr buffer for the address column in NVARCHAR2 */ OCIDefineByPos (stmthp, &dfn2p, errhp, (ub4)2, (dvoid *)caddr, (sb4)sizeof(caddr), SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT); OCIAttrSet((void *) dfn2p, (ub4) OCI_HTYPE_DEFINE, (void *) &cform, (ub4) 0, (ub4)OCI_ATTR_CHARSET_FORM, errhp); ...
OCIライブラリで多言語アプリケーション用に提供するUnicode APIを使用することができます。
OCI環境ハンドルを作成するときにUnicodeモードを指定することによって、Unicode APIを使用します。OCI環境ハンドルから継承されたハンドルは、すべて自動的にUnicodeモードに設定されます。Unicodeモードに変更することによって、OCI関数へのすべてのテキスト・データ引数は、Unicodeテキスト(utext*
)データ型でUTF-16エンコーディングであることが前提になります。バインドおよび定義を行う場合、データ・バッファにおいてutext
バッファがUTF-16エンコーディングであることが前提になります。
Unicode APIのプログラム・コードは、次の点を除いて、非Unicode OCI API用のコードと類似しています。
次のタスクを実行する方法を、その後のMicrosoft Windowsプログラムの例に示します。
Unicodeモードにして、OCI環境ハンドルを作成します。
customers
表のVARCHAR2
の名前列とNVARCHAR2
のアドレス列をバインドおよび定義します。
utext *sqlstmt= (text *)L"SELECT name, address FROM customers WHERE id = :cusid"; utext cname[100]; /* Customer Name */ utext caddr[200]; /* Customer Address */ text custid[10] = "9876"; /* Customer ID */ ub1 cform = SQLCS_NCHAR; /* Form of Use for NCHAR types */ ... /* Use Unicode OCI API by specifying UTF-16 mode */ status = OCIEnvCreate((OCIEnv **)&envhp, OCI_UTF16, (void *)0, (void *(*) ()) 0, (void *(*) ()) 0, (void(*) ()) 0, (size_t) 0, (void **)0); ... OCIStmtPrepare (stmthp, errhp, sqlstmt, (ub4)wcslen ((char *)sqlstmt), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); /* Bind the custid buffer */ OCIBindByName(stmthp, &bnd1p, errhp, (constant text*) L":custid", (sb4)wcslen(L":custid"), (dvoid *) custid, sizeof(cust_id), SQLT_STR, (dvoid *)&insname_ind, (ub2 *) 0, (ub2 *) 0, (ub4) 0,(ub4 *)0, OCI_DEFAULT); /* Define the cname buffer for the name column in VARCHAR2 */ OCIDefineByPos (stmthp, &dfn1p, errhp, (ub4)1, (dvoid *)cname, (sb4)sizeof(cname), SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT); /* Define the caddr buffer for the address column in NVARCHAR2 */ OCIDefineByPos (stmthp, &dfn2p, errhp, (ub4)2, (dvoid *)caddr, (sb4)sizeof(caddr), SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT); OCIAttrSet((void *) dfn2p, (ub4) OCI_HTYPE_DEFINE, (void *) &cform, (ub4) 0, (ub4)OCI_ATTR_CHARSET_FORM, errhp); ...
多言語アプリケーションの場合、Unicodeのバインドと定義をPro*C/C++で使用することができます。
Pro*C/C++によって、バインドおよび定義の操作用にUTF-16 Unicodeバッファを指定できるようになります。UTF-16バッファをPro*C/C++で指定するには、2種類の方法があります。
struct uvarchar { ub2 len; /* length of arr */ utext arr[1] ; /* UTF-16 buffer */ }; typedef struct uvarchar uvarchar ;
次の例では、cname
とcaddr
という2種類のホスト変数が使用されています。cname
ホスト変数は、100のUTF-16コード・ユニット(unsigned short)で構成されるutext
バッファとして、VARCHAR2
データ型の顧客名列に対して宣言されます。caddr
ホスト変数は、50のUCS2文字で構成されるuvarchar
バッファとして、NVARCHAR2
データ型の顧客アドレス列に対して宣言されます。len
とarr
のフィールドはstruct
のフィールドとしてアクセス可能です。
#include <sqlca.h> #include <sqlucs2.h> main() { ... /* Change to STRING datatype: */ EXEC ORACLE OPTION (CHAR_MAP=STRING) ; utext cname[100] ; /* unsigned short type */ uvarchar caddr[200] ; /* Pro*C/C++ uvarchar type */ ... EXEC SQL SELECT name, address INTO :cname, :caddr FROM customers; /* cname is NULL-terminated */ wprintf(L"ENAME = %s, ADDRESS = %.*s\n", cname, caddr.len, caddr.arr); ... }