PL/SQL Challenge 每日一题:2015-6-23 字符串的比较

[复制链接]
查看11 | 回复9 | 2008-9-15 01:28:12 | 显示全部楼层 |阅读模式
(原发表于2010-11-29)

最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可发新贴补充或纠正),其他会员如果提供有价值的分析、讨论也可获得纪念章一枚。
以往旧题索引:
http://www.itpub.net/forum.php?m ... eid&typeid=1808
原始出处:
http://www.plsqlchallenge.com/
作者:
KenHolmslykke
运行环境:SQLPLUS, SERVEROUTPUT已打开
注:本题给出答案时候要求给予简要说明才能得到奖品
哪些选项显示了我执行下列代码块之后屏幕上所出现的内容?
DECLARE
SUBTYPE index_t IS all_objects.object_type%TYPE;
TYPE list_t IS TABLE OF PLS_INTEGER

INDEX BY index_t;
l_list list_t;
BEGIN
l_list (1) := 1;
FOR indx IN 2 .. 150
LOOP
l_list (l_list.LAST + 1) := indx;
END LOOP;
DBMS_OUTPUT.put_line (l_list.COUNT);
END;
/
(A)
150
(B)
10
(C)
会出现VALUE_ERROR 异常。

回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
真是想不到
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
OBJECT_TYPE
VARCHAR2(19)
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
好像之前出一个类似的题目。 也是关于 index by [数值型 | 字符型]
l_list (1) := 1;
下次的l_list(l_list.last + 1) 出的下标,应该是 2 。 再循环一次,就是 3 ,直到 9
当 l_list.last =9 时, l_list.last + 1 = 10 。
此时,按index by index_t , 这里的 index_t 是引用的 object_type 是字符型 。〇〇 已列出来了 OBJECT_TYPE
VARCHAR2(19)
按数值是,10 比 9 大,但是按字符比较 '9' 是大于 '10' 的。
再向下循环, l_list.last 还是 9 ,一直到最后, 150 也好, 1500 也好,始终更新的是 l_list(10) 的值 。
掰手指头一数,就是 10 个数。
l_list.count = 10
B 是正常答案。

求高人指点。
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
4 楼 看起来是正确答案啊
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
4 LZ 解释得很清楚!
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
答案B, 4楼得奖。
A: 如果集合是用整数做索引,这个选项就对了。
B: 下面这个布尔型变量永远返回TRUE,所以在集合中只会用到10个不同的索引值:
DECLARE
l_boolean BOOLEAN;
BEGIN
l_boolean := '9%' > '1%';
END;
/
C: Oracle执行了一个从数值到字符串的隐式转换,然后又转换回来,这期间的所有字符串里面都是有效的整数值,所以不会发生异常。
-------
这是一个刁钻的问题,起因在于ORACLE的灵活性,以及在执行隐式转换上的不一致性。这个块中使用的关联数组的索引是VARCHAR2(19)(即数据字典视图ALL_OBJECTS的object_type列的数据类型)。
ORACLE执行下列这行代码的结果:
l_list (1) := 1;
在索引位置为 "1" (字符串"1"和数值1是完全不同的)定义了一个值为1的元素。
然后执行了查询。让我们一步一步看看ORACLE在执行下列语句时做了什么:
l_list (l_list.LAST + 1) := indx;
当 indx = 1:
l_list.LAST = "1"
将 "1" 转换成 1
再加上 1 = 2
将 2 转换为 "2"
将值2存储在索引位置 "2".
...
当 indx = 10:
l_list.LAST = "9"
将 "9" 转换为 9
再加上 1 = 10
将 10 转换为 "10"
将值10存储在索引位置 "10".
当 indx = 11: l_list.LAST = "9"
将 "9" 转换为 9
再加上 1 = 10
将 10 转换为 "10"
将值11存储在索引位置 "10".
等一下!为什么我们不把值11保存在索引位置"11"? 具体地说,为什么l_list.LAST返回"9"而不是"11"? 哦,因为它们是字符串,以"9"开头的字符串比"1"开头的字符串更大(至少在我们所用的缺省字符集是这样)
结果,最后一个值的索引位置永远返回"9",所以总共才用了10个索引值。
我知道这很刁钻。但这是个有价值的教训,当你决定将一个关联数组的索引从PLS_INTEGER转换成VARCHAR2就要特别小心。

回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
啊,last函数,index by varchar2,这俩是关键
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
lastwinner 发表于 2015-6-27 23:21
啊,last函数,index by varchar2,这俩是关键

这个错误点太阴险了
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
反应不过来啊!
回复

使用道具 举报

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

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行