子查询适用于9i但不适用于11g

时间:2010-12-28 13:54:45

标签: sql oracle oracle11g

以下声明适用于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子句的位置。 此查询应返回两行,就像在Oracle 9i上一样,但在Oracle 11g EE 11.2.0.1.0 - 64位上返回ORA-01476: divisor is equal to zero


有人可以帮忙吗?谢谢!

3 个答案:

答案 0 :(得分:5)

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

alter session set optimizer_features_enable='11.1.0.7'

更改优化器功能解决了这个问题。

答案 1 :(得分: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&gt; = 1.3.1 / 1.4.1(尚未发布),您可能必须使用参数“connectionInitSqls”而不是“initConnectionSqls”作为版本DBCP的1.3和1.4错误地使用“initConnectionSqls”作为JNDI对象工厂配置的此属性的名称。

有关详细信息,请查看Apache Tomcat 7 - JNDI Resources HOW-TOApache Commons - Database Connection Pooling Configuration

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

答案 2 :(得分:0)

不幸的是,我无法重现它。

作为解决方法,请尝试以下方法:

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)
        )