SQLPLUS编译存储过程见鬼记

SQLPLUS编译存储过程见鬼记
2010-12-24

最近逛天涯,看到了一个帖子,里面有灵异事件的内容,虽然不太相信,但因为无法解释,也让人毛骨悚然。没想到,今天使用SQLPLUS编译存储过程竟然也“见鬼”了,而且这个“鬼”很有意思,于是记录下来。

SQL> set line 120
SQL> set pagesize 9999
SQL> set time on

把待编译的含存储过程的文件载入编辑缓存。为了凸显问题部分,已经去掉了函数中不涉及错误的若干行代码。
10:58:54 SQL> get a.sql
  1  create or replace
  2  function remove_constants( p_query in varchar2 )
  3  return varchar2
  4  as
  5     l_query long;
  6     l_char varchar2(1);
  7     l_in_quotes boolean default FALSE;
  8  begin
  9     l_query := translate( l_query, '0123456789', '@@@@@@@@@@' );
 10     for i in 0 .. 8
 11     loop
 12     l_query := replace( l_query, lpad('@',10‐i,'@'), '@' );
 13     l_query := replace( l_query, lpad(' ',10‐i,' '), ' ' );
 14     end loop;
 15     return upper(l_query);
 16* end;
10:58:57  17
10:59:02 SQL> l
  1  create or replace
  2  function remove_constants( p_query in varchar2 )
  3  return varchar2
  4  as
  5     l_query long;
  6     l_char varchar2(1);
  7     l_in_quotes boolean default FALSE;
  8  begin
  9     l_query := translate( l_query, '0123456789', '@@@@@@@@@@' );
 10     for i in 0 .. 8
 11     loop
 12     l_query := replace( l_query, lpad('@',10‐i,'@'), '@' );
 13     l_query := replace( l_query, lpad(' ',10‐i,' '), ' ' );
 14     end loop;
 15     return upper(l_query);
 16* end;
10:59:06 SQL> /

Warning: Function created with compilation errors.
#^ 编译出错。

10:59:12 SQL> show err
Errors for FUNCTION REMOVE_CONSTANTS:

LINE/COL
---------------------------------------------------------------------------------
ERROR
------------------------------------------------------------------------------------------------------------------------
11/42
PLS-00103: Encountered the symbol "?" when expecting one of the following:

   ) , * & | = - + < / > at in is mod remainder not rem => ..
   <> or != or ~= >= <= <> and or like LIKE2_
   LIKE4_ LIKEC_ between || multiset member SUBMULTISET_
#^ 编译器声称在11行42列遇到了不合法符号问号“?”
10:59:14 SQL> l 11
 11*    loop
11:01:44 SQL>
#^ 问题是11行总共才一个单词"loop".
#^ 而且,整个文件中也没有什么问号呀!

在EMDC-方案-程序-函数中查看我们的函数remove_constants,发现了端倪:
( p_query in varchar2 )
return varchar2
as
    l_query long;
    l_char varchar2(1);
    l_in_quotes boolean default FALSE;
begin
    l_query := translate( l_query, '0123456789', '@@@@@@@@@@' );
    for i in 0 .. 8
    loop
    l_query := replace( l_query, lpad('@',10?\i,'@'), '@' );
    l_query := replace( l_query, lpad(' ',10?\i,' '), ' ' );
    end loop;
    return upper(l_query);
end;

可以看到,loop后面两行中确实显示有问号!!!
本来的文本应该是“10-i”,而在EMDC中显示的是“10?\i”。真是怪异!

回想一下,我们的编译环境是WINXP+ULTRAEDIT和SQLPLUS,而存储过程的驻留位置在CENTOS系统的DB上,那么是不是这二者在字符集差异方面的问题呢?

先看一下,我们的“10-i”在ULTRAEDIT下究竟存储成什么。
使用ULTRAEDIT的"Hex Edit"功能,同时显示二进制表示和文本表示,定位到“10-i”的位置,有了惊人的发现。由于直接拷贝黏贴过来,看不到二进制显示形式,只有转录。
选中文本显示中“10-i”的部分,对应的二进制显示部分选中的内容为:
31 30 A9 5C 69


11:41:09 SQL> select chr(169) from dual;

C
-
?

11:41:37 SQL> select chr(92) from dual;

C
-
\

11:51:37 SQL> select chr(105) from dual;

C
-
i

11:55:37 SQL>
#^ 使用数据库的chr函数,可以验证在“数据库字符集”下,0xa9,0x5c,0x69对应的字符分别为"?","\","i".

现在,终于可以解释这个“鬼”的来历了。最初,存储过程文本从pdf文件中拷贝过来时,原pdf文件中显示的“10-i”在复制过来后,由于pdf文件编码的问题,这个“10-i”实际上已经变异成了“10?\i”,被复制到ULTRAEDIT中。

与其他复制过程中“变异”的字符不同,其他的变异字符在ULTRAEDIT中可以直观的看到变异,从而被修正,而变异成“10?\i”的字符在ULTRAEDIT中仍然显示成正确的“10-i”,于是底层的编码仍然是变异后的31 30 A9 6C 69,而没有被修改成正确的31 30 2D 69。

这一看不到的编码错误被读入了SQLPLUS的编辑区,而SQLPLUS竟然同样肉眼凡胎,没有识别出错误编码的真面目(难道是WINDOWS的特色?)。再由PLSQL模块编译时,由于这一错误的编码代表的字符串不符合PLSQL语法,因而产生编译错误,“鬼”开始作弄人了。

总结:其实除了这次,以前在工作中也不止一次的遇到怪异的,按常理无法解释的事件。与生活中的科学无法解释的灵异事件不同,经过仔细分析和研究之后,发现这些技术上的怪异事件背后都有它非常常规的原因和解释。因此,见怪不怪,透过现象看本质,应该是技术人员应该具备的态度吧。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24131851/viewspace-682555/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/24131851/viewspace-682555/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值