ITPUB论坛-中国最专业的IT技术社区

 找回密码
 注册
查看: 6309|回复: 10

[每日一题] PL/SQL Challenge 每日一题:2017-7-4 包的初始化代码(12C)

[复制链接]
论坛徽章:
480
榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09
发表于 2017-7-6 04:27 | 显示全部楼层 |阅读模式
(原发表于 2017-6-23)

最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可发新贴补充或纠正),其他会员如果提供有价值的分析、讨论也可获得纪念章一枚。

每两周的优胜者可获得itpub奖励的技术图书一本。

以往旧题索引:
http://www.itpub.net/forum.php?m ... =typeid&typeid=1808

原始出处:
http://www.plsqlchallenge.com/

作者:Elic

运行环境:SQLPLUS, SERVEROUTPUT已打开
注:本题给出答案时候要求给予简要说明才能得到奖品

注:本题执行环境为12c

我执行了下列语句:

create package qz_pkg
as
  var___a          int := 0;
  const_b constant int := 0;
  error_c          int := 1e100;
  var___d          int := 0;
  const_e constant int := 0;
end qz_pkg;
/

begin
  dbms_output.put_line('Value=' || qz_pkg.var___a);
end;
/

匿名块报错了:

ORA-06502: PL/SQL: numeric or value error: number precision too large

哪些选项会显示 "Value=0"?

(A)
begin
  dbms_output.put_line('Value=' || qz_pkg.var___a);
end;
/

(B)
begin
  dbms_output.put_line('Value=' || qz_pkg.const_b);
end;
/

(C)
begin
  dbms_output.put_line('Value=' || qz_pkg.error_c);
end;
/

(D)
begin
  dbms_output.put_line('Value=' || qz_pkg.var___d);
end;
/

(E)
begin
  dbms_output.put_line('Value=' || qz_pkg.const_e);
end;
/

论坛徽章:
15
秀才
日期:2017-01-20 11:04:31秀才
日期:2017-04-05 13:22:59秀才
日期:2017-03-02 10:35:32秀才
日期:2016-11-09 14:32:17秀才
日期:2016-11-09 14:32:49秀才
日期:2016-11-09 14:32:49秀才
日期:2016-11-09 14:32:49秀才
日期:2016-11-09 14:32:49技术图书徽章
日期:2016-11-09 14:33:08秀才
日期:2016-11-09 14:46:36
发表于 2017-7-6 09:33 | 显示全部楼层
我选BE。
因为常量在声明时赋予初值,并且在运行时会重新赋值。而反观ACD由于在函数运行时需要重新赋值会因为  error_c 的赋值超过了int的最大限制而报错

使用道具 举报

回复
论坛徽章:
15
秀才
日期:2017-08-11 15:30:05技术图书徽章
日期:2017-08-23 14:17:00秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05
发表于 2017-7-6 16:52 | 显示全部楼层
本帖最后由 只是甲 于 2017-7-6 17:05 编辑

答案BE

为了回答这个题目,我也是拼了,单独找了台机器,安装了12C

题目特意表明要用12C,我猜想肯定是12C和11G的一些差别,实验结果也证明了,确实有差别。


11G上运行的结果,答案是ABE   
   但是第一次运行报错,第二次运行不报错,我也是奇了怪了
   重新开了一个窗口,依旧是第一次运行输出var___a报错,后面的n次都没有问题,这个有点难以解释。查了半天资料,也没找到解释,可能我太菜了吧。
   

SQL> begin
2    dbms_output.put_line('Value=' || qz_pkg.var___a);
3  end;
4  /
begin
*
第 1 行出现错误:
ORA-06502: PL/SQL: 数字或值错误 :  数值精度太高
ORA-06512: 在 "SCOTT.QZ_PKG", line 5
ORA-06512: 在 line 2


SQL>
SQL> begin
  2    dbms_output.put_line('Value=' || qz_pkg.var___a);
  3  end;
  4  /
Value=0

PL/SQL 过程已成功完成。


12C上运行的结果,答案是BE
  常量是编译的时候赋值,变量是运行时赋值,所以不影响常量,只影响变量。

使用道具 举报

回复
论坛徽章:
480
榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09
 楼主| 发表于 2017-7-7 03:56 | 显示全部楼层
本帖最后由 newkid 于 2017-7-10 23:04 编辑

答案BE, 2楼得奖。

当会话引用包头中的元素时,Oracle会为该会话将这个包进行实例化。

当Oracle实例化一个包时,它也会初始化它。初始化过程包括以下的适用步骤:

为公用常量赋予初始值
为其声明指定的公用变量赋予初始值
执行包体的初始化部分

当包初始化失败时,这意味着尝试引用包中的元素会导致未处理的异常。

然而,奇怪又可悲的是,当包初始化失败时,Oracle仍然会将包标记为初始化。这导致一些“经典”调试恶梦,此时错误会发生一次,但在同一会话中却不会重新出现。

在Oracle Database 11g Release 2及更早版本中,如果在程序包初始化期间发生错误,那么初始化将在出错误时终止,所有其他程序包元素都将未初始化,已初始化的部分则可供使用。因此在11.1和11.2中,A选项将显示“Value = 0”,而选项C和D将显示“Value =”。

但是,从Oracle数据库12c版本1开始,在程序包初始化期间的任何时候发生错误时,程序包将被视为未初始化。对该包的任何进一步的引用将使包被重新初始化。所以选项A,C,D失败。

然而,选项B和E成功,因为默认优化级别为2(或更高)的PL / SQL优化器足够聪明,以获得包常量的值,而不初始化包。

使用道具 举报

回复
论坛徽章:
480
榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09
 楼主| 发表于 2017-7-7 03:56 | 显示全部楼层
只是甲 发表于 2017-7-6 16:52
答案BE

为了回答这个题目,我也是拼了,单独找了台机器,安装了12C

为3楼的钻研精神点赞,我决定转让给你一枚徽章,请告诉我要哪个。

使用道具 举报

回复
论坛徽章:
15
秀才
日期:2017-08-11 15:30:05技术图书徽章
日期:2017-08-23 14:17:00秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05
发表于 2017-7-7 09:19 | 显示全部楼层
newkid 发表于 2017-7-7 03:56
为3楼的钻研精神点赞,我决定转让给你一枚徽章,请告诉我要哪个。

给我个 秀才 徽章吧,

看了你的解释,总算明白了,感谢

使用道具 举报

回复
论坛徽章:
480
榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09
 楼主| 发表于 2017-7-7 21:28 | 显示全部楼层
系统提示这个徽章不可转让,你要个别的吧。

使用道具 举报

回复
论坛徽章:
0
发表于 2017-7-10 20:48 | 显示全部楼层
newkid 发表于 2017-7-7 03:56
答案BE, 2楼得奖。

当会话引用包头中的元素时,Oracle会为该会话将这个包进行实例化。

楼主,请教一下:为什么选项A在11g中能成功,而在12C中是失败的呢?这个原因我还是每太搞明白

使用道具 举报

回复
论坛徽章:
480
榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09
 楼主| 发表于 2017-7-10 23:06 | 显示全部楼层
hzx_500 发表于 2017-7-10 20:48
楼主,请教一下:为什么选项A在11g中能成功,而在12C中是失败的呢?这个原因我还是每太搞明白

这是因为11g对这个问题处理不好,解释中已经说了:
"然而,奇怪又可悲的是,当包初始化失败时,Oracle仍然会将包标记为初始化。这导致一些“经典”调试恶梦,此时错误会发生一次,但在同一会话中却不会重新出现。"

也就是说,出错时Oracle对包的初始化只完成了一半,导致部分变量可用,而且它认为这个包已经被初始化了,所以不会试图再对它初始化。

使用道具 举报

回复
论坛徽章:
0
发表于 2017-7-11 20:19 | 显示全部楼层
newkid 发表于 2017-7-10 23:06
这是因为11g对这个问题处理不好,解释中已经说了:
"然而,奇怪又可悲的是,当包初始化失败时,Oracle仍 ...

多谢楼主,大致了解了

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

TOP技术积分榜 社区积分榜 徽章 电子杂志 团队 统计 虎吧 老博客 知识索引树 读书频道 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档 | IT博客
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛 | SAP ERP系统
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 网站律师 隐私政策 知识产权声明
京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表