ORA-00932: 不一致的数据类型: 预期 - 得到 CLOB - 在 regexp_substr 函数中使用 clob

Posted

技术标签:

【中文标题】ORA-00932: 不一致的数据类型: 预期 - 得到 CLOB - 在 regexp_substr 函数中使用 clob【英文标题】:ORA-00932: inconsistent datatypes: expected - got CLOB - while using clob in regexp_substr function 【发布时间】:2020-09-25 21:55:58 【问题描述】:

我正在尝试在 regexp_substr 函数中使用 CLOB 变量,如下所示

UPDATE TableName
SET Tab_DATE = SYSDATE
WHERE Tab_ID IN (
    select regexp_substr(clob_variable,'[^~]+', 1, level) from dual
    connect by regexp_substr(clob_variable, '[^~]+', 1, level) is not null
)

clob_variable 是 CLOB 类型,包含 ~ 分隔的 id。

执行更新语句时出现以下错误:

ORA-00932: inconsistent datatypes: expected - got CLOB

我们可以将 CLOB 与 RegExp 一起使用吗?如果没有,有没有办法将 CLOB 值转换为表格格式?

【问题讨论】:

问:我们可以将 CLOB 与 RegExp 一起使用吗?答:没有。 问:有什么方法可以将 CLOB 值转换为表格格式? A: 所以你想对 table 应用一个正则表达式???答:您可以做的就是将CLOB 转换为字符串。例如,SELECT dbms_lob.substr( my_clob, 4000, 1 ) FROM my_table; 谢谢.. 但是如果我将 CLOB 转换为字符串,它会占用所有值吗?我想从 CLOB 变量生成临时表。因为我的 CLOB 有 ~ 分隔的 ID。此外,我将在更新语句中使用这个临时表。 您不能将正则表达式应用于 CLOB。我建议了另一种选择,Barbaros Özhan 给了你另一种。建议:您可能想重新审视您的数据设计。听起来你放在 CLOB 中的东西可能首先应该是单独的列和/或单独的表:( tab_id 是数字数据类型吗?你的 oracle 版本是什么? @paulsm4 regexp_substr 支持 clob:docs.oracle.com/cd/B12037_01/server.101/b10759/functions116.htm 但它返回 clob 【参考方案1】:

数据应从CLOB 转换为字符串(CHAR 或数字类型,在这种情况下将Tab_ID 列视为INTEGER),例如

UPDATE TableName
   SET Tab_DATE = SYSDATE
 WHERE Tab_ID IN
       (
        SELECT TO_NUMBER(REGEXP_SUBSTR(clb, '[^~]+', 1, level))
          FROM (SELECT clb
                  FROM t -- the other table with CLOB column
               CONNECT BY level <= CEIL(DBMS_LOB.GETLENGTH(clb) / 4000))
       CONNECT BY level <= REGEXP_COUNT(clb, '~') + 1
           AND PRIOR SYS_GUID() IS NOT NULL 
       )

【讨论】:

谢谢巴巴罗斯,这里不能粘贴字符串,所以我必须创建新问题,如上所述。 很难处理这么长的变量,而是尝试插入到表中such as@TechTurtle 好的,我会尝试并告诉你。不确定我们是否可以在 Oracle 中创建临时表 - 但我想应该可以。 如果重要的话,您可以在 Oracle 中创建临时表(仅在会话期间保留)@TechTurtle 也没有错,但最好避免:prior sys_guid() is not null - 对于避免connect by 中的无限循环而言,这种解决方法太老了,而且这种行为从未被记录在案,而还有许多其他较新的以及更多标准方法,例如递归子查询分解、横向或 multiset() 等。【参考方案2】:

试试这个:

UPDATE TableName
SET Tab_DATE = SYSDATE
WHERE Tab_ID IN (
    select replace(dbms_lob.substr(regexp_substr(clob_variable,'[^~]+~', 1, level)), '~', '') from dual
    connect by dbms_lob.compare(regexp_substr(clob_variable,'[^~]+~', 1, level), empty_clob() ) != 0
)

【讨论】:

这很有效,与@SayanMalakshinov 提供的相比,它的转化次数更少。 这在 Oracle 中需要 10 分钟才能执行 1600 个 id。有什么方法可以在 Oracle SP 本身中创建块? 如果您想要一个性能更好的软件,我认为您应该使用 PL/SQL,从 clob 中提取您的 Id 并批量更新您的表。 这正是 select inside update 正在做的事情。【参考方案3】:

regexp_substr 在您的第一个输入参数是 CLOB 的情况下返回 CLOB,但您不能使用 in= 将 CLOB 的内容与任何内容进行比较。因此,您需要将返回的 CLOB 转换为 TAB_ID 的数据类型。

所以如果你的 TAB_ID 是数字类型,应该是:

UPDATE TableName
SET Tab_DATE = SYSDATE
WHERE Tab_ID IN (
    select to_number(to_char(regexp_substr(clob_variable,'[^~]+', 1, level))
    from dual
    connect by level<=regexp_count(clob_variable, '[^~]+')
)

如果您的 TAB_ID 是 varchar2 或 char:

UPDATE TableName
SET Tab_DATE = SYSDATE
WHERE Tab_ID IN (
    select to_char(regexp_substr(clob_variable,'[^~]+', 1, level)
    from dual
    connect by level<=regexp_count(clob_variable, '[^~]+')
)

更新: 将集合用于此类事情要好得多,而不是连接字符串。只需创建自己的集合,例如:

create or replace type numbers as table of number;
/

并将您的数字列表绑定为一个集合,因此您的查询将如下所示:

select * from tablename where id in (select * from table(:numbers))

在查询中使用集合的示例:

SQL> select * from table(numbers(1,2,3,4));

COLUMN_VALUE
------------
           1
           2
           3
           4

【讨论】:

使用集合:不确定如何绑定,因为数字列表将作为参数传递给 SP。

以上是关于ORA-00932: 不一致的数据类型: 预期 - 得到 CLOB - 在 regexp_substr 函数中使用 clob的主要内容,如果未能解决你的问题,请参考以下文章

ORA-00932: 不一致的数据类型: 预期 - 得到 CLOB

如何修复 PL/SQL:ORA-00932:不一致的数据类型:预期的 CLOB 得到了 -

ora-00932 不一致的数据类型预期数字得到 char plsql

ORA-00932: 不一致的数据类型: 预期 - 得到 clob 休眠/弹簧启动

无法选择 *(ORA-00932:不一致的数据类型:预期的 CHAR 得到了 ADT)

查找错误 ORA-00932:不一致的数据类型:预期的 DATE 得到了 NUMBER