●Oracle10g から 8i へのDBリンクで不具合
今回とある要件で、Oracle10gサーバーから8iサーバーにDBリンクでやり取りをする要件があったのですが、若干不具合がありましたのでご報告します。
リンク元:
Ver:Oracle10.2.0.2.0
DBキャラクタセット:JA16SJISTILDE
リンク先:
Ver:8.1.7.4.1
DBキャラクタセット:JA16SJIS
アプリケーションを作成する際、VBやJAVAを使用する分には問題はなかったのですが、
PL/SQLでのプログラミングで問題が発生しました。
簡単な例を示します。
sqlplusで10gサーバーに接続し、以下の無名PL/SQLブロックを実行するとします。
SQL> DECLARE
2 CD HOGE_TBL.HOGE_CD%TYPE;
3 BEGIN
4 SELECT HOGE_CD INTO CD FROM HOGE_TBL WHERE KEY=123;
5 END;
6 /
HOGE_TBLはりモードDB(8i)のテーブルです。リンク先のテーブルを指定する場合、「@リンク名」をテーブル名に付加する必要があるのですが、今回は事前にシノニムを作成していることとします。
実行する内容は、HOGE_TBLの一意な値である「KEY」列で検索して、該当する行の「HOGE_CD」列を変数「CD」に代入するだけのものです。
変数「CD」はDECLARE部にて、「CD HOGE_TBL.HOGE_CD%TYPE;」と参照宣言されている部分に注意してください。
「HOGE_CD」の実際のデータ型はCHAR(4)です。
そして実行結果はというと・・・
行1でエラーが発生しました。:
ORA-06502: PL/SQL: 数値または値のエラー:
文字列バッファが小さすぎます。が発生しました
ORA-06512: 行4
となってしまいます。
参照宣言した変数に、参照元の実データを代入しただけでバッファが足りないとはこれいかに。
長年のSEの経験から、上記コードを下記のように修正してトライしてみました。
SQL> DECLARE
2 CD CHAR(8)
3 BEGIN
4 SELECT HOGE_CD INTO CD FROM HOGE_TBL WHERE KEY=123;
5 END;
6 /PL/SQLプロシージャが正常に完了しました。
成功しました。もうちょい試しにCHAR(7)に宣言を変えてみたところ、これはアウトでした。
実データ長の倍になってる?!
ならば変数は参照宣言に戻して、SELECT時にTRIMをかけてみましょう。
SQL> DECLARE
2 CD HOGE_TBL.HOGE_CD%TYPE;
3 BEGIN
4 SELECT RTRIM(HOGE_CD) INTO CD FROM HOGE_TBL WHERE KEY=123;
5 END;
6 /PL/SQLプロシージャが正常に完了しました。
通りますね。本来のデータ長分スペースがついてきているのは間違い無いようです。
ただし、最終確認として以下の分も流してみました。
SQL> DECLARE
2 CD VARCHAR2(8)
3 BEGIN
4 SELECT HOGE_CD INTO CD FROM HOGE_TBL WHERE KEY=123;
5 DBMS_OUTPUT.PUT_LINE(TO_CHAR(LENGTHB(CD)));
6 END;
7 /
変数のサイズを実データ長の倍にして、データ型を可変長文字列であるVARCHAR2にしました。
変数に取得されたデータのバイト長を出力してみます。
可変長であっても、スペースが末尾についているのであれば取得サイズは8の筈なんですが・・・
4PL/SQLプロシージャが正常に完了しました。
意味わからん。やっぱ・・・これって・・・バグ?
コメント
そうそう、上記の例でもリンク先がOracle9iであれば問題なく通ります。やっぱバグ?
Posted by: たけし | 2006年06月23日 13:00
それと、この例では10gと8iのデータベースにおけるキャラクタセットが微妙に違いますが、「チルダ」文字のマッピングだけが異なっているだけで、今回の不具合とは関係ない・・・と思う。
Posted by: Anonymous | 2006年06月23日 13:04