Oracle 11g データベースに「監査」テーブルがあります。テーブルには「Account_Name」という列があります。"Audit"."Account_name" 列には、"Guest"、"feeder_1"、"feeder_2"、"feeder_3" などのデータがあります。
「Audit.Account_Name」列に次のインデックスを作成しました。
CREATE INDEX AUDIT_IX9_CI ON AUDIT (NLSSORT("ACCOUNT_NAME",'nls_sort=''BINARY_CI'''));
JDBCコードから、最初に以下のステートメントを実行し、次に実際のクエリを実行して「監査」テーブルからデータを取得しています。
connection.prepareStatement("ALTER SESSION SET NLS_COMP=LINGUISTIC"); //line1
connection.prepareStatement("ALTER SESSION SET NLS_SORT=BINARY_CI"); // line2
//これは、データを取得するために実行されるコードです
connection.prepareStatement("select account_name from audit where (ACCOUNT_NAME like 'f%' ) ");//line3
rs = pst.executeQuery();//line4
while(rs.next()){
String accountName = rs.getString("account_name");
System.out.println("account name "+accountName);
}
上記のクエリは、「Guest」などの値を含むすべてのデータをテーブルから取得しています。Account_name が 'f' で始まる行のみをクエリがフェッチする必要があることを除いて、NLS_SORT と NLS_COMP が正しくないデータをフェッチしているように見えます。
「line2」にコメントすると、データが正しく取得されることがわかりました。これらのオプションが正しく機能しない理由を誰でも提案できますか?
同じ接続オブジェクトで JDBC コードからクエリを実行しました。
select PARAMETER, value from nls_session_parameters
NLS_LANGUAGE = AMERICAN
NLS_TERRITORY = AMERICA
NLS_CURRENCY = $
NLS_ISO_CURRENCY = AMERICA
NLS_NUMERIC_CHARACTERS = .,
NLS_CALENDAR = GREGORIAN
NLS_DATE_FORMAT = DD-MON-RR
NLS_DATE_LANGUAGE = AMERICAN
NLS_SORT = BINARY_CI
NLS_TIME_FORMAT = HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT = DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT = HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT = DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY = $
NLS_COMP = LINGUISTIC
NLS_LENGTH_SEMANTICS = BYTEs
NLS_NCHAR_CONV_EXCP = FALSE
この問題は、本番環境で発生します。そのため、以前に JDBC を使用してスタンドアロン Java コードを作成し、本番環境と同じ問題が発生するかどうかを確認しました。
ここで、Oracle プロシージャを作成しました。このプロシージャでは、最初に NLS_COMP および NLS_SORT パラメータが設定され、次に検索クエリが実行され (ここでは CURSOR が使用されます)、後で NLS_SORT=BINARY がリセットされます。結果は同じで、同じ問題が発生します。
~の計画を説明する account_name が 'f%' のような監査から account_name を選択します 企画ハッシュ値:1078245361 -------------------------------------------------- -------------------------------- | | ID | 操作 | 名前 | 行 | 行 バイト | コスト (%CPU)| 時間 | -------------------------------------------------- -------------------------------- | | 0 | ステートメントを選択 | | | 10 | 2580 | 1 (0)| 00:00:01 | |* 1 | インデックスレンジスキャン| AUDIT_IX9 | 10 | 2580 | 1 (0)| 00:00:01 | -------------------------------------------------- -------------------------------- 述語情報 (操作 ID で識別): -------------------------------------------------- - 1 - access("ACCOUNT_NAME" LIKE U'f%') filter("ACCOUNT_NAME" LIKE U'f%') ノート ----- - このステートメントに使用される動的サンプリング (レベル = 2)
次のクエリを実行した後、文字セットを「WE8MSWIN1252」として取得しました。
パラメータ = 'NLS_CHARACTERSET'; nls_database_parameters から char_set に値を選択します。