oracle

NVARCHAR2(AL16UTF16)でのLENGTH()使用にはご注意!

先日サロゲートペア文字に関するバグに遭遇しました。NVARCHAR2型に対しLENGTH()ファンクションで文字数をカウントしていたのですが、サロゲートペア文字は2文字扱いになるため想定外の動作となっていました。当然ですがVARCHAR2型(AL32UTF8)については1文字として扱ってくれます。

検証

create table EX108 (lno number,name_vc varchar2(40),name_nv NVARCHAR2(40));

insert into ex108 (lno,name_vc,name_nv) values(1,'A','A');
insert into ex108 (lno,name_vc,name_nv) values(2,'Σ','Σ');
insert into ex108 (lno,name_vc,name_nv) values(3,'あ','あ');
insert into ex108 (lno,name_vc,name_nv) values(4,'𩸽','𩸽');
commit;

select lno,name_vc,name_nv,length(name_vc) VC2_LEN,lengthb(name_vc) VC2_LENB,length(name_nv) NVC_LEN,lengthb(name_nv) NVC_LENB from ex108;

おまけ

今回の事象を受けてcreate tableでCHAR列セマンティクスを指定したらどうなるのだろうとテストしてみた結果、NCHARやNVARCHAR2型についてはCHAR列セマンティクス指定はできませんでした。

--VARCHAR2型で以下のようにテーブル作成すると4×2=8byteのサイズ確保がされますが
--(こちらAL32UTF8を使っている環境です)
--NVARCHAR2型でCHAR列セマンティクスをするとエラーになります。

-- varchar2やchar型についてはCHAR列セマンティクス指定可能
create table EX118 (lno number,name_vc varchar2(2 CHAR));

-- nvarchar2やnchar型では文法エラー
create table EX120 (lno number,name_vc nvarchar2(2 CHAR));
ORA-00907: 右カッコがありません。

参考

スポンサーリンク