ВЫБЕРИТЕ DISTINCT CLOB_COLUMN ОТ TABLE;
Я хотел бы найти различные значения CLOB, которые могут принимать столбец с именем CLOB_COLUMN (типа CLOB), содержащийся в таблице с именем COPIA.
Я выбрал ПРОЦЕДУРНЫЙ ПУТЬ для решения этой проблемы, но я бы предпочел дать простой SELECT следующим образом: SELECT DISTINCT CLOB_COLUMN FROM TABLE, чтобы избежать ошибки "ORA-00932: несовместимые типы данных: ожидается - получил CLOB"
Как мне этого добиться?
Заранее благодарю за любезное сотрудничество. Это процедурный способ, который я подумал:
-- Find the distinct CLOB values that can assume the column called CLOB_COLUMN (of type CLOB)
-- contained in the table called COPIA
-- Before the execution of the following PL/SQL script, the CLOB values (including duplicates)
-- are contained in the source table, called S1
-- At the end of the excecution of the PL/SQL script, the distinct values of the column called CLOB_COLUMN
-- can be find in the target table called S2
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE S1 DROP STORAGE';
EXECUTE IMMEDIATE 'DROP TABLE S1 CASCADE CONSTRAINTS PURGE';
EXCEPTION
WHEN OTHERS
THEN
BEGIN
NULL;
END;
END;
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE S2 DROP STORAGE';
EXECUTE IMMEDIATE 'DROP TABLE S2 CASCADE CONSTRAINTS PURGE';
EXCEPTION
WHEN OTHERS
THEN
BEGIN
NULL;
END;
END;
CREATE GLOBAL TEMPORARY TABLE S1
ON COMMIT PRESERVE ROWS
AS
SELECT CLOB_COLUMN FROM COPIA;
CREATE GLOBAL TEMPORARY TABLE S2
ON COMMIT PRESERVE ROWS
AS
SELECT *
FROM S1
WHERE 3 = 9;
BEGIN
DECLARE
CONTEGGIO NUMBER;
CURSOR C1
IS
SELECT CLOB_COLUMN FROM S1;
C1_REC C1%ROWTYPE;
BEGIN
FOR C1_REC IN C1
LOOP
-- How many records, in S2 table, are equal to c1_rec.clob_column?
SELECT COUNT (*)
INTO CONTEGGIO
FROM S2 BETA
WHERE DBMS_LOB.
COMPARE (BETA.CLOB_COLUMN,
C1_REC.CLOB_COLUMN) = 0;
-- If it does not exist, in S2, a record equal to c1_rec.clob_column,
-- insert c1_rec.clob_column in the table called S2
IF CONTEGGIO = 0
THEN
BEGIN
INSERT INTO S2
VALUES (C1_REC.CLOB_COLUMN);
COMMIT;
END;
END IF;
END LOOP;
END;
END;
8 ответов
Используйте этот подход. Содержимое столбца профиля таблицы - NCLOB. Я добавил предложение where, чтобы сократить время, необходимое для запуска,
with
r as (select rownum i, content from profile where package = 'intl'),
s as (select distinct (select min(i) from r where dbms_lob.compare(r.content, t.content) = 0) min_i from profile t where t.package = 'intl')
select (select content from r where r.i = s.min_i) content from s
;
Он не собирается выигрывать призы за эффективность, но должен работать.
Если допустимо урезать ваше поле до 32767 символов, это работает:
select distinct dbms_lob.substr(FIELD_CLOB,32767) from Table1
Вы можете сравнить хэши CLOB, чтобы определить, отличаются ли они:
SELECT your_clob
FROM your_table
WHERE ROWID IN (SELECT MIN(ROWID)
FROM your_table
GROUP BY dbms_crypto.HASH(your_clob, dbms_crypto.HASH_SH1))
Редактировать:
HASH
Функция не гарантирует, что не будет никакого столкновения. Однако, по замыслу, очень маловероятно, что вы получите какое-либо столкновение. Тем не менее, если риск столкновения (<2^80?) Неприемлем, вы можете улучшить запрос, сравнив (с dbms_lob.compare
) подмножество строк, имеющих одинаковые хеши.
Добавлять TO_CHAR
после отдельного ключевого слова для преобразования CLOB в CHAR
SELECT DISTINCT TO_CHAR(CLOB_FIELD) from table1; //This will return distinct values in CLOB_FIELD
Выберите отдельный DBMS_LOB.substr(column_name, 3000) из table_name;
Если усечение clob до размера varchar2 не будет работать, и вы опасаетесь коллизий хеша, вы можете:
- Добавить номер строки в каждую строку;
- Используйте DBMS_lob.compare в подзапросе "не существует". Исключите дубликаты (это означает: сравнить = 0) с более высоким значением.
Например:
create table t (
c1 clob
);
insert into t values ( 'xxx' );
insert into t values ( 'xxx' );
insert into t values ( 'yyy' );
commit;
with rws as (
select row_number () over ( order by rowid ) rn,
t.*
from t
)
select c1 from rws r1
where not exists (
select * from rws r2
where dbms_lob.compare ( r1.c1, r2.c1 ) = 0
and r1.rn > r2.rn
);
C1
xxx
yyy
Чтобы обойти ошибку оракула, вы должны сделать что-то вроде этого:
ВЫБЕРИТЕ CLOB_COLUMN ИЗ ТАБЛИЦЫ COPIA C1, ГДЕ C1.ID В (ВЫБЕРИТЕ РАЗЛИЧНЫЙ C2.ID ИЗ КОПИИ C2 ГДЕ....)
Я знаю, что это старый вопрос, но я считаю, что нашел лучший способ сделать то, что вы просите.
На самом деле это похоже на чит... Идея заключается в том, что вы не можете сделать DISTINCT для столбца Clob, но вы можете сделать DISTINCT для функции Listagg Clob_Column... вам просто нужно поиграть с предложение partition функции Listagg, чтобы убедиться, что она вернет только одно значение.
Имея это в виду... вот мое решение.
SELECT DISTINCT listagg(clob_column,'| ') within GROUP (ORDER BY unique_id) over (PARTITION BY unique_id) clob_column
FROM copia;