ORA-00932: несогласованные типы данных: ожидалось - получил CLOB - при использовании clob в функции regexp_substr

Я пытаюсь использовать переменную CLOB в функции regexp_substr, как показано ниже

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 и содержит ~ разделенные идентификаторы.

При выполнении инструкции обновления я получаю сообщение об ошибке ниже:

ORA-00932: inconsistent datatypes: expected - got CLOB

Можем ли мы использовать CLOB с RegExp? Если нет, есть ли способ преобразовать значения CLOB в табличный формат?


person TechTurtle    schedule 25.09.2020    source источник
comment
В: Можно ли использовать CLOB с RegExp? A: Нет. Q: Есть ли способ преобразовать значения CLOB в табличный формат? A: Итак, вы хотите применить регулярное выражение к таблице ??? О: вы можете преобразовать CLOB в строку. Например, SELECT dbms_lob.substr( my_clob, 4000, 1 ) FROM my_table;   -  person paulsm4    schedule 26.09.2020
comment
Спасибо .. но если я конвертирую CLOB в строку, будут ли все значения? Я хочу создать временную таблицу из переменной CLOB. Поскольку мой CLOB имеет ~ разделенные идентификаторы. Далее я буду использовать эту временную таблицу в операторе обновления.   -  person TechTurtle    schedule 26.09.2020
comment
Вы НЕ МОЖЕТЕ применить регулярное выражение к CLOB. Я предложил одну альтернативу, Барбарос Озхан дал вам другую. ПРЕДЛОЖЕНИЕ: Возможно, вы захотите пересмотреть свой дизайн данных. Похоже, что то, что вы помещаете в CLOB, вероятно, должно было быть в первую очередь отдельными столбцами и / или отдельными таблицами :(   -  person paulsm4    schedule 26.09.2020
comment
Является ли tab_id типом данных number? Какая у вас версия оракула?   -  person Sayan Malakshinov    schedule 26.09.2020
comment
@ paulsm4 regexp_substr поддерживает clob: docs.oracle.com/cd/ B12037_01 / server.101 / b10759 / functions116.htm, но возвращает clob   -  person Sayan Malakshinov    schedule 26.09.2020
comment
@ Sayan Malakshinov - Факт остается фактом - вопиющее злоупотребление CLOB. Я настоятельно рекомендую OP пересмотреть свой дизайн данных :(   -  person paulsm4    schedule 26.09.2020
comment
@ paulsm4 Я бы не назвал это дизайном данных, потому что это была просто переменная clob, а не столбец, но - да, гораздо лучше использовать коллекции для таких вещей. Спасибо, что упомянули об этом, я добавлю это в свой ответ   -  person Sayan Malakshinov    schedule 26.09.2020
comment
@SayanMalakshinov прав, это не проблема DD, так как мне нужно передать большую строку, которая содержит ~ разделенные идентификаторы (номера типа).   -  person TechTurtle    schedule 28.09.2020


Ответы (3)


Попробуй это:

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
)
person Saxon    schedule 26.09.2020
comment
Это работает, и у него меньше конверсий по сравнению с тем, что предоставил @SayanMalakshinov. - person TechTurtle; 28.09.2020
comment
Это занимает 10 минут в Oracle для выполнения 1600 идентификаторов. Как мы можем создать чанк в самом Oracle SP? - person TechTurtle; 28.09.2020
comment
Если вам нужно более производительное программное обеспечение, я думаю, вам следует использовать PL / SQL, извлечь свои идентификаторы из clob и массово обновить свою таблицу. - person Saxon; 02.10.2020
comment
это именно то, что делает выбор внутри обновления. - person TechTurtle; 09.10.2020

данные должны быть преобразованы в строку (CHAR или числовой тип, рассматривающий Tab_ID столбец как INTEGER в этом случае) из CLOB, например

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 
       )
person Barbaros Özhan    schedule 25.09.2020
comment
Получение .... ORA-06502: PL / SQL: числовая ошибка или ошибка значения: буфер символьной строки слишком мал - person TechTurtle; 26.09.2020
comment
Вы можете поделиться примерами данных @TechTurtle ..? - person Barbaros Özhan; 26.09.2020
comment
См. Это: stackoverflow.com / questions / 64072157 / - person TechTurtle; 26.09.2020
comment
Спасибо, Барбарос, не могу вставить сюда строку, поэтому мне нужно создать новый вопрос, как указано выше. - person TechTurtle; 26.09.2020
comment
Итак, у меня нет столбца как CLOB, это переменная. Далее, в вашем примере, где я должен поместить свою переменную CLOB? это clb? - person TechTurtle; 26.09.2020
comment
Было бы сложно обрабатывать такую ​​длинную переменную, лучше попробуйте вставить в таблицу такую ​​как @TechTurtle - person Barbaros Özhan; 26.09.2020
comment
Хорошо, я попробую и дам тебе знать. Не уверен, что мы можем создавать временные таблицы в Oracle, но я думаю, что это должно быть возможно. - person TechTurtle; 26.09.2020
comment
Вы можете создавать временные таблицы (остается только во время сеанса) в Oracle, если это имеет значение @TechTurtle - person Barbaros Özhan; 26.09.2020
comment
но мне еще нужно разобрать его, верно? поскольку временная таблица будет содержать `разделенные значения в одном столбце, одной строке. - person TechTurtle; 26.09.2020
comment
конечно, @TechTurtle, это вы предпочитаете, хранить ли анализировать как целые числа в таблице или анализировать, когда это необходимо, с помощью такого запроса. Кстати, здесь уже очень поздно (около 3:00 утра), нужно ложиться спать :), в последнее время я смогу ответить, увидимся. - person Barbaros Özhan; 26.09.2020
comment
@ BarbarosÖzhan, у вас есть несколько ошибок в примере вашего запроса: 1. ваш подзапрос (SELECT clb FROM t CONNECT BY level <= CEIL(DBMS_LOB.GETLENGTH(clb) / 4000) должен завершиться ошибкой из-за бесконечного цикла (который вы пытаетесь избежать в родительском подзапросе с помощью prior sys_guid is not null; 2. тот же подзапрос просто возвращает дубликаты clb (похоже, вы пробовали для разделения clob на 4000 символов); 3. вам не нужно разделять CLOB, функции regexp отлично работают с CLOB; 4. length () также поддерживает CLOB, поэтому вам не нужен dbms_lob.getlength - person Sayan Malakshinov; 26.09.2020
comment
тоже не ошибка, но было бы лучше избегать: prior sys_guid() is not null - это слишком старый обходной путь для избежания бесконечных циклов в connect by, и такое поведение никогда не было задокументировано, в то время как существует много других более новых и более стандартных методов, например, рекурсивный факторинг подзапросов, боковые или multiset () и т. д. - person Sayan Malakshinov; 26.09.2020

regexp_substr возвращает CLOB, если ваш первый входной параметр - CLOB, но вы не можете сравнивать содержимое CLOB с чем-либо, используя in или =. Поэтому вам нужно преобразовать возвращенные вами 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
person Sayan Malakshinov    schedule 26.09.2020
comment
Использование коллекции: не знаю, как привязать, так как список чисел будет передан как параметр в SP. - person TechTurtle; 28.09.2020