• 数据库的 2个参数 NLS_LENGTH_SEMANTICS 说明,comment 说明


    ###############

    sample 1: NLS_LENGTH_SEMANTICS

    1、数据库字符集选择的是NLS_CHARACTERSET=UTF8,如果NLS_CHARACTERSET=ZHS16GBK就不会有这种情况;

     2、原库中NLS_LENGTH_SEMANTICS=CHAR,新库中NLS_LENGTH_SEMANTICS=BYTE;

     3、主要是第2条造成的,如果字符集是UTF8,字段类型VARCHAR2中一个字符占几个字节是由NLS_LENGTH_SEMANTICS参数决定的,
        如果是BYTE,则一个字符占一个字节,如果是CHAR,则一个字符占四个字节。
        通过下面的语句可以查看实际的data_length长度
        select table_name, column_name, data_type, data_length from cols

    https://www.2cto.com/database/201502/376311.html

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

    邮件内容主要意思是:

    (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 字节长度与字符长度的区别

    此章节从百度文库摘抄,原文地址为:https://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');
    
    insert into tab_t values ('ZHON')
    
    *
    
    ERROR at line 1:
    
    ORA-12899: value too large for column "SYS"."TAB_T"."T_NAME" (actual: 4,maximum: 3)

    从上面测试数据来看,插入三个英文字母成功,在插入四个字母的字符串时失败,提示实际长度为4,但maximum只有3

    (5) 插入中文字符串数据测试

    1)先计划一下“中”字占用几个字节

    SQL> SELECT LENGTHB('中') FROM DUAL;

    LENGTHB('中')

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

    3

    2)插入一个中文汉字

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

    1 row created.

    3)插入两个中文汉字

    SQL> insert into tab_t values ('中国');

    insert into tab_t values ('中国')

    *

    ERROR at line 1:

    ORA-12899: value too large for column "SYS"."TAB_T"."T_NAME" (actual: 6, maximum: 3)

    插入两个中文汉字失败,实际长度为6,字段maximum只有3,在此验证确定,在UTF8下,一个中文汉字占3个字符。

    5.3 将tab_t表的t_name列更改成char长度类型并做可插入长度测试

    (1)将tab_t表的t_name列长度类型更改成char

    SQL>alter table tab_t modify (t_name varchar2(3char));

    (2)验证修改结果

    SQL> selecttable_name,column_name,data_type,char_used from dba_tab_columns wheretable_name='TAB_T' ;

    TABLE_NAME COLUMN_NAME DATA_TYPE CHAR_USED
    
    -------------------- ----------------------- ------------------------- -----------------------------
    
    TAB_T T_NAME VARCHAR2 C

    (3) 插入两个中文汉字
     

    SQL> insert into tab_t values ('中国');
    
    
    
    1 row created.

    varchar2(3 char)插入两个中文汉字成功

    6、小结

    经过对开发人员的需求进行判断,以及纠正其对NLS_LENGTH_SEMANTICS参数用途错误的理解,用修改表字段长度类型的方式解决其面临的实际问题,避免了一次不必要的数据库重启,以及问题得到真正的解决。

    #########2

    oracle导出、导入表和字段的注释

    --导出表的注释

       set heading off; 
       set echo off; 
       set feedback off; 
       set termout on; 
       spool C: able_comment.sql; 
       SELECT 'comment on table ' || t.table_name || ' is '''  || t.comments ||''';' FROM user_tab_comments t; 
       spool off; 
      
       --导入表的注释
         @ C: able_comment.sql;
     
       --导出表字段的注释
       set heading off; 
       set echo off; 
       set feedback off; 
       set termout on; 
       spool C:column_comment.sql; 
       SELECT 'comment on column ' || t.table_name || '.' || t.column_name || ' is '''  || t.comments ||''';' FROM user_col_comments t; 
       spool off; 
     
      --导入表字段的注释
         @ C:column_comment.sql;
     
    https://blog.csdn.net/shipeng1022/article/details/53066558

    oracle 数据导入 数据和备注(comment)乱码问题解决办法

  • 相关阅读:
    可由inetd启动的协议无关时间获取服务器程序
    daemon_inetd函数
    作为守护进程运行的协议无关时间获取服务器程序
    daemon_init函数:调用该函数把普通进程转变为守护进程
    getnameinfo函数
    tcp_connect函数
    20200311 11. 应用生命周期事件
    20200311 10. Web 应用
    20200311 9. 分派请求
    20200311 8. 注解和可插拔性
  • 原文地址:https://www.cnblogs.com/feiyun8616/p/9224331.html
Copyright © 2020-2023  润新知