Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2322594
  • 博文数量: 310
  • 博客积分: 6853
  • 博客等级: 准将
  • 技术积分: 2833
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-04 16:41
文章分类

全部博文(310)

文章存档

2013年(17)

2012年(42)

2011年(76)

2010年(71)

2009年(99)

2007年(2)

2006年(1)

2005年(2)

分类: Oracle

2010-03-15 17:09:30

先介绍一下shell所在的环境:
操作系统 Linux Suse 9 数据库 Oracle 9i

Suse的环境变量:
NLS_LANG=SIMPLIFIED CHINESE_CHINA.UTF8 (控制Oracle客户端应用程序使用的字符集)
LANG=zh_CN.gbk(操作系统的语言字符集)

Oracle服务器的字符集:UTF8(Oracle服务器端的字符集)


shell的执行方式:先用ftp工具将脚本以asc方式上传至Suse上,然后利用telnet工具登录Suse来运行shell。下面 一段为原始shell,即执行结果出现乱码问题的代码。功能是通过调用存储过程,获得返回出参,并将出参值写到目标文件 DelProductInfoResult.txt中:

send_day=`sqlplus -s $db_conn_cmd <<EOF
set serveroutput on
set pagesize 0
set linesize 32767
set feedback off
DECLARE
ret1 
varchar2(1000);
BEGIN
 zxdbm_ismp.product_delete(
'${v_productid}',ret1);
 DBMS_OUTPUT.PUT_LINE(ret1);
END;
/
exit;
EOF`

 

del_info=`echo $send_day|awk '{ print $1 }'`
echo "del_time:"$v_time
echo $del_info
echo $del_info
>>$vac_product_path"/result/"$v_time"DelProductInfoResult.txt"


上面2段原始脚本被执行后:
telnet工具的屏幕上打印的变量del_info为:111100027100000000026|鎴愬姛|浜у搧锛?|涓氬姟锛?|浜у搧鎸囦护锛
同 时,目标文件DelProductInfoResult.txt中的内容也为:111100027100000000026|鎴愬姛|浜у搧锛?|涓氬姟锛?|浜у搧鎸囦护锛

分析原 因:Suse系统上的oracle客户端的NLS_LANG变量为:SIMPLIFIED CHINESE_CHINA.UTF8, 当存储过程zxdbm_ismp.product_delete('${v_productid}',ret1);执行后,通过sqlplus将返回值打 印在telnet工具屏幕上,由于Suse的操作系统环境变量LANG=zh_CN.gbk,导致返回的中文信息写到telnet屏幕上时,ret1的值 显示为乱码。即对于下面PL/SQL语句:

set serveroutput on
set pagesize 0
set linesize 32767
set feedback off
DECLARE
ret1 
varchar2(1000);
BEGIN
 zxdbm_ismp.product_delete(
'111100027100000000026',ret1);
 DBMS_OUTPUT.PUT_LINE(ret1);
END;
/

【1】当SUSE的NLS_LANG为SIMPLIFIED CHINESE_CHINA.UTF8时,telnet到Suse后,sqlplus连上Oracle并执行上面的PL/SQL语句后,ret1的打印信 息如下:
SQL> set serveroutput on
SQL> set pagesize 0
SQL> set linesize 32767
SQL> set feedback off
SQL> DECLARE
  2  ret1 varchar2(1000);
  3  BEGIN
  4   zxdbm_ismp.product_delete('111100027100000000026',ret1);
  5   DBMS_OUTPUT.PUT_LINE(ret1);
  6  END;
  7  /
111100027100000000026|鎴愬姛|浜у搧锛?|涓氬姟锛?|浜у搧鎸囦护锛?

【2】当SUSE的NLS_LANG为SIMPLIFIED CHINESE_CHINA.ZHS16GBK时,telnet到Suse后,sqlplus连上Oracle并执行上面的PL/SQL语句后,ret1 的打印信息如下:
SQL> set serveroutput on
SQL> set pagesize 0
SQL> set linesize 32767
SQL> set feedback off
SQL> DECLARE
  2  ret1 varchar2(1000);
  3  BEGIN
  4   zxdbm_ismp.product_delete('111100027100000000026',ret1);
  5   DBMS_OUTPUT.PUT_LINE(ret1);
  6  END;
  7  /
111100027100000000026|成功|产品:1|业务:1|产品指令:0


乱 码问题的解决思路:

经过将Suse的NLS_LANG变量更改为SIMPLIFIED CHINESE_CHINA.ZHS16GBK,该问题得到解决。
开头的原始shell脚本被执行后:
telnet工具的屏幕上打印的变 量del_info为:111100027100000000026|成 功|产品:1|业务:1|产品指令:0
同时,目标文件DelProductInfoResult.txt中的内容也为:111100027100000000026|成功|产品:1|业务:1|产品指 令:0

但是,按照这修改操作系统的环境变量NLS_LANG来实现乱码问题的解决始终不是好的方法,这样的更改操作系统环 境变量,会影响到运行在该系统上的其他应用程序的运行。

鉴于这样,就得来通过扩展shell脚本的功能代码,来适应在特定操作系统的环境 变量下,没有乱码出现。

下面一段代码,通过判断操作系统NLS_LANG值,如果是UTF8,则先将变量del_info的值写到临时文 件中,再通过iconv命令将临时文件的内容的编码方式由utf8转换为gb2312,以跟操作系统的LANG环境变量保持一致,再将转换编码方式后的临 时文件的内容写到目标文件DelProductInfoResult.txt中。这样,就在不更改操作系统NLS_LANG变量的情况下,实现乱码问题的 解决:

if [ -d "$NLS_LANG" ]
        
then    
            echo "NLS_LANG 
not set!"
            
exit
        
else    
            echo "NLS_LANG:" $NLS_LANG
            
if [ "$NLS_LANG" = "SIMPLIFIED CHINESE_CHINA.UTF8" ]
            
then    
                del_info
=`echo $send_day|awk '{ print $1 }'`
                echo "del_time:"$v_time
                echo $del_info
                echo $del_info 
>$vac_product_path"/cc.temp"
                iconv 
-f utf-8 -t gb2312 $vac_product_path"/cc.temp>> $vac_product_path"/result/"$v_time"DelProductInfoResult.txt"
                rm 
-f $vac_product_path"/cc.temp"
            
else
                del_info
=`echo $send_day|awk '{ print $1 }'`
                echo "del_time:"$v_time
                echo $del_info
                echo $del_info 
>>$vac_product_path"/result/"$v_time"DelProductInfoResult.txt"
            fi
        fi
阅读(6866) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~