【问题标题】:100 strings in IN operator, oracle pl/sqlIN 运算符中的 100 个字符串,oracle pl/sql
【发布时间】:2014-04-10 04:58:07
【问题描述】:

我在 IN 运算符中将 100 个表名作为字符串传递,但由于操作数过多,我收到了数字溢出错误。 除了 IN 之外,还有什么方法可以让我使用其他东西吗?

set serveroutput on

 DECLARE
  ...
 BEGIN
   FOR r IN 
   (
     SELECT table_name, column_name
     FROM all_tab_columns 
     WHERE table_name IN (...100 strings)
    )
AND data_type = 'NUMBER'
     ORDER BY table_name, column_id
   )
   LOOP
    execute immediate 'SELECT COUNT("' || r.column_name || '")
                             ,COUNT(nvl2("' || r.column_name || '", NULL, 1))                        
                       FROM "' || r.table_name || '"'
    INTO not_null_count, null_count;

    DBMS_OUTPUT.PUT_LINE(..)

注意:对于变量,我使用的是 PLS_Integer。

【问题讨论】:

  • 作为the documentation says,我们在IN 子句中最多可以有1000 个值。所以这不是你的问题。
  • 您收到的实际错误消息是什么?您如何将 100 个字符串传递给查询?
  • 是的,但这并不能解决我的问题
  • 所以回答我的其他问题。
  • 什么错误号? ORA-01426?

标签: oracle plsql in-operator


【解决方案1】:

ORA-01426 的建议操作是“减少操作数”。这并不意味着减少操作数的数量。这意味着您试图将太大的数字放入变量中。所以缩小数字,或者扩大变量。

你说:

“对于我使用 PLS_Integer 的变量”

因此,如果您有一个大表,并且我的意思是超过 2,147,483,647 行,您将得到一个数字溢出。因为PLS_INTEGERa 32-bit data type

如果这是您的场景,那么您需要声明数据类型为 INTEGER(或 NUMBER(38,0))的变量。


正如@BobJarvis 指出的那样,PLS_INTEGER 针对硬件算术进行了优化。所以一般的建议是使用它来计算类型操作。但是,您的情况只需要一个变量来保存 SQL count() 操作的输出,所以我认为效率不会有任何差异。

【讨论】:

  • 我总是对 PLS_INTEGER 有点困惑。在 SYS.STANDARD 中,我们找到 type NUMBER is NUMBER_BASE; subtype INTEGER is NUMBER(38, 0); subtype BINARY_INTEGER is INTEGER range '-2147483647'..-2147483647; subtype pls_integer is binary_integer;。因此,PLS_INTEGER 似乎是 NUMBER 的子类型(通过几层子类型)。我想使用硬件算法的优化是在幕后完成的。
  • @BobJarvis - 有趣的是,pls_integer 的类型是 binary integer,而它的类型正好相反。在 10g 之前,binary integer 是在独立于平台的 C 库中实现的(与其他数字数据类型一样); pls_integer 被引入(我认为是在 8.0 中)具有更高性能的硬件优化。然后在 10g 中,他们将 binary integer 转换为同样的操作。
【解决方案2】:

我相信“IN”子句的限制是 1000 个字符串,而不是 100 个字符串。调试:

a.) 尝试在 SQL 中运行隐式游标查询。

b.) 如果工作正常,则在替换列名后立即运行查询。 另外,尝试增加 not_null_count 和 null_count 变量的大小。

希望对你有帮助

维沙德

【讨论】:

  • 为什么“相信”你可以在文档中验证的东西? Find out more
  • 对于我使用 PLS_Integer 的变量
【解决方案3】:

其他一些可能的解决方案

  1. 使用临时表 - 用表名填充它以过滤加入它。
  2. 创建一个全局数组类型

    create type table_of_varchar2 is table of varchar2(30)

使用table_name member of arr_tables_list填充数组和过滤器

【讨论】:

  • 这解决了错误的问题。 IN 子句中有 100 个元素不会导致数字溢出。
  • 同意。只是想我在这里添加一些可能相关的解决方案。
【解决方案4】:

除了 IN 之外,我还有什么方法可以使用其他东西吗?

考虑改用光标。

【讨论】:

    猜你喜欢
    • 2014-10-19
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 2017-11-13
    相关资源
    最近更新 更多