我是靠谱客的博主 顺心豆芽,最近开发中收集的这篇文章主要介绍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/

最后

以上就是顺心豆芽为你收集整理的SQLPLUS编译存储过程见鬼记的全部内容,希望文章能够帮你解决SQLPLUS编译存储过程见鬼记所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部