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

 找回密码
 注册
查看: 3141|回复: 7

[每日一题] PL/SQL Challenge 每日一题:2017-8-1 自定义嵌套表类型的MULTISET操作

[复制链接]
论坛徽章:
479
状元
日期: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:03:12状元
日期:2015-11-23 10:04:09
发表于 2017-8-4 03:46 | 显示全部楼层 |阅读模式
(原发表于 2011-7-28)

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

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

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

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

作者:Steven Feuerstein

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

我们有两只宠物:一只大鹦鹉(Mercury,它是一只非洲灰鹦鹉)和一只大猫(Moshe)。我想要记录它们看兽医的信息,用的是一个名为plch_vet_visit_t的对象类型和一个名为plch_vet_visits_t的此对象的嵌套表类型。

CREATE TYPE plch_vet_visit_t IS OBJECT
/* SPECIFICATION AND/OR BODY TO BE COMPLETED BY CHOICES */
...

CREATE OR REPLACE TYPE plch_vet_visits_t IS TABLE OF plch_vet_visit_t
/


下面的代码块用MULTISET EXCEPT比较这些访问记录:

DECLARE
   mercury_visits   plch_vet_visits_t
      := plch_vet_visits_t (
            plch_vet_visit_t (TRUNC(SYSDATE) - 20, 'Clip wings')
          , plch_vet_visit_t (TRUNC(SYSDATE) - 5, 'Check cholesterol'));
   moshe_visits     plch_vet_visits_t
      := plch_vet_visits_t (plch_vet_visit_t (TRUNC(SYSDATE), 'Overweight'));
   moshe2_visits    plch_vet_visits_t
      := plch_vet_visits_t (plch_vet_visit_t (TRUNC(SYSDATE), 'Overweight'));

   minus_visits     plch_vet_visits_t;
BEGIN
   minus_visits := mercury_visits MULTISET EXCEPT moshe_visits;

   IF minus_visits.COUNT = 0
   THEN
      DBMS_OUTPUT.put_line ('Same visits!');
   ELSE
      DBMS_OUTPUT.put_line ('Different visits!');
   END IF;

   minus_visits := moshe_visits MULTISET EXCEPT moshe2_visits;

   IF minus_visits.COUNT = 0
   THEN
      DBMS_OUTPUT.put_line ('Same visits!');
   ELSE
      DBMS_OUTPUT.put_line ('Different visits!');
   END IF;
END;
/

哪些选项包含了plch_vet_visit_t对象的实现呆啊吗,使得上述代码块执行之后会显示如下两行文本?

Different visits!
Same visits!

(A)
CREATE TYPE plch_vet_visit_t IS OBJECT
       (visit_date DATE
      , reason VARCHAR2 (100)
      , MAP MEMBER FUNCTION visit_map
           RETURN INTEGER);
/

CREATE OR REPLACE TYPE BODY plch_vet_visit_t
IS
   MAP MEMBER FUNCTION visit_map
      RETURN INTEGER
   IS
   BEGIN
      RETURN CASE
                WHEN self.visit_date < TRUNC(SYSDATE) - 10 THEN 100
                WHEN self.visit_date < TRUNC(SYSDATE) THEN 10
                ELSE 1
             END;
   END;
END;
/

(B)
CREATE TYPE plch_vet_visit_t IS OBJECT
       (visit_date DATE
      , reason VARCHAR2 (100)
      , ORDER MEMBER FUNCTION visit_order (visit_in IN plch_vet_visit_t)
           RETURN INTEGER);
/

CREATE OR REPLACE TYPE BODY plch_vet_visit_t
IS
   ORDER MEMBER FUNCTION visit_order (visit_in IN plch_vet_visit_t)
      RETURN INTEGER
   IS
   BEGIN
      RETURN CASE
                WHEN self.visit_date < visit_in.visit_date THEN -1
                WHEN self.visit_date = visit_in.visit_date THEN 0
                ELSE 1
             END;
   END;
END;
/

(C)
CREATE TYPE plch_vet_visit_t IS OBJECT
       (visit_date DATE
      , reason VARCHAR2 (100));
/


(D)
CREATE TYPE plch_vet_visit_t IS OBJECT
       (visit_date DATE
      , reason VARCHAR2 (100)
      , MAP STATIC FUNCTION visit_map
           RETURN INTEGER);
/

CREATE OR REPLACE TYPE BODY plch_vet_visit_t
IS
   MAP STATIC FUNCTION visit_map
      RETURN INTEGER
   IS
   BEGIN
      RETURN CASE
                WHEN self.visit_date < TRUNC(SYSDATE) - 10 THEN 100
                WHEN self.visit_date < TRUNC(SYSDATE) THEN 10
                ELSE 1
             END;
   END;
END;
/

论坛徽章:
479
状元
日期: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:03:12状元
日期:2015-11-23 10:04:09
 楼主| 发表于 2017-8-5 02:42 | 显示全部楼层
顶一下。

使用道具 举报

回复
认证徽章
论坛徽章:
203
2010新春纪念徽章
日期:2010-03-01 11:20:51至尊黑钻
日期:2015-08-13 13:38:12至尊黑钻
日期:2015-02-15 09:47:472015中国数据库技术大会纪念徽章
日期:2015-05-15 14:08:23管理团队2007贡献徽章
日期:2015-01-19 09:48:272015年中国系统架构师大会纪念徽章
日期:2015-07-31 17:48:20红宝石
日期:2015-01-19 09:42:28红宝石
日期:2017-04-21 09:23:38海蓝宝石
日期:2015-02-03 10:23:39红宝石
日期:2015-02-03 10:26:04
发表于 2017-8-5 08:25 | 显示全部楼层
顶一下

使用道具 举报

回复
论坛徽章:
479
状元
日期: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:03:12状元
日期:2015-11-23 10:04:09
 楼主| 发表于 2017-8-7 09:19 | 显示全部楼层

你有这顶一下的功夫,都可以把题目答出来了。

使用道具 举报

回复
认证徽章
论坛徽章:
6
秀才
日期:2017-06-29 10:16:48技术图书徽章
日期:2017-06-29 10:17:04秀才
日期:2017-06-29 10:17:04秀才
日期:2017-08-11 15:38:34秀才
日期:2017-08-11 15:38:34秀才
日期:2017-08-23 14:12:15
发表于 2017-8-7 12:45 | 显示全部楼层
答案是A。这么久都没人答啊。
A.经MAP MEMBER FUNCTION处理,mercury_visits中两个元素分别第三个字段返回100,10;moshe_visits 第三个字段返回1;moshe2_visits第三个字段也返回1;
又moshe_visits中的元素与moshe2_visits中的元素前两个字段也相同;mercury_visits含有两个三个字段都不同的元素,moshe_visits只有一个元素,且与mercury_visits中的元素也不同,因而作差集后的minus_visits.COUNT=2。进而会得到理想的输出。
B.报错,ORDER MEMBER需要一个明确的参数plch_vet_visit_t类型实例才行;
C.报错,Two objects of nonscalar type are comparable if they are of the same named type and there is a one-to-one correspondence between their elements. In addition, nested tables of user-defined object types, even if their elements are comparable, must have MAP methods defined on them to be used in equality or IN conditions.必须要有MAP方法。
D.STATIC使用错误。 STATIC methods do not have any implicit parameters. You cannot reference SELF in their body.

使用道具 举报

回复
论坛徽章:
479
状元
日期: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:03:12状元
日期:2015-11-23 10:04:09
 楼主| 发表于 2017-8-8 04:23 | 显示全部楼层

答案A, 5楼得奖。

A: MAP方法恰好就是我们所需要的!
B: Oracle不能(现在还不能)利用ORDER方法来执行MULTISET中的比较操作,只有MAP才是支持的。在这个对象类型的定义中,当你试图执行代码块,ORACLE会报错:
PLS-00306: wrong number or types of arguments in call to 'MULTISET_EXCEPT_ALL'

Oracle 已经在MOS(My Oracle Support)中记录了这个BUG,关于无法在MULTISET中使用ORDER方法:

Bug 6653918: LET AN ORDER METHOD BE OK FOR MULTISET OPERATIONS OF NESTED TABLES OF ADTS

这个问题在2007年被记录,截止2011年7月,它的状态仍然是 "Cost Required, To Development". (译者注:2017年8月也是这个状态,在12.1中仍未修复)

注意,在PL/SQL MULTISET 操作中对ORDER的这个使用限制是针对PL/SQL的;你可以在SQL MULTISET中使用ORDER,如下列代码所示(感谢_Nikotin提供代码):

DECLARE
   mercury_visits   plch_vet_visits_t
      := plch_vet_visits_t (
            plch_vet_visit_t (TRUNC (SYSDATE) - 20, 'Clip wings')
          , plch_vet_visit_t (TRUNC (SYSDATE) - 5, 'Check cholesterol'));
   moshe_visits     plch_vet_visits_t
      := plch_vet_visits_t (plch_vet_visit_t (TRUNC (SYSDATE), 'Overweight'));
   moshe2_visits    plch_vet_visits_t
      := plch_vet_visits_t (plch_vet_visit_t (TRUNC (SYSDATE), 'Overweight'));
   minus_visits     plch_vet_visits_t;
   minus_visit      plch_vet_visit_t;
BEGIN
   SELECT VALUE (t)
     BULK COLLECT INTO minus_visits
     FROM TABLE (mercury_visits) t
   MINUS
   SELECT VALUE (t)
     FROM TABLE (moshe_visits) t;

   IF minus_visits.COUNT = 0
   THEN
      DBMS_OUTPUT.put_line ('Same visits!');
   ELSE
      DBMS_OUTPUT.put_line ('Different visits!');
   END IF;

   SELECT VALUE (t)
     BULK COLLECT INTO minus_visits
     FROM TABLE (moshe_visits) t
   MINUS
   SELECT VALUE (t)
     FROM TABLE (moshe2_visits) t;

   IF minus_visits.COUNT = 0
   THEN
      DBMS_OUTPUT.put_line ('Same visits!');
   ELSE
      DBMS_OUTPUT.put_line ('Different visits!');
   END IF;
END;

C: 如果类型中没有定义MAP方法,ORACLE就不能够比较两个对象类型。在这个定义中,当你试图执行代码块,ORACLE会报错:
PLS-00306: wrong number or types of arguments in call to 'MULTISET_EXCEPT_ALL'

D: MAP方法必须被定义为MEMBER, 不是 STATIC。当你试图执行代码块,ORACLE会报错:
PLS-00103: Encountered the symbol "STATIC" when expecting one of the following: member


使用道具 举报

回复
论坛徽章:
2
托尼托尼·乔巴
日期:2017-08-01 21:49:16ITPUB 11周年纪念徽章
日期:2017-07-05 23:19:11
发表于 2017-8-9 23:34 | 显示全部楼层
该题目中,对于reason 字段的设置,不影响结果。map函数里没有用到这个字段做比较。

使用道具 举报

回复
认证徽章
论坛徽章:
6
秀才
日期:2017-06-29 10:16:48技术图书徽章
日期:2017-06-29 10:17:04秀才
日期:2017-06-29 10:17:04秀才
日期:2017-08-11 15:38:34秀才
日期:2017-08-11 15:38:34秀才
日期:2017-08-23 14:12:15
发表于 2017-8-11 21:11 | 显示全部楼层
fire_feng 发表于 2017-8-9 23:34
该题目中,对于reason 字段的设置,不影响结果。map函数里没有用到这个字段做比较。

reason字段是有用的,   minus_visits := mercury_visits MULTISET EXCEPT moshe_visits;
这句multiset except做差集运算时会比较。

使用道具 举报

回复

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

本版积分规则

SACC2017购票8.8折优惠进行时

2017中国系统架构师大会(SACC2017)将于10月19-21日在北京新云南皇冠假日酒店震撼来袭。今年,大会以“云智未来”为主题,云集国内外顶级专家,围绕云计算、人工智能、大数据、移动互联网、产业应用等热点领域展开技术探讨与交流。本届大会共设置2大主会场,18个技术专场;邀请来自互联网、金融、制造业、电商等多个领域,100余位技术专家及行业领袖来分享他们的经验;并将吸引4000+人次的系统运维、架构师及IT决策人士参会,为他们提供最具价值的交流平台。
----------------------------------------
优惠时间:2017年8月30日前

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