为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

Oracle 中英文字符集转换解决方案

2017-09-01 19页 doc 116KB 47阅读

用户头像

is_153723

暂无简介

举报
Oracle 中英文字符集转换解决方案Oracle 中英文字符集转换解决方案 技术文档 Oracle 中英文字符集转换解决方案 背景说明: 目前国内用户使用的ORACLE字符集,大部分所采用的都是 ZHS16GBK – GBK 16位简体中文 ,而很少采用US7ASCII – ASCII 7位美国英语 。 现在所遇到的问题就是,如何解决在US7ASCII字符集和ZHS16GBK字符集的数据库实例下进行数据访问,以及进行导入、导出数据的时候出现汉字乱码的问题。 解决方案: 目前比较好的解决方案在网上几乎是没有的,也是行不通的,对于其他单位或许会有相应的解...
Oracle 中英文字符集转换解决方案
Oracle 中英文字符集转换解决 技术文档 Oracle 中英文字符集转换解决方案 背景: 目前国内用户使用的ORACLE字符集,大部分所采用的都是 ZHS16GBK – GBK 16位简体中文 ,而很少采用US7ASCII – ASCII 7位美国英语 。 现在所遇到的问题就是,如何解决在US7ASCII字符集和ZHS16GBK字符集的数据库实例下进行数据访问,以及进行导入、导出数据的时候出现汉字乱码的问题。 解决方案: 目前比较好的解决方案在网上几乎是没有的,也是行不通的,对于其他单位或许会有相应的解决方案,但是也会因为是内部资料或者保密,或者流失。经过近期的研究,总算有了一个比较好的解决方案。其中采用的主要方法是利用ORACLE的utl_raw包中的cast_to_varchar2()、cast_to_raw()两个方法。服务器架构如下图所示: 应用服务器源数据库实例业务数据库实例 (US7ASCII)(ZHS16GBK) dblink 源数据库服务器目标数据库服务器 图1.1 服务器数据存储结构 如上图所示,有两台服务器,目标要求在“应用服务器”访问的“目标数据库服务器”上能读取“源数据库服务器”上的数据,但是由于“目标数据库服务器”和“源数据服务器”的数据库字符集不一致,所以简单的建立一个dblink进行数据的访问就会出现汉字乱码的问题,所以还要进行一些字符的转换工作,步骤如下: 1、首先在“源数据库服务器”上建立视图,供“目标数据库服务器”调用。视图建立的规则:将视图中中文汉字的字段进行转换,转换函数为cast_to_raw(), 如 a表中有a1,a2,a3三个字段,其中a2字段为中文汉字,那么建立的视图的语句就可以是: create view v_a as select a1 as a1, utl_raw.cast_to_raw(a2) as a2, a3 as a3 from a; 2、在“目标数据库服务器”建立dblink: 如: create database link dbl_1 connect to test identified by test using 'oradb'; 3、在“目标数据库服务器”直接使用dblink进行数据访问,当然需要加上中文汉字转换函数了。格式如下: QQ- 154955209 技术文档 select a1, utl_raw.cast_to_varchar2(a2), a3 from v_a@bdl_1; 如上所示,我们基本就能完成在“目标数据服务器”对“源数据库服务器”的数据访问,但是目前网站程序不允许实时去访问“源数据库服务器”,而且也不能在“源数据库服务器”建立视图。所以要在自己的“目标数据库服务器”上同时建立一个ZHS16GBK业务数据库实例和一个US7ASCII的中间转换数据库实例,通过“中间转换数据库实例”使用dblink连接“源数据库服务器”实现数据的共享和实时连接,然后在“业务数据库实例”下通过dblink再连接“中间转换数据库实例”进行字符集的转换。具体图示如下: 应用服务器 中间转换数据库实例业务数据库实例源数据库实例(US7ASCII)(ZHS16GBK)(US7ASCII)dblinkdblink 源数据库服务器目标数据库服务器 图1.2 新版网站数据库服务器结构 具体实现方法如下: 1、在“目标数据库服务器”建立两个不同字符集的数据库实例; 注:这里在安装数据库实例的时候,最好先安装 US7ASCII ,再安装 ZHS16GBK。这样能保证操作系 统最后的字符集是ZHS16GBK,如果相反的话,则需要修改操作系统的注册表或者配置文件 (window注册表修改位置: HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE ,搜索 NLS_LANG 键值,将其修改为 SIMPLIFIED CHINESE_CHINA.ZHS16GBK) 2、在“中间转换数据库实例”建立dblink链接“源数据库实例”; create database link CB_DBAST.REGRESS.RDBMS.DEV.US.ORACLE.COM connect to JYZX identified by "xzyj" using '(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.128.5.43)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = dbast) ) )'; 3、在“中间转换数据库实例”建立视图访问“源数据库实例”的数据;以其中一个表作为例 子。 QQ- 154955209 技术文档 注:将所有字段类型为 字符型(varcha2)的字段全部使用 UTL_RAW.CAST_TO_RAW() 方法进行转 换;存储过程如下: create or replace procedure pro_createview is cbsql varchar2(3000); cb_cname varchar2(30); cb_coltype varchar2(106); sbsql varchar2(3000); scbdata varchar2(3000); type cur_data is ref cursor; cdata cur_data; cursor cur_cb is select view_name from all_views@cb_dbast where owner = 'JYZX'; begin for rec_cb IN cur_cb loop cbsql := 'select cname , coltype from col@cb_dbast where tname= ''' || rec_cb.view_name || ''''; scbdata := ''; open cdata for cbsql; loop fetch cdata into cb_cname, cb_coltype; exit when cdata%NOTFOUND; if cb_coltype = 'VARCHAR2' then scbdata := scbdata || ' UTL_RAW.CAST_TO_RAW(' || cb_cname || ') ' || cb_cname || ','; elsif cb_coltype = 'LONG' then scbdata := scbdata; else scbdata := scbdata || cb_cname || ','; end if; end loop; close cdata; scbdata := substr(scbdata, 0, length(scbdata) - 1); sbsql := ' create or replace view v_' || rec_cb.view_name || ' as select ' || scbdata || ' from ' || rec_cb.view_name || '@cb_dbast'; execute immediate sbsql; commit; end loop; end pro_createview; 4、在“业务数据库实例”建立dblink链接“中间转换数据库实例”; create database link CB.REGRESS.RDBMS.DEV.US.ORACLE.COM QQ- 154955209 技术文档 connect to CB identified by "cb" using 'ora_cb'; 5、在“业务数据库实例”建立数据转换临时表和存储过程 (1)建立临时表 CB_OBJ(船舶转换数据表) CB_LOG(船舶数据转换日志表) -------------------------------------------------------------------------------- create table CB_OBJ ( CB_TBL VARCHAR2(30), CB_VIEW VARCHAR2(30) ) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage ( initial 64K minextents 1 maxextents unlimited ); -- Add comments to the table comment on table CB_OBJ is '船舶转换数据'; -- Add comments to the columns comment on column CB_OBJ.CB_TBL is '船舶转换数据表名'; -- Add comments to the columns comment on column CB_OBJ.CB_VIEW is '船舶转换来源视图'; -------------------------------------------------------------------------------- create table CB_LOG ( CB_OBJ VARCHAR2(30), CB_DATE DATE, CB_NUM NUMBER ) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage ( QQ- 154955209 技术文档 initial 64K minextents 1 maxextents unlimited ); -- Add comments to the table comment on table CB_LOG is '船舶转换数据日志表'; -- Add comments to the columns comment on column CB_LOG.CB_OBJ is '船舶数据表名'; comment on column CB_LOG.CB_DATE is '转换时间'; comment on column CB_LOG.CB_NUM is '转换数量'; -------------------------------------------------------------------------------- (2)向临时表中插入数据 insert into CB_OBJ (CB_TBL, CB_VIEW) values ('BWXX', 'V_BWXX@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('B_00031', 'V_B_00031@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('B_00038', 'V_B_00038@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('B_00158', 'V_B_00158@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBDA', 'V_CBDA@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBDT_DTJH', 'V_CBDT_DTJH@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBDT_DTSJ', 'V_CBDT_DTSJ@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBDT_JCZ', 'V_CBDT_JCZ@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBDT_XCDT', 'V_CBDT_XCDT@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBZY_FCZY', 'V_CBZY_FCZY@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBZY_PG', 'V_CBZY_PG@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBZY_PG_FB', 'V_CBZY_PG_FB@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CBZY_ZYJH', 'V_CBZY_ZYJH@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CCMB', 'V_CCMB@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CDXX', 'V_CDXX@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('CGSXX', 'V_CGSXX@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('TBSJ', 'V_TBSJ@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('VIEW_ZZJG_CDXX', 'V_VIEW_ZZJG_CDXX@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('WQD', 'V_WQD@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('YQB', 'V_YQB@CB'); insert into CB_OBJ (CB_TBL, CB_VIEW) values ('ZZJG', 'V_ZZJG@CB'); commit; (3)建立船舶数据表 建立如下存储过程进行执行 create or replace procedure pro_cb_createtable is cbsql varchar2(3000); sbsql varchar2(3000); QQ- 154955209 技术文档 cbdata varchar2(3000); cb_cname varchar2(30); cb_coltype varchar2(106); cb_width varchar2(30); cb_nulls varchar2(30); type cur_data is ref cursor; cdata cur_data; cursor cur_cb is select cb_tbl, cb_view from cb_obj; begin for rec_cb IN cur_cb loop cbsql := ' select cname,coltype,width ,nulls from col@cb_dbast where tname= ''' || rec_cb.cb_tbl || ''''; cbdata := ''; open cdata for cbsql; loop fetch cdata into cb_cname, cb_coltype, cb_width, cb_nulls; exit when cdata%NOTFOUND; if cb_coltype in ('VARCHAR2', 'CHAR') then cbdata := cbdata || cb_cname || ' ' || cb_coltype || '(' || cb_width || ') ' || cb_nulls || ' ,'; else cbdata := cbdata || cb_cname || ' ' || cb_coltype || ' ' || cb_nulls || ' ,'; end if; end loop; close cdata; cbdata := substr(cbdata, 0, length(cbdata) - 1); sbsql := ' create table ' || rec_cb.cb_tbl || ' (' || cbdata || ') '; execute immediate sbsql; end loop; end pro_cb_createtable; (4)船舶数据转换存储过程 create or replace procedure pro_cb is cbsql varchar2(3000); --执行取表字段名称和字段类型的动态sql cb_cname varchar2(30); -- 取表的字段名称 cb_coltype varchar2(106); --取表的字段类型 sbsql varchar2(3000); --执行插入操作的动态sql scbdata varchar2(3000); --拼写插入动态sql select的字段 QQ- 154955209 技术文档 icbdata varchar2(3000); --拼写插入动态sql into的字段 type cur_data is ref cursor; --定义动态sql类型 cdata cur_data; --临时表游标 cursor cur_cb is select cb_tbl, cb_view from cb_obj; begin --循环游标 循环临时表中需要转换的表单 for rec_cb IN cur_cb loop --定义读取字段名称和字段类型的动态sql cbsql := 'select cname , coltype from col where tname= ''' || rec_cb.cb_tbl || ''''; --初始化变量 icbdata := ''; scbdata := ''; --打开动态sql游标 open cdata for cbsql; --循环动态sql loop fetch cdata into cb_cname, cb_coltype; exit when cdata%NOTFOUND; if cb_coltype = 'VARCHAR2' then scbdata := scbdata || ' utl_raw.cast_to_varchar2(' || cb_cname || '), '; icbdata := icbdata || cb_cname || ','; else icbdata := icbdata || cb_cname || ','; scbdata := scbdata || cb_cname || ','; end if; end loop; --关闭动态sql游标 close cdata; --对拼写的字段进行处理去除最后的"," icbdata := substr(icbdata, 0, length(icbdata) - 1); scbdata := substr(scbdata, 0, length(scbdata) - 1); sbsql := ' insert into ' || rec_cb.cb_tbl || ' (' || icbdata || ') select ' || scbdata || ' from ' || rec_cb.cb_view; --清除原始数据 execute immediate ' truncate table ' || rec_cb.cb_tbl; commit; --此处必须提交,不然下面执行的时候会死锁 --执行插入操作 execute immediate sbsql; commit; QQ- 154955209 技术文档 end loop; end pro_cb; 6、在“业务数据库实例”建立job定期执行存储过程进行数据更新。 declare job number ; begin sys.dbms_job.SUBMIT(job => job, what => 'pro_cb;', next_date => to_date('20-10-2009 09:22:00', 'dd-mm-yyyy hh24:mi:ss'), interval => 'trunc(sysdate)+1+1/24'); --24小时执行一次 commit; end; / 附录:oracle JOB使用详解 每天1点执行的oracle JOB样例 DECLARE X NUMBER; BEGIN SYS.DBMS_JOB.SUBMIT ( job => X, what => 'ETL_RUN_D_Date;', next_date => to_date('2009-08-26 01:00:00','yyyy-mm-dd hh24:mi:ss'), interval => 'trunc(sysdate)+1+1/24', no_parse => FALSE ); SYS.DBMS_OUTPUT.PUT_LINE('Job Number is: ' || to_char(x)); COMMIT; END; / 以上是明确指定每天的1点执行此job,如果指定是每天中午12点执行interval需要指定为 'trunc(sysdate)+1+12/24',如果仅仅指定interval为一天,这样当你手工用dbms_job.run(job)去运行一 次时,job每天的执行时间是会改变的,如果你想job每天在固定时间执行,可以参考上面的例子. 初始化相关参数job_queue_processes alter system set job_queue_processes=39 scope=spfile;//最大值不能超过1000 ;job_queue_interval = 10 //调度作业刷新频率秒为单位 QQ- 154955209 技术文档 job_queue_process 表示oracle能够并发的job的数量,可以通过语句 show parameter job_queue_process; 来查看oracle中job_queue_process的值。当job_queue_process值为0时表示全部停止oracle的 job,可以通过语句 ALTER SYSTEM SET job_queue_processes = 10; 来调整启动oracle的job。 相关视图: dba_jobs all_jobs user_jobs dba_jobs_running 包含正在运行job相关信息 ,,,,,,,,,,,,,,,,,,,,,,,,, 提交job语法: begin sys.dbms_job.submit(job => :job, what => 'P_CLEAR_PACKBAL;', next_date => to_date('04-08-2008 05:44:09', 'dd-mm-yyyy hh24:mi:ss'), interval => 'sysdate+ 1/360'); commit; end; / ,,,,,,,,,,,,,,,,,,,,,,,,, 创建JOB variable jobno number; begin dbms_job.submit(:jobno, 'P_CRED_PLAN;',SYSDATE,'SYSDATE+1/2880',TRUE); commit; 运行JOB SQL> begin dbms_job.run(:job1); end; / 删除JOB SQL> begin dbms_job.remove(:job1); end; / DBA_JOBS ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,, 字段(列) 类型 描述 JOB NUMBER 任务的唯一标示号 LOG_USER VARCHAR2(30) 提交任务的用户 PRIV_USER VARCHAR2(30) 赋予任务权限的用户 QQ- 154955209 技术文档 SCHEMA_USER VARCHAR2(30) 对任务作语法分析的用户模式 LAST_DATE DATE 最后一次成功运行任务的时间 LAST_SEC VARCHAR2(8) 如HH24:MM:SS格式的last_date日期的小时,分钟和秒 THIS_DATE DATE 正在运行任务的开始时间,如果没有运行任务则为null THIS_SEC VARCHAR2(8) 如HH24:MM:SS格式的this_date日期的小时,分钟和秒 NEXT_DATE DATE 下一次定时运行任务的时间 NEXT_SEC VARCHAR2(8) 如HH24:MM:SS格式的next_date日期的小时,分钟和秒 TOTAL_TIME NUMBER 该任务运行所需要的总时间,单位为秒 BROKEN VARCHAR2(1) 标志参数,Y标示任务中断,以后不会运行 INTERVAL VARCHAR2(200) 用于计算下一运行时间的表达式 FAILURES NUMBER 任务运行连续没有成功的次数 WHAT VARCHAR2(2000) 执行任务的PL/SQL块 CURRENT_SESSION_LABEL RAW MLSLABEL 该任务的信任Oracle会话符 CLEARANCE_HI RAW MLSLABEL 该任务可信任的Oracle最大间隙 CLEARANCE_LO RAW MLSLABEL 该任务可信任的Oracle最小间隙 NLS_ENV VARCHAR2(2000) 任务运行的NLS会话设置 MISC_ENV RAW(32) 任务运行的其他一些会话参数 ,,,,,,,,,,,,,,,,,,,,,,,,,, 描述 INTERVAL参数值 每天午夜12点 'TRUNC(SYSDATE + 1)' 每天早上8点30分 'TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)' 每星期二中午12点 'NEXT_DAY(TRUNC(SYSDATE ), ''TUESDAY'' ) + 12/24' 每个月第一天的午夜12点 'TRUNC(LAST_DAY(SYSDATE ) + 1)' 每个季度最后一天的晚上11点 'TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24' 每星期六和日早上6点10分 'TRUNC(LEAST(NEXT_DAY(SYSDATE, ''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) + (6×60+10)/(24×60)' ,,,,,,,,,,,,,,,,,,,,,,,,,, 1:每分钟执行 Interval => TRUNC(sysdate,'mi') + 1/ (24*60) 或 Interval => sysdate+1/1440 2:每天定时执行 例如:每天的凌晨1点执行 Interval => TRUNC(sysdate) + 1 +1/ (24) 3:每周定时执行 例如:每周一凌晨1点执行 Interval => TRUNC(next_day(sysdate,'星期一'))+1/24 4:每月定时执行 例如:每月1日凌晨1点执行 Interval =>TRUNC(LAST_DAY(SYSDATE))+1+1/24 5:每季度定时执行 例如每季度的第一天凌晨1点执行 Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'Q') + 1/24 6:每半年定时执行 QQ- 154955209 技术文档 例如:每年7月1日和1月1日凌晨1点 Interval => ADD_MONTHS(trunc(sysdate,'yyyy'),6)+1/24 7:每年定时执行 例如:每年1月1日凌晨1点执行 Interval =>ADD_MONTHS(trunc(sysdate,'yyyy'),12)+1/24 QQ- 154955209
/
本文档为【Oracle 中英文字符集转换解决方案】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索