【问题标题】:Dynamic SQL same from and where clause but different select clause one working one not动态 SQL 相同的 from 和 where 子句,但不同的 select 子句一个工作一个不工作
【发布时间】:2016-04-02 18:50:28
【问题描述】:

我经历了一次工作失败。在作业中,使用 offcid 和 spool 文件调用 PLS。我检查了假脱机文件,错误是无效的数字。通过传递 offcid 在 PLS 中单独运行查询时,我发现错误来自一个选择查询,其中 offcid 在 where 子句中动态传递。

where offcid = &2;

在进一步检查详细信息时,我发现还有一个关于 from 和 where 子句的相同查询,只有 select 子句不同(没有 group by),但运行良好。 offcid 在作业中传递为 43。根据高级开发人员的建议,我们扫描了表,发现源表中的一条记录的 offcid 列中有字符值,我们将其删除,然后查询运行正常。

我只在开发环境中的生产环境中遇到了这个错误,在相同的场景下,相同的查询运行良好。有谁知道可能是什么导致了这个问题? oracle 11g 是否有任何可能导致此问题的后端检查?

【问题讨论】:

    标签: plsql oracle11g


    【解决方案1】:

    所以 offcid 被定义为 VARCHAR2 而不是数字列?如果是这种情况,您可能希望将替换变量括在引号中,以便将传入的值也视为字符。 (该列是否应该被定义为数字列是另一回事。)

    如果我理解您的问题,您想知道为什么假设两个环境具有相同的数据,一个环境在一个环境中而不是另一个环境中遇到“无效数字”错误?

    如果您尝试将字符串与数字进行比较,Oracle 会先隐式尝试将字符值转换为数字,然后将结果与数字进行比较。也就是说,像这样:

    SELECT * FROM dual WHERE '1' = 1 
    

    实际上会这样评估:

    SELECT * FROM dual WHERE TO_NUMBER('1') = 1
    

    这里可以将字符串'1'转换为数字,一切正常。

    在您的情况下,如果 &2 被替换为 10,您的查询将被评估为:

    SELECT ... where TO_NUMBER(offcid) = 10
    

    即使表确实有无法转换为数字的 offcid 值,您也会间歇性地收到“无效数字”错误的原因取决于 Oracle 是否实际上认为包含不能被转换的值的行转换为数字。这一切都取决于用于查询的执行计划。

    假设您有这样的查询:

    SELECT ... FROM some_table where TO_NUMBER(offcid) = 17 AND another_column = 4
    

    假设您的违规行有 offcid = 'ONE7' 和 another_column = 2

    如果 Oracle 对 some_table 进行全表扫描,它将比较所有行,当它遇到无法转换为数字的值的行时会遇到错误(比如“XYZ” )。但是,如果您在 another_column 上有一个索引,Oracle 决定首先使用该索引来隔离 another_column = 4 的行,它不会查看 another_column = 2 的行,也不会尝试将“XYZ”转换为数字和你不会得到错误。

    可能有两个环境具有完全相同的数据和完全相同的查询,但因为使用了不同的执行计划(已知数据库版本会导致优化器工作方式发生变化可能会影响查询计划)您的查询可以在一种环境中正常运行,但在另一种环境中会失败。

    这有意义吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 2019-02-25
      • 1970-01-01
      • 2018-07-26
      • 2021-03-14
      • 2010-11-20
      相关资源
      最近更新 更多