设为首页 收藏本站
查看: 1240|回复: 0

[经验分享] Oracle 中文记录 及 乱码 判断 说明

[复制链接]

尚未签到

发表于 2016-7-26 09:12:53 | 显示全部楼层 |阅读模式
  

  
  
一. 判断记录中是否有中文
  这个可以使用Length 和 Lengthb 函数。 这个在blog里有说明:
  Oracle Length 和 Lengthb 函数说明
  http://blog.csdn.net/tianlesoftware/article/details/6863797
  
   这种方法使用与字符集为GBK的情况,其他情况不使用。在GBK 字符集下,中文的length 是1个字符,而lengthb 是2个byte。
  
  示例:
  select * from t where length(c1) != lengthb(c1);
  
  
二. 判断记录中是否有乱码
  这里需要使用asciistr 函数,ASCIISTR 的官网说明:
  
  http://download.oracle.com/docs/cd/E11882_01/server.112/e26088/functions014.htm#i1000190
  
  ASCIISTRtakesas its argument a string, or an expression that resolves to a string, in anycharacter set and returns an ASCII version of the string in the databasecharacter set. Non-ASCII characters are converted to the form\xxxx, wherexxxxrepresentsa UTF-16 code unit.
   ASCIISTR函数会把非ASCII 的字符转换成\xxxx 的格式,xxxx 是UTF-16的code unit。
  
  示例:
  SQL> select asciistr('/\/Davecome from 安?庆?') as str from dual;
  /\005C/Dave come from \5B89?\5E86?
  
  这里的’安’ 被转换成了\5B89,‘庆’被转换成了\5E86。
  
  这里要注意一个特殊字符“\”,当它出现的时候转换后的码为“\005C”。
  
  
  当然,我们也可以使用UNISTR函数,把asciistr 的结果反转回来,如:
  SQL>select UNISTR('\5E86') from dual;
  庆
  
  那么当我们的记录中存在中文乱码时,
  select UNISTR('\FFFD') from dual;
  �
  
  注意一点:
  执行以上SQL 不要在sqlplus 里执行,sqlplus 受本地环境影响。到第三方的工具(PL/SQL DEV 或者Toad)里测试。
  
  那么当我们的中文记录变成乱码后,那么转成asciistr的值就会包含2种特殊符号: ? 和 \FFFD 对应的问号。我们只需要匹配这2种符号,就可以判断记录里是否有乱码了。
  
  
  HelloJin 同学提供的判断乱码的存储过程:
  
  /* Formatted on 2011/10/11 16:03:44 (QP5 v5.163.1008.3004) */CREATE OR REPLACE PROCEDURE MessyCode (pv_tbname   IN VARCHAR2,pv_owner    IN VARCHAR2)ISnum        NUMBER;p_flag     NUMBER;p_flag2    NUMBER;p_flagw1   NUMBER;p_flagw2   NUMBER;p_col      VARCHAR2 (30);p_str      VARCHAR2 (1000);p_tbname   VARCHAR2 (30);p_owner    VARCHAR2 (30);BEGINp_tbname := pv_tbname;p_owner := pv_owner;p_flagw1 := 0;p_flagw2 := 0;--  p_tbname:='LANK_F1';--  p_owner:='SYS';--dbms_output.put_line(p_tbname||p_owner);SELECT MAX (COLUMN_ID)INTO p_flagFROM dba_tab_columnsWHERE table_name = p_tbname AND owner = p_owner;-- dbms_output.put_line('Total:'||p_flag);EXECUTE IMMEDIATE 'alter session enable parallel dml';WHILE p_flag > 0LOOPSELECT column_nameINTO p_colFROM dba_tab_columnsWHERE table_name = p_tbname AND COLUMN_ID = p_flag AND owner = p_owner;--用来判断是否有中文,并且表的记录数小于<10000EXECUTE IMMEDIATE'select sum(length('|| p_col|| ')) , sum(lengthb('|| p_col|| ')) from '|| p_owner|| '.'|| p_tbname|| '  where rownum<10000'INTO p_flagw1, p_flagw2;--如果有中文,在判断乱码,这里启用了8个并行查询-- dbms_output.put_line(p_str);IF p_flagw1 <> p_flagw2THENEXECUTE IMMEDIATE'select  /*+ parallel('|| p_tbname|| ',8) */  count('|| p_col|| ') from  '|| p_owner|| '.'|| p_tbname|| ' where asciistr('|| p_col|| ') like ''%??%'' or asciistr('|| p_col|| ') like ''%\FFFD%''  'INTO p_flag2;IF p_flag2 > 0THENDBMS_OUTPUT.put_line (p_owner|| '.'|| p_tbname|| ' Have:'|| p_flag|| ','|| p_col);INSERT INTO resoutVALUES (p_owner,p_tbname,p_flag,p_col);COMMIT;END IF;END IF;--initp_flag2 := 0;p_flag := p_flag - 1;END LOOP;INSERT INTO table_tempVALUES (p_owner, p_tbname);COMMIT;END MessyCode;


  该存储过程由HelloJin同学编写,感谢他的辛勤劳动。
  
  这里的核心语句是:
              || ' where asciistr('|| p_col|| ') like ''%??%'' or asciistr('|| p_col|| ') like ''%\FFFD%''  'INTO p_flag2;


  Oracle Parallel Execution(并行执行)
  http://blog.csdn.net/tianlesoftware/article/details/5854583
  
  如果是因为复制导致的乱码,可以和源库进行匹配,然后使用replace函数替换掉乱码。
  
  下面的SQL 可以处理库之间复制导致的乱码:
  /* Formatted on 2011/10/11 20:29:00 (QP5 v5.163.1008.3004) */DECLAREexec_block     VARCHAR2 (32767);module_block   VARCHAR2 (32767):= 'declare      cur_ucs sys_refcursor;type type_tab_ucs1 is table of $$1.$$2.$$3%type;v_tab_ucs1 type_tab_ucs1;type type_tab_pk1 is table of $$1.$$2.$$4%type;v_tab_pk1 type_tab_pk1;beginopen cur_ucs for select $$3,$$4 from $$1.$$2@$$remotelink;loopfetch cur_ucs bulk collect into v_tab_ucs1,  v_tab_pk1 limit 10000;exit when v_tab_ucs1.count = 0;forall i in 1 .. v_tab_ucs1.countupdate  $$1.$$2set  $$1.$$2.$$3  = v_tab_ucs1(i)where $$1.$$2.$$4 = v_tab_pk1(i);commit;end loop;close cur_ucs;end; ';BEGINFOR i IN (SELECT table_name, col_name FROM tab_col)LOOPexec_block := REPLACE (module_block, '$$1', i.owner);exec_block := REPLACE (module_block, '$$2', i.table_name);EXECUTE IMMEDIATE exec_block;INSERT INTO recordupdateVALUES (i.owner, i.table_name, i.col_name);END LOOP;END;


  该代码同样由HelloJin 同学提供。
  
  

  
  其他文档:
  Common Character Sets Found in InternetEmails [ID 477967.1]
  
  
  
  
  -------------------------------------------------------------------------------------------------------
  Blog: http://blog.csdn.net/tianlesoftware
  Weibo: http://weibo.com/tianlesoftware
  Email: dvd.dba@gmail.com
  DBA1 群:62697716(满); DBA2 群:62697977(满)DBA3 群:62697850(满)
  DBA 超级群:63306533(满); DBA4 群:83829929(满) DBA5群: 142216823(满)
  DBA6 群:158654907(满) DBA7 群:69087192(满)DBA8 群:172855474
  DBA 超级群2:151508914 DBA9群:102954821 聊天 群:40132017(满)
  --加群需要在备注说明Oracle表空间和数据文件的关系,否则拒绝申请

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-249436-1-1.html 上篇帖子: Oracle中recyclebin的保留策略 下篇帖子: Oracle DUL/AUL/ODU 工具说明
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表