我试图创建函数,块或过程,以在表中找到重复的行(而不是在两个表之间)。我在Oracle“emp”中使用了默认表,当然我复制了一行,以查看结果。这是我的代码而我还没有成功
declare
cursor c1 is select * from emp;
cursor c2 is select * from emp;
V_REGISTERS c1%rowtype;
V_REGISTERS2 c2%rowtype;
BEGIN
<<OUTER>>
FOR V_REGISTERS IN c1
LOOP
FOR V_REGISTERS2 IN c2
LOOP
IF (
V_REGISTERS.EMPNO=V_REGISTERS2.EMPNO AND
V_REGISTERS.ENAME=V_REGISTERS2.ENAME AND
V_REGISTERS.JOB=V_REGISTERS2.JOB AND
V_REGISTERS.MGR = V_REGISTERS2.MGR AND
V_REGISTERS.HIREDATE=V_REGISTERS2.HIREDATE AND
V_REGISTERS.SAL=V_REGISTERS2.SAL AND
V_REGISTERS.COMM=V_REGISTERS2.COMM AND
V_REGISTERS.DEPTNO=V_REGISTERS2.DEPTNO
)
THEN
dbms_output.put_line('I HAVE FOUND THE REPEATED ROWS');
dbms_output.put_line(to_char(V_REGISTERS.empno) ||' '|| V_REGISTERS.ename ||' '|| V_REGISTERS.job ||' '|| to_char(V_REGISTERS.mgr) ||' '|| to_char(V_REGISTERS.hiredate)||' '||
to_char(V_REGISTERS.sal)||' '|| to_char(V_REGISTERS.comm)||' '|| to_char(V_REGISTERS.deptno));
dbms_output.put_line(to_char(V_REGISTERS2.empno) ||' '|| V_REGISTERS2.ename ||' '|| V_REGISTERS2.job ||' '|| to_char(V_REGISTERS2.mgr) ||' '|| to_char(V_REGISTERS2.hiredate)||' '||
to_char(V_REGISTERS2.sal)||' '|| to_char(V_REGISTERS2.comm)||' '|| to_char(V_REGISTERS2.deptno));
dbms_output.put_line(' ');
dbms_output.put_line(' ');
END IF;
END LOOP;
END LOOP OUTER;
END;
我完全了解使用动态函数,并丢弃pl / sql,就像这样......
select *
from (
select f.*,
count(*) over (partition by empno,ename,job) ct
from emp f
)
where ct > 1
......得到......
7698 BLAKE MANAGER 7839 01/05/81 2850 30 2
7698 BLAKE MANAGER 7839 01/05/81 2850 30 2
..但这不是我的目标。
任何帮助或建议,都会非常感激。感谢
答案 0 :(得分:1)
你试图做的循环也检查相同的记录,所以即使它有一个记录它会显示为重复..我修改你的游标得到rownum和条件不匹配相同的rownum在循环可能会给你正确的输出。
我做了以下。在创建表并插入重复记录后,我运行了脚本并返回了重复的记录。
create table emp
(empno number,
ename varchar2(10),
job varchar2(10),
mgr varchar2(10),
hiredate date,
sal number,
comm number,
deptno number);
insert into emp
values
(
7698, 'BLAKE', 'ASSISTANT', 'JERRY',to_date('14/02/2018','dd/mm/yyyy'), 7839, 2850, 30);
insert into emp
values
(
7698, 'BLAKE', 'ASSISTANT', 'JERRY',to_date('14/02/2018','dd/mm/yyyy'), 7839, 2850, 30);
insert into emp
values
(
7698, 'DAN', 'ANALYST', 'TOM',to_date('14/02/2018','dd/mm/yyyy'), 7839, 2850, 30);
declare
cursor c1 is select EMP.*,ROWNUM from emp ORDER BY EMPNO DESC;
cursor c2 is select EMP.*,ROWNUM from emp ORDER BY EMPNO DESC;
V_REGISTERS c1%rowtype;
V_REGISTERS2 c2%rowtype;
BEGIN
<<OUTER>>
FOR V_REGISTERS IN c1
LOOP
FOR V_REGISTERS2 IN c2
LOOP
IF (
V_REGISTERS.EMPNO=V_REGISTERS2.EMPNO AND
V_REGISTERS.ENAME=V_REGISTERS2.ENAME AND
V_REGISTERS.JOB=V_REGISTERS2.JOB AND
V_REGISTERS.MGR = V_REGISTERS2.MGR AND
V_REGISTERS.HIREDATE=V_REGISTERS2.HIREDATE AND
V_REGISTERS.SAL=V_REGISTERS2.SAL AND
V_REGISTERS.COMM=V_REGISTERS2.COMM AND
V_REGISTERS.DEPTNO=V_REGISTERS2.DEPTNO AND
V_REGISTERS.ROWNUM <> V_REGISTERS2.ROWNUM
)
THEN
dbms_output.put_line('I HAVE FOUND THE REPEATED ROWS');
dbms_output.put_line(to_char(V_REGISTERS.empno) ||' '|| V_REGISTERS.ename ||' '|| V_REGISTERS.job ||' '|| to_char(V_REGISTERS.mgr) ||' '|| to_char(V_REGISTERS.hiredate)||' '||
to_char(V_REGISTERS.sal)||' '|| to_char(V_REGISTERS.comm)||' '|| to_char(V_REGISTERS.deptno));
dbms_output.put_line(to_char(V_REGISTERS2.empno) ||' '|| V_REGISTERS2.ename ||' '|| V_REGISTERS2.job ||' '|| to_char(V_REGISTERS2.mgr) ||' '|| to_char(V_REGISTERS2.hiredate)||' '||
to_char(V_REGISTERS2.sal)||' '|| to_char(V_REGISTERS2.comm)||' '|| to_char(V_REGISTERS2.deptno));
dbms_output.put_line(' ');
dbms_output.put_line(' ');
END IF;
END LOOP;
END LOOP OUTER;
END;
输出:
我已经找到了重复的行
7698 BLAKE ASSISTANT JERRY 14-FEB-18 7839 2850 30
7698 BLAKE ASSISTANT JERRY 14-FEB-18 7839 2850 30
我已经找到了重复的行
7698 BLAKE ASSISTANT JERRY 14-FEB-18 7839 2850 30
7698 BLAKE ASSISTANT JERRY 14-FEB-18 7839 2850 30
答案 1 :(得分:1)
您可以使用GROUP BY功能,如下所示:
.gitignore
答案 2 :(得分:0)
这是一种只用一个光标和一个表格传递的方法。我们简单地记住前一行是什么,并将其与当前行进行比较。即使有很多,“l_in_a_dup_list”也只打印出1次重复,但如果你想要所有的重复,那么很容易删除。
SQL> create table t as select * from scott.emp;
Table created.
SQL> insert into t select * from scott.emp where rownum <= 2;
2 rows created.
SQL> insert into t select * from scott.emp where rownum <= 2;
2 rows created.
SQL> insert into t select * from scott.emp where rownum <= 2;
2 rows created.
SQL>
SQL> set serverout on
SQL> declare
2 --
3 -- we'll assume that empno/ename/hiredate is the definition of duplicate here
4 -- but it could be anything (including all columns)
5 --
6 l_this_key varchar2(4000);
7 l_prev_key varchar2(4000) := '<nothing yet>';
8 l_in_a_dup_list boolean := false;
9 begin
10 for i in (
11 select * from t
12 order by empno, ename, hiredate
13 )
14 loop
15 l_this_key := i. empno||'-'||i.ename||'-'||to_char(i.hiredate,'yyyymmddhh24miss');
16 if l_this_key = l_prev_key
17 then
18 if not l_in_a_dup_list then
19 dbms_output.put_line(l_this_key||' is a duplicate');
20 l_in_a_dup_list := true;
21 end if;
22 else
23 l_in_a_dup_list := false;
24 end if;
25 l_prev_key := l_this_key;
26 end loop;
27 end;
28 /
7369-SMITH-19801217000000 is a duplicate
7499-ALLEN-19810220000000 is a duplicate
PL/SQL procedure successfully completed.
答案 3 :(得分:0)
只需使用分析功能。 RANK()似乎最适合这里。
SELECT 列列表,以逗号分隔 FROM( 选择 RANK()OVER(由列分隔,由逗号分隔 ORDER BY RowIdentifier )RNK,* 来自EMP )RNK RNK.RNK&gt; 1
此查询将对表中的行进行分区并为其提供排名。例如,如果第3条记录和第5条记录在RANK()函数的分区子句中提到的那些列中具有相同的数据,那么它将第3行排名为1,第5行排名为2,因此在外部查询中如果你已经过滤了超过1的等级,你将获得所有重复的记录,如果你过滤了rank = 1,你将获得没有重复的独特记录。
谢谢☺