消除收集中的重复

时间:2017-01-13 23:15:19

标签: oracle object plsql types

我有一个声明的对象类型集合:

CREATE TYPE category_type AS OBJECT (
  col1   VARCHAR2(6),
  col2   VARCHAR2(10),
  col3   NUMBER);
/

CREATE TYPE category_tab AS TABLE OF category_type;
/

在PL / SQL代码中:

v_category_data     category_Tab := category_tab();

在我填充v_category_data后,我发现有重复项。我需要删除它们。因此,我尝试使用MULTISET UNION DISTINCT:

v_new_data := v_category_data;
v_new_data := v_new_data MULTISET UNION DISTINCT v_category_data;

然而,我收到此错误:

804/17   PLS-00306: wrong number or types of arguments in call to
         'MULTISET_UNION_DISTINCT'

我尝试使用MAP功能,但不明白如何使用它,或者它是否有用。

有没有人知道删除对象集合中重复项的方法?

2 个答案:

答案 0 :(得分:0)

multiset union distinct要求集合的元素具有可比性。在您的情况下,元素是PL / SQL记录,遗憾的是不是可比较的数据结构(即PL / SQL没有提供比较PL / SQL记录的内置机制)。

multiset union有效,因为它不需要比较元素。

如果出于某种原因,当您填充v_category_data集合时,您不想使用distinct,那么我建议按照下面的说明进行操作。从集合中选择并在列上使用distinct。

这是您感兴趣的部分:

SELECT Category_type(col1, col2, col3) 
bulk   collect INTO v_new_data 
FROM   (SELECT DISTINCT col1, 
                        col2, 
                        col3 
        FROM   TABLE(v_category_data)); 

这是我检查的整个代码。

DECLARE

v_category_data CATEGORY_TAB := Category_tab(); 
v_new_data      CATEGORY_TAB := Category_tab(); 

BEGIN 

--populate the collection with 2 types of duplicates and print them
FOR i IN 1 .. 10 LOOP 
    v_category_data.Extend(); 

    IF i < 4 THEN 
      V_category_data(v_category_data.last) := 
      Category_type('Test', 'Test', 1); 
    ELSE 
      V_category_data(v_category_data.last) := 
      Category_type('Test2', 'Test2', 2); 
    END IF; 
END LOOP; 

FOR i IN v_category_data.first..v_category_data.last LOOP 
    dbms_output.Put_line(V_category_data(i).col1 
                         ||' ' 
                         ||V_category_data(i).col2 
                         ||' ' 
                         ||V_category_data(i).col3); 
END LOOP; 

dbms_output.Put_line('After processing' 
                     ||Chr(10)); 

-- populate your collection using distinct and print the content
SELECT Category_type(col1, col2, col3) 
bulk   collect INTO v_new_data 
FROM   (SELECT DISTINCT col1, 
                        col2, 
                        col3 
        FROM   TABLE(v_category_data)); 

FOR i IN v_new_data.first..v_new_data.last LOOP 
    dbms_output.Put_line(V_new_data(i).col1 
                         ||' ' 
                         ||V_new_data(i).col2 
                         ||' ' 
                         ||V_new_data(i).col3); 
END LOOP; 

END; 

答案 1 :(得分:0)

请参阅下文我们如何实现这一目标:

CREATE TYPE category_type AS OBJECT (
  col1   VARCHAR2(6),
  col2   VARCHAR2(10),
  col3   NUMBER);
/

CREATE OR REPLACE  TYPE category_tab AS TABLE OF category_type   ;
/

declare

v_category_data    category_Tab := category_tab();
v_new_data         category_Tab := category_tab();

begin
--Defining collection length
v_category_data.extend(3);

--Populating the collection
v_category_data(1):= category_type('A','B',1);
v_category_data(2):= category_type('A','B',1);
v_category_data(3):= category_type('B','C',2);

dbms_output.put_line('*********First Collection Elements**************');
for i in 1..v_category_data.count
 loop  
  dbms_output.put_line(v_category_data(i).col1 || v_category_data(i).col2 || v_category_data(i).col3 );
 end loop;

--Way to remove duplicate
 select 
      v_category_data MULTISET UNION DISTINCT category_Tab(category_type('A','B',1))
    into 
      v_new_data 
    from 
  dual;

--Displaying elements of second collection
dbms_output.put_line('*********Second Collection Elements**************');
for i in 1..v_new_data.count
 loop
  dbms_output.put_line(v_new_data(i).col1 || v_new_data(i).col2 || v_new_data(i).col3 );
 end loop;

end;

输出

SQL> /
*********First Collection Elements**************
AB1
AB1
BC2
*********Second Collection Elements**************
AB1
BC2

PL/SQL procedure successfully completed.