在Oracle中,ORDER BY后面的+0是什么意思?

11

我正尝试理解这个Oracle 9i查询的末尾加上+0是什么意思:

SELECT /*+ INDEX (a CODE_ZIP_CODE_IX) */ 
       a.city, 
       a.state, 
       LPAD(a.code,5,0)  ZipCode, 
       b.County_Name     CoName, 
       c.Description     RegDesc, 
       d.Description     RegTypeDesc  
FROM TBL_CODE_ZIP a, 
     TBL_CODE_COUNTY b, 
     TBL_CODE_REGION c, 
     TBL_CODE_REGION_TYPE d  
WHERE a.City = 'LONDONDERRY' 
    AND a.State = 'NH' 
    AND lpad(a.Code,5,0) = '03038' 
    AND a.Region_Type_Code = 1 
    AND b.County(+) = a.County_Code  
    AND b.STATE(+) = a.STATE 
    AND c.Code(+) = a.Region_Code  
    AND d.Code(+) = a.Region_Type_Code  
ORDER BY a.Code +0

有什么想法吗?

注:我认为这与升序或降序无关,因为我无法在 a.Code 和 +0 之间添加 asc 或 desc,但我可以在 +0 后面添加 asc 或 desc。


有没有一种方法可以通过引起隐式转换来将代码强制转换为数字数据类型? - Tom H
代码被指定为NUMBER(5)。 - Lucas B
只要代码排版得当,事情就会变得更加清晰。 - APC
是的,对不起。感谢Niessner适当地进行格式化。 - Lucas B
5个回答

9
“+ 0”是在基于规则的优化器时代的一个技巧,它使得无法使用数字列上的索引。同样地,对于字母数字列,他们会使用“|| ''”技巧。
就您的查询而言,我检查后得出的唯一结论是其创建者在处理性能时遇到了困难。如果(这是我的假设)CODE_ZIP_CODE_IX索引是TBL_CODE_ZIP(Code)的索引,则查询不会使用它,即使提示使用它也是如此。创建者可能不知道使用LPAD(a.code,5,0)而不是a.code,索引将无法使用。order by子句获取其中间结果集(驻留在内存中)并对其进行排序。不需要索引。但是通过“+ 0”,看起来他想禁用它。
因此,使用的技巧是无效的,现在只会误导人,正如您所发现的那样。
问候, 罗伯。
附注1:最好使用LPAD(TO_CHAR(a.code),5,'0')或TO_CHAR(a.code,'fm00009')。然后清楚地知道您正在处理的数据类型。
附注2:您的查询可能会从在LPAD(TO_CHAR(a.code),5,'0')上使用函数索引或使用左填充邮政编码的任何表达式中获益。

7

我的猜测是a.code是一个包含数字字符串的VARCHAR2,+0实际上将其转换为NUMBER,以便排序是数字而不是字母

您可以在+0之后添加ASC/DESC


2
这似乎是一种奇怪的方法 - 这样做有什么优势,而不是只使用 to_number(a.code) 吗? - FrustratedWithFormsDesigner
1
@Lucas B - 如果a.code已经是一个数字,那么+0就是多余的。 - Mark Baker
有人能提供一个参考来确认MarkBaker的猜测吗? - Lucas B
@LucasB - 你指的是哪个猜测? - APC
@Luca B:Mark 猜测 a.code 是一个 varchar2,是因为他无法访问 TBL_CODE_ZIP.CODE 的定义。我们在 StackOverflow 上也无法访问您的数据库或其中的对象定义,因此我们无法提供参考。您说 CODE 是一个 NUMBER(5),这意味着他的猜测是不正确的,您已经提供了反例。 - Shannon Severance
显示剩余4条评论

3
注意:我删除了这个答案,因为Mark B打字速度更快。然而,我重新恢复它,因为我认为演示Lucas发布的SQL可能潜在意图有一定价值。
假设CODE是一个包含数字字符串(邮政编码)的VARCHAR2列。问题在于varchars按字符串而不是数字排序。将零添加到CODE会产生隐式转换为数字,因此可以进行数字排序:
SQL> select id, code
  2  from t72
  3  order by code
  4  /

        ID CODE
---------- -----
         1 1
         2 11
         3 111
         4 12

SQL> select id, code
  2  from t72
  3  order by code+0
  4  /

        ID CODE
---------- -----
         1 1
         2 11
         4 12
         3 111

SQL>

如果存储的代码已经用零填充,则不需要进行转换,因为它们会按数字顺序排序。正如其他人所指出的那样,使用TO_NUMBER()将是更好的选择。+0比显式转换不太明显,清楚表达意图总是有益的。

to_number(a.code) 会有相同的效果吗,还是与 +0 有区别? - FrustratedWithFormsDesigner
1
我认为 to_number 会产生相同的效果,并且对读者来说更明显。 - Lucas B

1

TBL_CODE_ZIP.Code上有索引吗? 我看过一些查询,在查询的某个部分添加0(或''到字符串)以强制优化器避免使用索引。(当然,避免使用索引的正确方法是添加适当的提示)

也许原始作者遇到了ORDER BY被优化为索引扫描的问题,这导致查询运行较慢;因此他们添加了+0以强制使用不同的访问路径并进行普通排序。


是的,有一个名为CODE_ZIP_CODE_IX的索引,其中包含Code,在此查询中,我们正在“提示”使用该索引。当我通过Explain Plan查看它时,与+0和不带+0相比,计划是相同的。 - Lucas B
1
@Lucas,是的,现在它不一定会有所不同。或者开发人员可能错误地认为这样做会使它更快,因为“以前对我有效” :) - Jeffrey Kemp
我同意,我的一位同事认为这可能是Oracle 8实现的剩余部分。感谢您的洞察力。 - Lucas B

0
首先很抱歉回答这个问题,因为它现在已经非常老了。然而,+0 是一个提示,告诉您的数据库忽略此特定查询的索引(如果它在 a.Code 列上)。
有时索引可以使检索变得更快,而有时则会使其变得非常慢,这取决于数据库的优化器模式。
所以现在您有两个选项,要么使用 +0 提示,要么删除索引,如果它在 a.code 上,您将获得相同的速度。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接