当前位置:  开发笔记 > 后端 > 正文

为什么查询中的"Where 1 <> 1"会返回所有行?

如何解决《为什么查询中的"Where1<>1"会返回所有行?》经验,为你挑选了4个好方法。

我在一个我继承的应用程序中遇到了一个查询,如下所示:

Select *
From foo
where
    1 <> 1

当我解析它时,它应该什么都不返回(1 <> 1应该评估为false,对吧).但是(至少在我的Oracle盒子上)它会返回一个完整的所有内容列表foo.当我在MSAccess/Jet和MSSQL中尝试相同的事情时,我得到了我期望的行为.为什么它与Oracle不同(为什么原始开发人员想要这样做)?

注意:我看到一些关于使用"where 1 = 1"的+ s和-s的迷信,它会导致全表扫描; 但我不认为这是原始开发者的意图.

小更新:
在这种情况下foo是一个视图.当我在实际的桌子上尝试相同的事情时,我会得到我期望的(没有行).

更新2:
我已经在兔子洞的下方进一步遵循代码,并确定他正在做的只是尝试获取字段/列名称.我仍然不知道为什么它会返回完整的记录集; 但仅限于观点.

从字面上看,他正在用字符串构建查询并将其传递给另一个函数以便不加改变地执行.

'VB6
strSQL = "SELECT * FROM " & strTableName & " WHERE 1 <> 1"

在这种情况下,strTableName包含视图的名称.

更新3:
作为参考,这里是我遇到问题的一个视图(我已经更改了字段/表/模式名称)

CREATE OR REPLACE FORCE VIEW scott.foo (field1,
                                        field2,
                                        field4,
                                        field5,
                                        field12,
                                        field8,
                                        field6,
                                        field7,
                                        field16,
                                        field11,
                                        field13,
                                        field14,
                                        field15,
                                        field17
                                       )
AS
   SELECT   bar.field1,
            bar.field2,
            DECODE
               (yadda.field9, NULL, 'N',
                DECODE (yadda.field3, NULL, 'Y', 'N')
               ) AS field4,
            bar.field5,
            snafu.field6,
            DECODE
                (snafu.field6,
                 NULL,
                bar.field8,
                   bar.field8
                 - snafu.field6
                ) AS field7,
            DECODE
               (yadda.field10,
                NULL,
            bar.field12,
                yadda.field10
               ) AS field11,
            DECODE
               (SIGN (  yadda.field10 - bar.field12),
                NULL, 'N', 1, 'N', 0, 'N', -1, 'Y'
               ) AS field13,
            bar.field14,
            ADD_MONTHS
               (DECODE (yadda.field10, NULL, bar.field12, yadda.field10
                       ),
                bar.field14 * 12
               ) AS field15,
       FROM clbuttic,
            bar,
            yadda,
            snafu
      WHERE clbuttic.asset_type = bar.asset_type
        AND bar.field16 = yadda.field9(+)
        AND bar.field1 = snafu.field1(+)
        AND (bar.field17 IS NULL)
   ;

追加Order By 1(或者foo上的select中的一些列名)似乎说服Oracle给我回空集.这是一个长期解决方案,但不是短期解决方案(改变代码和重新部署是一个主要的PITA).我希望在数据库方面有一个鲜为人知的设置,或者视图中出现错误导致这种奇怪行为的原因.



1> Beska..:

好的......为什么在甲骨文中发生这种情况超出了我的想象.但是,我可以告诉你为什么它经常在其他数据库中使用:当人想要返回列时,但没有值.(例如为新表创建模式)



2> Paul Tomblin..:

Oracle不会为我这样做:

SQL*Plus: Release 10.2.0.1.0 - Production on Thu Mar 19 13:36:20 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL> select * from wrkr where 1 <> 1;

no rows selected

SQL> select count(*) from wrkr;

  COUNT(*)
----------
        88

编辑:它与观点无关,也是:

SQL> create view foo as select * from wrkr;

View created.

SQL> select count(*) from foo;

  COUNT(*)
----------
        88

SQL> select * from foo where 1 <> 1;

no rows selected



3> Mehrdad Afsh..:

当你想动态生成一个WHERE子句.这样,您可以添加一些OR [another-condition]子句并使其工作,而不检查条件是否是第一个.



4> 小智..:

它看起来像是Oracle优化器代码视图中的一个错误.我敢打赌你只能得到包含外连接的视图.你ORDER BY解决了它,因为它实际上强迫了NO_MERGE视图.

我不会在视图中放置一个ORDER BY或一个NO_MERGE提示,因为(取决于您的数据量)它可能会降低使用该视图的其他查询的性能.您应该在外部查询中添加no_merge提示:

Select /*+ NO_MERGE(foo) */ *
From foo
where
    1 <> 1

您还应该在Oracle支持下提出SR,因为这绝对是一个错误.无论您从中选择什么,或者内部有多复杂,该查询都不应该返回任何行.永远不能.

我无法重现它,所以它可能已修复我正在使用的版本.您正在使用的db版本是什么?

推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有