ВЫБЕРИТЕ DISTINCT CLOB_COLUMN ОТ TABLE; - PullRequest
12 голосов
/ 13 октября 2010

Я хотел бы найти различные значения 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;

Ответы [ 7 ]

7 голосов
/ 13 октября 2010

Вы можете сравнить хэши 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))

Edit:

Функция HASH не гарантирует, что столкновения не будет. Однако, по замыслу, очень маловероятно, что вы получите какое-либо столкновение. Тем не менее, если риск столкновения (<2 ^ 80?) Неприемлем, вы можете улучшить запрос, сравнив (с <code>dbms_lob.compare) подмножество строк, имеющих одинаковые хэши.

4 голосов
/ 14 декабря 2016

Если допустимо урезать ваше поле до 32767 символов, это работает:

select distinct dbms_lob.substr(FIELD_CLOB,32767) from Table1
4 голосов
/ 13 октября 2010

Используйте этот подход.В таблице профиль столбец содержание равно 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
;

Он не собирается выигрывать призы за эффективность, но должен работать.

1 голос
/ 10 апреля 2019

добавить TO_CHAR после отдельного ключевого слова для преобразования CLOB в CHAR

SELECT DISTINCT TO_CHAR(CLOB_FIELD) from table1;   //This will return distinct values in CLOB_FIELD
1 голос
/ 24 сентября 2018

Если усечение 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  
1 голос
/ 08 марта 2017

выбрать отдельный DBMS_LOB.substr (имя_ столбца, 3000) из имени_таблицы;

0 голосов
/ 11 сентября 2013

Чтобы обойти ошибку оракула, вы должны сделать что-то вроде этого:

ВЫБЕРИТЕ CLOB_COLUMN ИЗ ТАБЛИЦЫ КОПИИ C1 ГДЕ C1.ID IN (ВЫБЕРИТЕ РАЗЛИЧНЫЙ C2.ID ИЗ КОПИИ C2 ГДЕ ....)

...