【问题标题】:Subquery works in 9i but not in 11g子查询在 9i 中有效,但在 11g 中无效
【发布时间】:2010-12-28 13:54:44
【问题描述】:

以下语句适用于 Oracle 9i,但不适用于 Oracle 11g

SELECT *
FROM
(
    SELECT 0 scrnfail_rate, '9' zz, 7 hh FROM DUAL
    UNION ALL
    SELECT 0 scrnfail_rate, '9' zz, 7 hh FROM DUAL
)
WHERE zz IS NOT NULL
AND TO_CHAR (hh) NOT IN
(
    SELECT
        DECODE
        (
            scrnfail_rate, 0, -1,
                ROUND (LEVEL * 1 / (scrnfail_rate / 100)) 
                - 
                ROUND (1 / (2 * (scrnfail_rate / 100)))
        ) AS nno
    FROM   DUAL
    WHERE   NVL (scrnfail_rate, 0) > 0
    CONNECT BY   LEVEL <= ROUND(9 * scrnfail_rate / 100)
)

看起来 Oracle 11g 忽略了 where decode 甚至是子查询中的 where 子句。 该查询应该像在 Oracle 9i 上一样返回两行,但在 Oracle 11g EE 11.2.0.1.0 - 64 位上返回 ORA-01476: divisor is equal to zero


有人可以帮忙吗?谢谢!

【问题讨论】:

  • 对我来说在 10g11g 上都有效。
  • 这么多来自 DUAL 的 SELECT... 你最好写一个存储过程之类的。
  • 请在9i11g 中发布查询的执行计划。
  • @Vitaly:我相信这只是一个重现错误的测试用例。
  • 按大小写替换解码...当...结束。

标签: sql oracle oracle11g


【解决方案1】:

我发现 Oracle 11.2.0.1.0 中存在导致此问题的错误。

alter session set optimizer_features_enable='11.1.0.7'

改变优化器特性可以解决这个问题。

【讨论】:

    【解决方案2】:

    如果您遇到此问题并且无法从 SQL 脚本中删除子查询,我建议您使用 Zsuetams 解决方案并使用:

    alter session set optimizer_features_enable='11.1.0.7';
    

    您甚至可能想要更改 Oracle 实例的系统设置,以便只要通过执行以下命令挂载数据库,此优化器设置就会自动对所有会话保持有效:

    alter system set optimizer_features_enable='11.1.0.7' scope=both;
    

    作为具有 ALTER SYSTEM 系统权限的用户(例如 SYS 用户)。

    如果您担心这种系统范围的部署会产生任何副作用,例如。 G。您正在运行一个集群,并且您担心使用 Oracle 实例系统设置进行调整可能也会对其他方产生影响(并且重新测试所有内容是不合理的)......然后您的应用程序容器可能会通过提供某种方式来扩展其 JNDI 来拯救带有一些 sql 初始化语句的 DataSource 资源配置。然后,连接工厂将在创建与此数据源的连接期间执行这些语句一次。

    例如,如果您使用的是 Tomcat 7,请使用 initConnectionSqls 参数:

        <Resource name="application.datasource" auth="Container"
                  type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
    [...]
                  initConnectionSqls="alter session set optimizer_features_enable=&apos;11.1.0.7&apos;" />
    

    注意:如果您使用 DBCP >= 1.3.1/1.4.1(尚未发布),您可能已经必须使用参数“connectionInitSqls”而不是“initConnectionSqls”作为 1.3 版本DBCP 1.4 错误地使用“initConnectionSqls”作为 JNDI 对象工厂配置的此属性的名称。

    查看Apache Tomcat 7 - JNDI Resources HOW-TOApache Commons - Database Connection Pooling Configuration 了解更多信息。

    哦,最后:一个更好的解决方案可能是升级到 Oracle 11g 版本 11.2.0.2.0 ;-)

    【讨论】:

      【解决方案3】:

      很遗憾,我无法重现它。

      作为一种解决方法,试试这个:

      SELECT  *
      FROM    (
              SELECT  0 scrnfail_rate, '9' zz, 7 hh
              FROM    DUAL
              UNION ALL
              SELECT  0 scrnfail_rate, '9' zz, 7 hh
              FROM    DUAL
              )
      WHERE   zz IS NOT NULL
              AND TO_CHAR (hh) NOT IN
              (
              SELECT  DECODE
                      (
                      scrnfail_rate, 0, -1,
                      ROUND (LEVEL * 1 / (DECODE(scrnfail_rate, 0, 1, scrnfail_rate) / 100)) - ROUND (1 / (2 * (DECODE(scrnfail_rate, 0, 1, scrnfail_rate) / 100)))
                      ) AS nno
              FROM    DUAL
              WHERE   NVL (scrnfail_rate, 0) > 0
              CONNECT BY
                      LEVEL <= ROUND(9 * scrnfail_rate / 100)
              )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-02
        • 2013-01-24
        • 2014-07-30
        • 2016-07-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多