我创建了2个表并插入数据如下---
SQL> create table t (aa nvarchar2(10));
Table created.
SQL> create table t1 (aa varchar2(10));
Table created.
现在,插入一些法语字符,如下所示 -
SQL> insert into t values ('Éé, Eè, Eê, Eë');
insert into t values ('Éé, Eè, Eê, Eë')
*
ERROR at line 1:
ORA-12899: value too large for column "CDUREFDB"."T"."AA" (actual: 14, maximum:
10)
SQL> insert into t1 values ('Éé, Eè, Eê, Eë');
insert into t1 values ('Éé, Eè, Eê, Eë')
*
ERROR at line 1:
ORA-12899: value too large for column "CDUREFDB"."T1"."AA" (actual: 21,
maximum: 10)
问题是为什么两个插入中的错误消息都有差异。
以下是NLS参数详情:
SQL> SELECT *
2 FROM v$nls_parameters
3 WHERE parameter LIKE '%CHARACTERSET'
4 ;
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_CHARACTERSET
AL32UTF8
NLS_NCHAR_CHARACTERSET
UTF8
我正在使用Oracle 11g
版本。
另外,是否建议在oracle中使用NVARCHAR2(NCHAR etc.)
非英语字符?
感谢。
答案 0 :(得分:2)
如果你问为什么"实际"错误消息中的值不同,答案是长度语义。
当您声明nvarchar2(n)
时,您隐式使用字符长度语义。 nvarchar2(n)
为nls_nchar_characterset
中的n个字符分配空间,而不管所需的字节数。您尝试在nvarchar2(10)
中插入一个14个字符的字符串,这样您就可以得到14作为错误的实际长度。
当您声明varchar2(n)
时,您将为n个字节或n个存储字符分配空间,具体取决于您的会话nls_length_semantics
。默认情况下,这是byte
,因此您可以为10个字节分配空间。您的一些字符在nls_characterset
中需要超过1个字节的存储空间,因此您的14个字符的字符串将需要21个字节的存储空间。这就是为什么你得到21作为错误中的实际长度的原因。我希望如果您使用字符长度语义将列声明为varchar2(n char)
,则报告的实际大小将为14。
如果您的数据库字符集支持Unicode,则很少有理由使用nvarchar2
。当您的数据库和国家字符集都是UTF-8时,使用nvarchar2
毫无意义。