设为首页 加入收藏

TOP

纠正要求修改数据库NLS_LENGTH_SEMANTICS参数的错误要求(一)
2015-07-24 11:36:16 来源: 作者: 【 】 浏览:8
Tags:纠正 要求 修改 数据库 NLS_LENGTH_SEMANTICS 参数 错误

1、开发人员错误的要求

先看一封开发人员向某DBA提出的一个“要求修改数据库NLS_LENGTH_SEMANTICS参数并重启数据库”的邮件:

\

?

上面邮件,出于对隐私的保护,对发件人,收件人,数据库名称进行了隐涂。

邮件内容主要意思是:

(1) 源端和目标端数据库的字符集均为SIMPLIFIED CHINESE_CHINA.UTF8,但是源端数据库NLS_LENGTH_SEMANTICS参数的值为char,目标数据库NLS_LENGTH_SEMANTICS参数的值为byte

(2) 邮件中对知识错误的理解:由于源端数据库NLS_LENGTH_SEMANTICS参数的值为char(把1个汉字当成一个字节),目标数据库NLS_LENGTH_SEMANTICS参数的值为byte(把1个汉字占3个字节),所以,源端Varchar2(16)能存储16个汉字,而目标端Varchar2(16)即只能存5个汉字,导致源数据的数据无法插入到目标端数据库中去

(3) 邮件中错误的建议解决办法:将目标端数据库的NLS_LENGTH_SEMANTICS参数的值,改成与源端数据库NLS_LENGTH_SEMANTICS参数相同的值

2、知识的梳理

2.1 NLS_LENGTH_SEMANTICS参数的用途

NLS_LENGTH_SEMANTICS参数是一个专为创建CHAR和VARCHAR2两种字符型的列时,指定使用的字节长度,还是使用字符长度的定义方式,有byte和char两种值,默认为byte。

当设置该参数为BYTE时,定义CHAR列或VARCHAR2列采用字节长度方式;当设置该参数为CHAR时,定义CHAR列或VARCHAR2列采用字符长度的方式。该参数对于数据库中已经存在的列不具备任何用途,只是在创建表,或修改表的列时才具有意义。

2.2 字节长度与字符长度的区别

此章节从百度文库摘抄,原文地址为:http://baike.baidu.com/link?url=gtnaOI4rLZejxtdNISG3z8Vm1IpobqAB4nv3TRSnKh9RwTo2eR8eRkUWUUv00J7INVvGPQ2O51o-r77SfyIwT_

(1)ASCII码:

一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。如一个ASCII码就是一个字节。

(2)UTF-8编码:

一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。

(3) Unicode编码:

一个英文等于两个字节,一个中文(含繁体)等于两个字节。

(4) 符号:

一个英文标点占一个字节,一个中文标点占两个字节。举例:英文句号“.”占1个字节的大小,中文句号“。”占2个字节的大小。

3、邮件中对知识错误的理解

邮件中要求修改目标端数据库NLS_LENGTH_SEMANTICS参数,是完全错误的解决方案,之所以出现这样的情况,是因为此开发人员对NLS_LENGTH_SEMANTICS参数的理解不正确。

该开发人员,错误的将NLS_LENGTH_SEMANTICS参数理解成,只要该参数一改,数据库中所有的涉及CHAR和VARCHAR2两种字符型的列的长度类型都发生变化了。

其实不是,NLS_LENGTH_SEMANTICS参数的值,不对已经存在的列产生任何影响,只是在创建表中的列时,默认的指定列长度类型为byte还是char,如果在创建或修改表的列时指定了长度类型,完全覆盖NLS_LENGTH_SEMANTICS参数的值。

4、剖析问题的真正原因

其实,该开发人员所面对的真正问题原因,是源端表字段的长度类型与目标端表字段长度的类型不一致所致。

问题根本原因搞清楚了,解决方案就容易了,将目标端表的字段长度类型修改成与源端一样,不就解决了木。何必修改数据库参数还重启数据库的。

下面以三条create table的语句说清楚NLS_LENGTH_SEMANTICS参数的用途

(1)两条指定长度类型的SQL语句

create table tab_t(t_name varchar2(20byte));

create table tab_t(t_name varchar2(20char));

上面两条语句,唯一的不同,就是在指定列长度为20后,再指定长度的类型,类型的值不同。

(2)不指定长度类型的SQL语句

create table tab_t(t_name varchar2(20));

这条语句,在指定列的长度为20后,并未指定长度的类型,那它的类型会是什么呢,这个就是由NLS_LENGTH_SEMANTICS参数的值所决定了,该参数值可以在会话级设定。

5、测试验证

5.1 确认数据库的字符集类型

SQL> select *from nls_database_parameters t where t.parameter='NLS_CHARACTERSET';

PARAMETER VALUE

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

NLS_CHARACTERSET AL32UTF8

?

5.2 创建列长度类型为byte的表并测试可插入数据长度

(1)查看NLS_LENGTH_SEMANTICS参数当前值

SQL> selectname,value from v$parameter where upper(name)='NLS_LENGTH_SEMANTICS';

NAME VALUE

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

nls_length_semantics BYTE

?

(2)创建带列长度类型为byte的表

SQL>create table tab_t(t_name varchar2(3));

(3)查看新创建的tab_t表的t_name列长度类型

SQL>select table_name,column_name,data_type,char_usedfrom dba_tab_columns where table_name='TAB_T'
?

TABLE_NAME COLUMN_NAME DATA_TYPE CHAR_USED

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

TAB_T T_NAME VARCHAR2 B

(4)插入英文字符串数据测试

$ export NLS_LANG=AMERICAN_AMERICA.UTF8

--注意上面这一条,设置客户端字符集很重要,如果环境变量有设置,此步可以跳过。如果发生复杂的字符集转换,一个中文汉字有可能会占用6个字节

?

SQL> insert into tab_t values ('ZHO');

1 row created.



SQL> insert into tab_t values ('ZHON');
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇【翻译自mos文章】使用索引快速全.. 下一篇管理ONS(OracleNotificationServi..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Shell 中各种括号的 (2025-12-24 19:50:39)
·Shell 变量 - 菜鸟教 (2025-12-24 19:50:37)
·Linux source 命令 - (2025-12-24 19:50:34)
·switch520最新的地址 (2025-12-24 19:19:41)
·微信聊天功能使用了 (2025-12-24 19:19:39)