Oracle PL SQL删除字符串中的重复数据

时间:2014-02-21 03:28:42

标签: sql oracle format

.....
temp Varchar2 (20);
e_name Varchar2 (255);
.....

Begin

e_name := e_name || temp;

Dbms_Output.Put_Line('names: ' || e_name);

Output result
-------------
names: 'John', 'Sam', 'David', 'Sam', 'John', 'Alex'

如何格式化我的e_name以删除重复的名称,以便我有输出结果

required result
-------------
names: 'John', 'Sam', 'David', 'Alex'

4 个答案:

答案 0 :(得分:1)

你可以像这样修改你的程序

Begin
e_name := e_name || temp;
 SELECT listagg ( names, ',' ) within GROUP (ORDER BY rn )
   INTO e_name
   FROM
  (
         SELECT level rn,
                regexp_substr ( e_name, '[^,]+', 1, level ) names,
                row_number ( ) over ( partition BY regexp_substr ( e_name, '[^,]+', 1, level ) order by level ) rnn
           FROM dual
          CONNECT BY regexp_substr ( e_name, '[^,]+', 1, level ) IS NOT NULL
  )
  WHERE rnn = 1;

Dbms_Output.Put_Line('names: ' || e_name);

最内层的查询会将列表转换为行,然后外部查询将过滤并再次创建字符串。

答案 1 :(得分:1)

用LISTAGG替换WM_CONCAT - 我正在运行Oracle 10g,LISTAGG是11g:

SELECT wm_concat(ename) AS employees
  FROM emp_test
 WHERE deptno = 20
/

 Output - SMITH repeats twice:
    SMITH,JONES,SCOTT,ADAMS,FORD,SMITH

SELECT wm_concat(distinct ename) AS employees
 FROM emp_test
WHERE deptno = 20
/

The distinct fixes the problem:
  ADAMS,FORD,JONES,SCOTT,SMITH

答案 2 :(得分:0)

这可以在纯SQL中完成,但它有点乱,特别是如果你是11gR2之前的listagg()。由于您已经处于PL / SQL领域,因此这是一种以简单的PL / SQL方式消除重复的解决方案:

declare e_name varchar2(255) := q'"'John', 'Sam', 'David', 'Sam', 'John', 'Alex'"';
        new_ename varchar2(255) := substr(e_name,1,instr(e_name,'''',2));
begin
dbms_output.put_line ('e_name: ' || e_name);
for i in 1..length(e_name) - length(replace(e_name,',')) loop
    if instr(new_ename,
        substr(e_name,instr(e_name,', ',1,i),instr(e_name||', ',', ',1,i+1) - instr(e_name,', ',1,i))) = 0
    then 
        new_ename := new_ename || substr(e_name,instr(e_name,', ',1,i),instr(e_name||', ',', ',1,i+1) - instr(e_name,', ',1,i));
    end if;
end loop;
dbms_output.put_line ('new_ename: ' || new_ename);
end;


e_name: 'John', 'Sam', 'David', 'Sam', 'John', 'Alex'
new_ename: 'John', 'Sam', 'David', 'John', 'Alex'

答案 3 :(得分:0)

有一些名为ASSOCIATIVE的数组,它在Java中充当哈希表。我们可以将分隔文本放入哈希表中,从而可以消除重复项。

我们在这里使用EXISTS收集方法来检查该值是否已经存在!

这是一个简单易读的 NO SQL 类型的解决方案。所以,执行一个。

DECLARE
   e_name VARCHAR2 (4000) := 'the text goes here';
   L_TEMP_TEXT  VARCHAR2(4000);
   V_LOOPCOUNT NUMBER :=0;
   T_WORD VARCHAR2(4000);
   T_FINAL_TEXT VARCHAR2(4000) := ' ';

   --Declare a DICT like a Hash table
   TYPE DICT IS TABLE OF VARCHAR2(4000) INDEX BY VARCHAR(4000);
   MYDICT DICT;
BEGIN
      L_TEMP_TEXT := regexp_replace(e_name,'[,]+',','); -- Replace multiple consecutive commas as single
      LOOP
        v_LOOPCOUNT := v_LOOPCOUNT+1;
        T_WORD      := REGEXP_SUBSTR(e_name, '[^,]+', 1, V_LOOPCOUNT);
        --In a loop we tokenize the String using comma as delimiter
        EXIT WHEN T_WORD IS NULL;

        IF NOT MYDICT.EXISTS(T_WORD) THEN
          -- It is like a Hash Table, if not exists add to it.
           MYDICT(T_WORD) := T_WORD;
           T_FINAL_TEXT : T_FINAL_TEXT || ',' || T_WORD;
        END;
      END LOOP;
      T_FINAL_TEXT := TRIM(BOTH ',' FROM TRIM(T_FINAL_TEXT));
      -- Trimming the unwanted commas

      DBMS_OUTPUT.PUT_LINE('after removing duplicates : ' || T_FINAL_TEXT);
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE(sqlerrm||chr(10)||dbms_utility.format_error_backtrace);
END;
/