【问题标题】:Selecting big size docs from oracle db从 oracle db 中选择大尺寸文档
【发布时间】:2014-05-06 13:14:36
【问题描述】:

所以想获取大于 60 mb 的文档的 ID:

SELECT

DOCS.ID

FROM DOCS

where LENGTH(DOCS.DOCUMENT) > (60*1024*1024) 

我得到这个错误: SQL 错误:ORA-00932:不一致的数据类型:预期 NUMBER 得到 LONG BINARY 00932. 00000 - “不一致的数据类型:预期的 %s 得到了 %s” 文档很长,很原始... 可能应该以某种方式投射到长???

我想出的唯一解决方案是将表从 long raw 更改为 BLOB,然后出于某种神圣的原因,您必须为该表重新创建所有索引......这是唯一的方法。

【问题讨论】:

    标签: oracle oracle11g oracle-sqldeveloper


    【解决方案1】:

    这确实是个问题,但您可以使用 PL/SQL 作为解决方法:

    create or replace function get_doc_length(iDocId in number) return number is
      aLong long;
    begin
      select d.document into aLong from docs d where d.id = iDocId;
    
      return length(aLong);
    end;
    /
    

    这个函数(不幸的是,它不能使用LONG作为参数,所以必须特定于表DOCS)然后可以像这样使用:

    SELECT DOCS.ID
    FROM DOCS
    where get_doc_length(DOCS.ID) > (60*1024*1024)
    

    编辑:好的,这不适用于大 LONGs。您必须深入挖掘 SQL 的奥秘才能完成这项工作:

    create or replace function get_doc_length(iDocId in number) return number is
      myQuery  varchar2(200);
      myCursor binary_integer;
      myRes    pls_integer;
      myDoc    clob;
    
      long_val long;
      long_len integer;
      buf_len  integer;
      cur_pos  number;
    begin
    
      myQuery := 'select d.document from docs d where d.id = ' || iDocId;
    
      -- Create cursor, parse and bind.
      myCursor := DBMS_SQL.OPEN_CURSOR;
      DBMS_SQL.PARSE(myCursor, myQuery, DBMS_SQL.NATIVE);
      DBMS_SQL.DEFINE_COLUMN_LONG(myCursor, 01);
    
      myRes := DBMS_SQL.EXECUTE(myCursor);
    
      -- Fetch row (only one normally)
      if DBMS_SQL.FETCH_ROWS(myCursor) > 0 then
        -- Create CLOB.
        DBMS_LOB.CREATETEMPORARY(myDoc, false, DBMS_LOB.CALL);
    
        -- Piecewise fetching of the LONG column, appending to the CLOB.
        buf_len := 32760;
        cur_pos := 0;
        loop
          DBMS_SQL.COLUMN_VALUE_LONG(myCursor, 01, buf_len, cur_pos, long_val, long_len);
          exit when long_len = 0;
          DBMS_LOB.APPEND(myDoc, long_val);
          cur_pos := cur_pos + long_len;
        end loop;
      end if;
    
      DBMS_SQL.CLOSE_CURSOR(myCursor);
    
      return length(myDoc);
    end;
    /
    

    DBMS_SQL 包允许通过循环将LONG 转换为CLOB 并逐渐附加LONG 的片段。

    如果您想要CLOB 的二进制长度而不是其字符长度(这可能会有所不同),您可以使用dbms_lob.getlength 而不是length,如this other SO post 所示。

    【讨论】:

    • 有没有办法在没有存储过程的情况下做到这一点?
    • 我没有找到任何东西,正如我在谷歌搜索时看到的其他几个帖子一样。很遗憾,因为您必须为每个要获取的 LONG 字段创建一个这种类型的函数...
    • 对于较小的文档,这是可行的,但是当我们必须处理较大的文档时,这就是我得到的...错误报告:SQL 错误:ORA-06502:PL/SQL:数字或值错误 ORA- 06512:在“xxx.GET_DOC_LENGTH”处,第 10 行 06502。00000 -“PL/SQL:数字或值错误%s”
    • 我有一个使用 LONG 到 CLOB 转换的解决方案,请参阅我的编辑。
    • 不幸的是这个函数抛出了这个错误,我也认为我们可以尝试使用 BLOB 而不是 CLOBS 错误报告:SQL 错误:ORA-00932:不一致的数据类型:预期的数字得到了 LONG BINARY ORA-06512:在“ SYS.DBMS_SQL”,第 1575 行 ORA-06512:在“SOS.GET_DOC_LENGTH”,第 20 行 00932。00000 -“不一致的数据类型:预期的 %s 得到了 %s”
    【解决方案2】:
    SELECT DOCS.ID
    FROM DOCS
    WHERE dbms_lob.getlength(DOCS.DOCUMENT) > (60*1024*1024) 
    

    【讨论】:

    • SQL 错误:ORA-00997:非法使用 LONG 数据类型 00997。00000 -“非法使用 LONG 数据类型”
    猜你喜欢
    • 2023-01-18
    • 1970-01-01
    • 2015-06-18
    • 2015-03-12
    • 2018-07-18
    • 2013-03-23
    • 1970-01-01
    • 2012-11-12
    • 2020-08-20
    相关资源
    最近更新 更多