19

我想找到可以假定包含在名为 COPIA 的表中的名为 CLOB_COLUMN(CLOB 类型)的列的不同 CLOB 值。

我选择了一种程序方式来解决这个问题,但我更愿意给出一个简单的 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;
4

7 回答 7

13

如果可以将您的字段截断为 32767 个字符,则此方法有效:

select distinct dbms_lob.substr(FIELD_CLOB,32767) from Table1
于 2016-12-14T13:04:21.103 回答
8

您可以比较 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)具有相同散列的行子集来改进查询。

于 2010-10-13T11:28:45.353 回答
7

在 distinct 关键字之后添加TO_CHAR将 CLOB 转换为 CHAR

SELECT DISTINCT TO_CHAR(CLOB_FIELD) from table1;   //This will return distinct values in CLOB_FIELD
于 2019-04-10T11:45:48.980 回答
6

使用这种方法。在表配置文件内容是 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
;

它不会因为效率而赢得任何奖励,但应该有效。

于 2010-10-13T10:10:06.333 回答
3

从 table_name 中选择不同的 DBMS_LOB.substr(column_name, 3000);

于 2017-03-08T06:36:22.277 回答
1

如果将 clob 截断为 varchar2 的大小不起作用,并且您担心哈希冲突,您可以:

  • 为每一行添加一个行号;
  • 在不存在的子查询中使用 DBMS_lob.compare。排除具有更高 rownum 的重复项(这意味着: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  
于 2018-09-24T15:09:41.163 回答
0

要绕过 oracle 错误,您必须执行以下操作:

SELECT CLOB_COLUMN FROM TABLE COPIA C1 WHERE C1.ID IN(SELECT DISTINCT C2.ID FROM COPIA C2 WHERE ....)

于 2013-09-11T15:57:25.677 回答