查看: 1835|回复: 3

[每日一题] PL/SQL Challenge 每日一题:2018-7-23 嵌套子程序

[复制链接]
论坛徽章:
527
紫蜘蛛
日期:2007-09-26 17:05:56奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:53
发表于 2018-7-26 02:32 | 显示全部楼层 |阅读模式
(原发表于 2011-10-14)

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

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

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

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

作者:Steven Feuerstein

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

星期一我写了这个存储过程:

CREATE OR REPLACE PROCEDURE plch_show_amounts (
   amount1_in   IN NUMBER
,  amount2_in   IN NUMBER)
IS
BEGIN
   DBMS_OUTPUT.put_line (
      TO_CHAR (plch_show_amounts.amount1_in, 'FML999G999D99'));
   DBMS_OUTPUT.put_line (
      TO_CHAR (plch_show_amounts.amount2_in, 'FML999G999D99'));
END;
/

星期二,我有个同事觉得自己比任何人都知道该如何写好代码,他批评过程中出现的重复代码。“你为什么不把重复的代码放到一个嵌套的子过程?那样的话,假如你需要修改显示格式,或者其他和显示金额相关的东西,你只需修改一个地方。”

好吧,我也没法反对。所以我把代码移入一个嵌套的子过程。实际上,我在推出一个能使用的程序版本之前也这么干过几次。

下面的选项中哪些包含了一个对原始的plch_show_amounts的“重构”,从而在我执行这段代码之后:
BEGIN
   plch_show_amounts (100.45, 452666.77);
END;
/

我在屏幕上会看到这样的输出:

$100.45
$452,666.77


(A)
CREATE OR REPLACE PROCEDURE plch_show_amounts (
   amount1_in   IN NUMBER
,  amount2_in   IN NUMBER)
IS
   PROCEDURE show_one (amount_in IN NUMBER)
   AS
   BEGIN
      DBMS_OUTPUT.put_line (
         TO_CHAR (amount1_in, 'FML999G999D99'));
   END;
BEGIN
   show_one (plch_show_amounts.amount1_in);
   show_one (plch_show_amounts.amount2_in);
END;
/


(B)
CREATE OR REPLACE PROCEDURE plch_show_amounts (
   amount1_in   IN NUMBER
,  amount2_in   IN NUMBER)
IS
   PROCEDURE show_one (amount_in IN NUMBER)
   AS
   BEGIN
      DBMS_OUTPUT.put_line (
         TO_CHAR (amount_in, 'FML999G999D99'));
   END;
BEGIN
   show_one (plch_show_amounts.amount1_in);
   show_one (plch_show_amounts.amount2_in);
END;
/

(C)
CREATE OR REPLACE PROCEDURE plch_show_amounts (
   amount1_in   IN NUMBER
,  amount2_in   IN NUMBER)
IS
   PROCEDURE show_one (amount1_in IN NUMBER)
   AS
   BEGIN
      DBMS_OUTPUT.put_line (
         TO_CHAR (amount1_in, 'FML999G999D99'));
   END;
BEGIN
   show_one (plch_show_amounts.amount1_in);
   show_one (plch_show_amounts.amount2_in);
END;
/

(D)
CREATE OR REPLACE PROCEDURE plch_show_amounts (
   amount1_in   IN NUMBER
,  amount2_in   IN NUMBER)
IS
   PROCEDURE show_one (amount1_in IN NUMBER)
   AS
   BEGIN
      DBMS_OUTPUT.put_line (
         TO_CHAR (plch_show_amounts.amount1_in, 'FML999G999D99'));
   END;
BEGIN
   show_one (plch_show_amounts.amount1_in);
   show_one (plch_show_amounts.amount2_in);
END;
/
论坛徽章:
4
秀才
日期:2018-07-23 13:55:51秀才
日期:2018-07-23 14:00:48技术图书徽章
日期:2018-07-23 14:01:23秀才
日期:2018-07-23 14:01:23
发表于 2018-7-26 08:50 | 显示全部楼层
答案BC
A:内嵌套块可以访问外嵌套块的变量,但外部不能访问内部变量。子程序show_one并没有重新声明amount1_in,打印的时候是外部的全局变量amount1_in。结果是两次都会显示$100.45
B:正确,子程序show_one接收amount_in参数并打印,传进来啥打印啥。
C:正确,在子程序里重新定义了内部块的变量amount1_in
D:虽然子程序重新定义了内部变量amount1_in,但打印的时候引用的是外部块的变量。结果还是两次都会显示$100.45

使用道具 举报

回复
认证徽章
论坛徽章:
25
林肯
日期:2013-07-30 18:00:55技术图书徽章
日期:2018-05-22 15:21:47秀才
日期:2018-05-22 15:21:47秀才
日期:2018-05-22 16:13:08秀才
日期:2018-05-22 16:13:21技术图书徽章
日期:2018-05-22 16:13:30秀才
日期:2018-05-22 16:13:30秀才
日期:2018-05-22 16:17:26秀才
日期:2018-07-23 13:38:29技术图书徽章
日期:2018-07-23 13:38:40
发表于 2018-7-26 10:35 | 显示全部楼层
BC。
呵呵。还能procedure里面嵌套procedure 和function神奇啊。(但是一定在声明的最后)如下:
红色一定要在嵌套之前,要不然报错,要不就是我自己定义的问题。希望指教
CREATE OR REPLACE PROCEDURE plch_show_amounts (
   amount1_in   IN NUMBER
,  amount2_in   IN NUMBER)
IS
L_VAR Number:=0;
   PROCEDURE show_one (amount1_in IN NUMBER)
   AS
   BEGIN
      DBMS_OUTPUT.put_line (
         TO_CHAR (amount1_in, 'FML999G999D99'));
   END;
  
BEGIN
   show_one (plch_show_amounts.amount1_in);
   show_one (plch_show_amounts.amount2_in);
END;
/


这样写也行啊:哈哈。(跟此题无关,只是调侃)
CREATE OR REPLACE PROCEDURE plch_show_amounts (
   amount1_in   IN NUMBER
,  amount2_in   IN NUMBER)
Is
L_FORMAT Varchar2(200):='FML999G999D99';
BEGIN
   DBMS_OUTPUT.put_line (
      TO_CHAR (amount1_in, L_FORMAT));
   DBMS_OUTPUT.put_line (
      TO_CHAR (amount2_in, L_FORMAT));
END;
/

使用道具 举报

回复
论坛徽章:
527
紫蜘蛛
日期:2007-09-26 17:05:56奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:53
 楼主| 发表于 2018-7-27 04:19 | 显示全部楼层
答案BC, 2楼得奖。

A: 在这个选项中,我把第一个DBMS_OUTPUT.PUT_LINE转移到一个嵌套过程中,并且加了一个参数。不幸的是,我忽略了将对amount1_in 的引用修改成 amount_in。过程会被编译,这个没问题,但是它永远都会显示amount1_in的值,不管实际上传递给show_one的是什么东西。
B: 在这个选项中,我把第一个DBMS_OUTPUT.PUT_LINE转移到一个嵌套过程中,并且加了一个参数。然后我将对amount1_in 的引用修改成 amount_in。这将会显示正确的文本信息。
C: 我将显示amount1_in的代码转移到一个嵌套过程中。我增加了一个参数,它和父过程的参数名是一样的(amount1_in)。这可能不是最佳的,最清晰的方法。最好改下名字,比如叫"amount_in"。

但是这个代码工作起来是没问题的。在show_one中任何不带修饰的对"amount1_in" 的引用都会被解释成嵌套过程的参数。

D: 这是一个典型的半吊子工程的例子。我将对DBMS_OUTPUT.PUT_LINE的调用移动(拷贝粘贴)到嵌套过程中。我增加了一个参数。我忘记修改TO_CHAR调用中对参数的引用。
不管传递给show_one的是什么值,他永远会显示amount1_in的值。

使用道具 举报

回复

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

本版积分规则 发表回复

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