【问题标题】:Reading BLOB column in oracle table读取 oracle 表中的 BLOB 列
【发布时间】:2021-01-21 05:27:03
【问题描述】:

我有一个表 tbl,它有以下几列:

create table tbl (id number,
                  colA BLOB,
                  ColB BLOB,
                  Insert_time timestamp(0)
                  )

当我运行以下查询时,它工作正常:

select id,
substr(substr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.colA), 2000, 1) ),instr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColA), 2000, 1) ),'MeterReadingReasonCode',1),25),24,2) first
--substr(substr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColB), 2000, 1) ),instr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColB), 2000, 1) ),'MeterReadingTypeCode',1),23),22,2) second
from tbl 
where
tbl.INSERT_TIME >=  To_Date('04-01-2020 12:00:00 AM' ,'dd-mm-yyyy hh12:mi:ss AM')
and tbl.INSERT_TIME <=  To_Date('04-08-2020 11:00:00 PM' ,'dd-mm-yyyy hh12:mi:ss AM')

但是当我在下面运行时会抛出错误:

select id,
substr(substr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.colA), 2000, 1) ),instr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColA), 2000, 1) ),'MeterReadingReasonCode',1),25),24,2) first
substr(substr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColB), 2000, 1) ),instr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColB), 2000, 1) ),'MeterReadingTypeCode',1),23),22,2) second
from tbl 
where
tbl.INSERT_TIME >=  To_Date('04-01-2020 12:00:00 AM' ,'dd-mm-yyyy hh12:mi:ss AM')
and tbl.INSERT_TIME <=  To_Date('04-08-2020 11:00:00 PM' ,'dd-mm-yyyy hh12:mi:ss AM')

我的意思是说,如果我只选择 1 个 blob 列来读取,那么日期过滤器就可以正常工作。 但是当我在 where 子句中选择两个带有日期过滤器的 BLOB 列时,它会抛出以下错误:

ORA-29261: bad argument
ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 60
ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 230
ORA-06512: at "SYS.UTL_COMPRESS", line 89
29261. 00000 -  "bad argument"
*Cause:    A bad argument was passed to the PL/SQL API.
*Action:   Check the arguments passed to the PL/SQL API and retry the call.

【问题讨论】:

    标签: sql oracle plsql blob


    【解决方案1】:

    这个简单的意思是(正如例外所暗示的那样)ColLB 列中包含的解压缩值无效。

    测试表明这很可能是一个具有NULL 值的列 - 请参见下面的脚本。

    create table tbl (ColB BLOB);
                      
    insert into tbl ( colb)
    values(null);
    
    select  
       utl_compress.lz_uncompress(tbl.ColB)
    from tbl  
    ;
    
    ORA-29261: bad argument
    ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 56
    ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 226
    ORA-06512: at "SYS.UTL_COMPRESS", line 89
    

    请注意,如果您存储了一个已损坏的非 NULL 值(即不是压缩格式),您会看到不同的异常

    insert into tbl ( colb)
    values(HEXTORAW('cafe'));
    
    select  
       utl_compress.lz_uncompress(tbl.ColB)
    from tbl  
    ;
    
    ORA-29294: A data error occurred during compression or uncompression.
    ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 56
    ORA-06512: at "SYS.UTL_SYS_COMPRESS", line 226
    ORA-06512: at "SYS.UTL_COMPRESS", line 89
    

    因此,作为一种解决方法,您应该使用 CASE 语句测试 NULL 来保护您的表达式

    select 
      case when colB is not NULL then 
        substr(substr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColB), 2000, 1) ),instr(utl_raw.cast_to_varchar2( dbms_lob.substr( utl_compress.lz_uncompress(tbl.ColB), 2000, 1) ),'MeterReadingTypeCode',1),23),22,2) 
      end as  second
    from tbl 
    

    【讨论】:

    • 嗨,Marmite,感谢您的意见。是的,你是对的。另一个 BLOB 列是可以为空的,因此它抛出了错误。我已经按照你的建议处理了。
    • @PujaShaw,欢迎您!
    猜你喜欢
    • 2012-04-07
    • 2013-10-25
    • 2020-08-20
    • 2017-06-14
    • 2012-01-16
    • 2016-07-24
    • 2014-11-01
    • 2011-08-06
    • 2021-08-28
    相关资源
    最近更新 更多