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

 找回密码
 注册
查看: 3435|回复: 2

[每日一题] PL/SQL Challenge 每日一题:2017-1-11 查找集合元素

[复制链接]
论坛徽章:
454
秀才
日期:2015-08-18 09:49:27秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01状元
日期:2015-09-09 10:34:21榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01
发表于 2017-1-14 00:52 | 显示全部楼层 |阅读模式

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

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

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

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

作者:        AcePLSQLGuy

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

我执行了下列语句:

CREATE OR REPLACE PACKAGE plch_pkg
   AUTHID DEFINER
IS
   TYPE strings_t IS TABLE OF VARCHAR2 (100);

   g_strings        strings_t := strings_t ();

   TYPE string_index_t IS TABLE OF PLS_INTEGER
      INDEX BY VARCHAR2 (100);

   g_string_index   string_index_t;
END;
/

CREATE OR REPLACE PACKAGE BODY plch_pkg
IS
BEGIN
   g_strings.EXTEND (100000);

   FOR indx IN 1 .. 100000
   LOOP
      g_strings (indx) := 'String ' || indx;
      g_string_index (g_strings (indx)) := indx;
   END LOOP;
END;
/

哪些选项在执行下列代码块之后:
BEGIN
   plch_show_match (string_in => 'String 95000');
   plch_show_match (string_in => 'String 100001');
END;
/

会显示如下两行?
Matching index - 95000
No match for String 100001


(A)
CREATE OR REPLACE PROCEDURE plch_show_match (string_in IN VARCHAR2)
   AUTHID DEFINER
IS
BEGIN
   FOR indx IN 1 .. plch_pkg.g_strings.COUNT
   LOOP
      IF plch_pkg.g_strings (indx) = string_in
      THEN
         DBMS_OUTPUT.put_line ('Matching index - ' || indx);
         RETURN;
      END IF;
   END LOOP;

   DBMS_OUTPUT.put_line ('No match for ' || string_in);
END;
/

(B)
CREATE OR REPLACE PROCEDURE plch_show_match (string_in IN VARCHAR2)
   AUTHID DEFINER
IS
   l_index       PLS_INTEGER := plch_pkg.g_strings.FIRST;
   l_not_found   BOOLEAN := TRUE;
BEGIN
   WHILE (l_index IS NOT NULL AND l_not_found)
   LOOP
      IF plch_pkg.g_strings (l_index) = string_in
      THEN
         DBMS_OUTPUT.put_line ('Matching index - ' || l_index);
         l_not_found := FALSE;
      ELSE
         l_index := plch_pkg.g_strings.NEXT (l_index);
      END IF;
   END LOOP;

   IF l_not_found
   THEN
      DBMS_OUTPUT.put_line ('No match for ' || string_in);
   END IF;
END;
/

(C)
CREATE OR REPLACE PROCEDURE plch_show_match (string_in IN VARCHAR2)
   AUTHID DEFINER
IS
   l_index   PLS_INTEGER := plch_pkg.g_strings.FIRST;
BEGIN
   IF string_in NOT MEMBER OF plch_pkg.g_strings
   THEN
      DBMS_OUTPUT.put_line ('No match for ' || string_in);
   ELSE
      WHILE l_index IS NOT NULL
      LOOP
         IF plch_pkg.g_strings (l_index) = string_in
         THEN
            DBMS_OUTPUT.put_line ('Matching index - ' || l_index);
            l_index := NULL;
         ELSE
            l_index := plch_pkg.g_strings.NEXT (l_index);
         END IF;
      END LOOP;
   END IF;
END;
/

(D)
CREATE OR REPLACE PROCEDURE plch_show_match (string_in IN VARCHAR2)
   AUTHID DEFINER
IS
BEGIN
   DBMS_OUTPUT.put_line (
      'Matching index - ' || plch_pkg.g_string_index (string_in));
EXCEPTION
   WHEN NO_DATA_FOUND
   THEN
      DBMS_OUTPUT.put_line ('No match for ' || string_in);
END;
/

(E)
CREATE OR REPLACE PROCEDURE plch_show_match (string_in IN VARCHAR2)
   AUTHID DEFINER
IS
BEGIN
   IF plch_pkg.g_string_index.EXISTS (string_in)
   THEN
      DBMS_OUTPUT.put_line (
         'Matching index - ' || plch_pkg.g_string_index (string_in));
   ELSE
      DBMS_OUTPUT.put_line ('No match for ' || string_in);
   END IF;
END;
/
认证徽章
论坛徽章:
166
SQL数据库编程大师
日期:2016-01-13 10:30:43SQL极客
日期:2013-12-09 14:13:35SQL大赛参与纪念
日期:2013-12-06 14:03:45最佳人气徽章
日期:2015-03-19 09:44:03现任管理团队成员
日期:2015-08-26 02:10:00秀才
日期:2015-07-28 09:12:12举人
日期:2015-07-13 15:30:15进士
日期:2015-07-28 09:12:58探花
日期:2015-07-28 09:12:58榜眼
日期:2015-08-18 09:48:03
发表于 2017-1-14 09:49 | 显示全部楼层
A.是嵌套表,下标123456……所以95000满足,100001不满足
B.原因同上,使用的是下标访问
C.NOT MEMBER OF集合判断
D.管联数组直接定位
E.EXISTS元素判断

ABCDE都对

使用道具 举报

回复
论坛徽章:
454
秀才
日期:2015-08-18 09:49:27秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01状元
日期:2015-09-09 10:34:21榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01
 楼主| 发表于 2017-1-17 04:33 | 显示全部楼层
答案ABCDE, 2楼得奖。

A:(不推荐)
能够完成任务。有两个顾虑:
1. 性能:它执行了一个全集合扫描,所以随着集合的增长它会变慢,取决于匹配在哪里找到。
2. 在循环中的RETURN是一种不良结构。通常而言,最好避免用这种方法来中止循环或者过程。
B:(不推荐)
这能返回正确结果,比A的结构好一点。但是它仍然(可能)依赖于全集合扫描。

C:(不推荐)
这个选项用了MEMBER OF来快速查询字符串是否在集合中,这只能用于嵌套表。想法不错...如果你所需的只是“它是否在嵌套表中?”,那么MEMBER OF是最好的。
然而在这个题目中,我们需要知道它在哪里。所以我又回到了全集合扫描。

D: 嗯,这个选项显然比其它的代码少了很多,并且不管集合中的元素有多少,不管要匹配的字符串在哪里,它都会很高效。
然而,通常而言,最好不要依赖于异常来处理一个逻辑分支。在这个选项中,我依赖于PL/SQL会抛出NO_DATA_FOUND,假如我试图去“读”一个未定义的索引值。对于一个这样的小程序,这无伤大雅,但是在大型程序中,很难记得去异常部分查看应用逻辑。

(译者注:这个方法没有问题,只需记住不要把异常放在一大段代码之后,可以把要处理的地方写一个小匿名块,紧贴着要捕获异常语句就可以了)

E:(推荐)
这个看起来好极了!非常简洁且高效,这是因为它依赖于我构建的字符串索引,并且更好的结构化,因为我用EXISTS方法来检查是否存在,而不是依赖于NO_DATA_FOUND的抛出。

使用道具 举报

回复

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

本版积分规则

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