关于Oracle一个汉字代表几个字节的问题(转)

[b]ps:本人破解了润乾报表,全部功能可用,低价销售,需要要的请加qq:229501642联系[/b]

在Oracle定义变量时,常有VARCHAR2 (3 Char)或者VARCHAR2 (10 Byte)的数据类型,那么3char或者10Byte到底代表几个汉字,几个字符呢,上次外公司一同事讨论这个问题,一下没给解释清楚,所以下来以后整理如下:

总结:
当NLS_CHARACTERSET=AL32UTF8时()
NLS_LENGTH_SEMANTICS=BYTE时,一个汉字代表三个字节
NLS_LENGTH_SEMANTICS=CHAR时,一个汉字代表一个字节
当NLS_CHARACTERSET=US7ASCII时(字符集为单字节)
NLS_LENGTH_SEMANTICS=BYTE时,一个汉字代表两个字节
NLS_LENGTH_SEMANTICS=CHAR时,一个汉字代表两个字节

现象:
select * from nls_database_parameters;
…. …………..
NLS_CHARACTERSET AL32UTF8

…..

NLS_LENGTH_SEMANTICS BYTE

….

NLS_NCHAR_CHARACTERSET AL16UTF16

NLS_RDBMS_VERSION 10.2.0.4.0


SQL> alter session set nls_length_semantics='BYTE';

SQL> create table nls_byte(c1 varchar2(7));

SQL> insert into nls_byte values('测试机');

insert into nls_byte values('测试机')

ORA-12899: 列 "SYS"."NLS_BYTE"."C1" 的值太大 (实际值: 9, 最大值: 7)

SQL> insert into nls_byte values('测试a');

1 row inserted

SQL> select table_name,column_name,t.DATA_TYPE,t.DATA_LENGTH,t.CHAR_USED from user_tab_columns t where table_name='NLS_BYTE';

TABLE_NAME COLU DATA_TYP DATA_LENGTH CHAR_USED

---------- ---- -------- ----------- ---------

NLS_BYTE C1 VARCHAR2 7 B

NLS_LENGTH_SEMANTICS allows you to specify the length of a column datatype in terms of CHARacters rather than in terms of BYTEs. Typically this is when using an AL32UTF8 or other varying width NLS_CHARACTERSET database where one character is not always one byte. While using CHAR semantics has as such no added value in a 7/8 bit characterset it's fully supported so any application code / table setup using CHAR can also be used in a 7/8bit characterset like US7ASCII/WE8MSWIN1252.
This parameter is a 9i (and up) feature and is not available in older releases

翻译过来就是:这个参数允许将列的数据单位设为字符而不是byte.这个问题会在字符集设为UTF8的时候出现. 此参数在9i以上版本有效.

NLS_LENGTH_SEMANTICS 设置.

1. NLS_DATABASE_PARAMETERS中的值是在数据库创建的时候确定的,一般都为BYTE

2. 此参数可以以 “ALTER SYSTEM SET NLS_LENGTH_SEMANTICS=CHAR scope=both”方式修改,但是需要重启数据库才能生效.

3. 也可用” ALTER SESSION SET NLS_LENGTH_SEMANTICS=CHAR”使对当前session生效.

4. 此参数可以在10G以上版本中,在环境变量或注册表中设置(注意需要大写),设定后从当前客户端启动的所有会话都采用新的取值.

5. 修改后只对新建的列生效,对于已有的列没有作用

6. 新建或升级DB时用BYTE,否则XDB或dba_tables会出现问题.

7. NLS_LENGTH_SEMANTICS对sys用户下的对象无效.

8. 如果对于7/8bit的字符集,设为byte/char意义不大,因为无论是char和byte都对应一个byte.

测试:

一.在当前session中修改此参数

SQL> alter session set nls_length_semantics='char';

Session altered

SQL> create table nls_char(c1 varchar2(7),c2 varchar2(7));

Table created

SQL> desc nls_char

Name Type Nullable Default Comments

---- ----------- -------- ------- --------

C1 VARCHAR2(7) Y

C2 VARCHAR2(7) Y

SQL> insert into nls_char values('测试机','测试测试测试');

1 row inserted

如果对于alter system,效果是一样的

二.对于已经存在的表,

SQL> desc nls_byte

Name Type Nullable Default Comments

---- ---------------- -------- ------- --------

C1 VARCHAR2(7 BYTE) Y

SQL> alter table nls_byte modify c1 varchar2(7 char);

Table altered

SQL> desc nls_byte

Name Type Nullable Default Comments

---- ----------- -------- ------- --------

C1 VARCHAR2(7) Y

SQL> insert into nls_byte values('测试机');

1 row inserted

1. exp/imp : 不能直接导入,因为会采用source table的建表方式在target db里建表,即使目标库设的值为char.

*可以预先在目标库中以char方式建表

*然后导入,指定参数ignore=y

2. Alter table

alter table "<owner>"."<table>" modify "<column>" char (10 char);

创建脚本,修改列设定.

注:

Bug-3611750, ora-01450 online rebuild of index fails, 可以在重建索引前指定byte, 10.2.0.5以上已经修复

Bug 1488174 UNICODE: ALTER SYSTEM SET NLS_LENGTH_SEMANTICS DOESN'T
TAKE EFFECT, 用此语句修改后,实际上不起作用,需要重启才能生效, 但是如果用alter session方式即时生效,不用重启.

进一步测试,在另一个字符集设为us7ascii的DB设置此参数

SQL> select * from nls_database_parameters

6 NLS_CHARACTERSET US7ASCII

SQL> alter session set nls_length_semantics=byte;

Session altered.

SQL> create table nls_byte(c1 varchar2(7));

Table created.

SQL> insert into nls_byte values('测试测试');

insert into nls_byte values('测试测试')

ERROR at line 1:

ORA-12899: value too large for column "TEA"."NLS_BYTE"."C1" (actual: 8,

maximum: 7)

SQL> desc nls_byte

Name Null? Type

-------------------------------

C1 VARCHAR2(7)

SQL> alter session set nls_length_semantics=char;

Session altered.

SQL> create table nls_char(c1 varchar2(7));

Table created.

SQL> insert into nls_char values('测试测试');

insert into nls_char values('测试测试')

ERROR at line 1:

ORA-12899: value too large for column "TEA"."NLS_CHAR"."C1" (actual: 8,

maximum: 7)

SQL> desc nls_char

Name Null? Type

----------------------------------------- -------- -------------------

C1 VARCHAR2(7)

可以看出,在字符集为单字节的情况下,无论取何值,汉字都是以二个字节的方式存在的.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值