You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PL/SQL查找单表重复行失败,求解决方案与建议

嘿,我来帮你搞定用PL/SQL查找Oracle emp表重复行的需求!首先咱们得先明确“重复行”的定义——这里我默认是指除主键empno外,其他核心字段(ename、job、mgr、hiredate、sal、comm、deptno)完全一致的记录(你可以根据实际需求调整字段)。下面是几个可以直接用的PL/SQL实现方案:

方案1:PL/SQL匿名块(快速测试用)

这个匿名块直接查询并输出所有重复行,适合快速验证你的测试数据:

SET SERVEROUTPUT ON;

DECLARE
    CURSOR c_duplicate_emp IS
        SELECT e.*
        FROM emp e
        JOIN (
            -- 先找出存在重复的字段组合
            SELECT ename, job, mgr, hiredate, sal, comm, deptno
            FROM emp
            GROUP BY ename, job, mgr, hiredate, sal, comm, deptno
            HAVING COUNT(*) > 1
        ) dup
        ON e.ename = dup.ename
        AND e.job = dup.job
        AND e.mgr = dup.mgr
        AND e.hiredate = dup.hiredate
        AND NVL(e.sal, 0) = NVL(dup.sal, 0)  -- 处理NULL值,避免因NULL不相等漏判
        AND NVL(e.comm, 0) = NVL(dup.comm, 0)
        AND e.deptno = dup.deptno
        ORDER BY e.ename, e.empno;
    v_emp emp%ROWTYPE;
BEGIN
    DBMS_OUTPUT.PUT_LINE('重复的员工记录:');
    DBMS_OUTPUT.PUT_LINE('EMPNO | ENAME  | JOB       | MGR  | HIREDATE  | SAL   | COMM  | DEPTNO');
    DBMS_OUTPUT.PUT_LINE('------|--------|-----------|------|-----------|-------|-------|-------');
    
    OPEN c_duplicate_emp;
    LOOP
        FETCH c_duplicate_emp INTO v_emp;
        EXIT WHEN c_duplicate_emp%NOTFOUND;
        
        -- 格式化输出,让结果更清晰
        DBMS_OUTPUT.PUT_LINE(
            RPAD(v_emp.empno, 6) || '|' ||
            RPAD(v_emp.ename, 8) || '|' ||
            RPAD(v_emp.job, 11) || '|' ||
            RPAD(NVL(v_emp.mgr, 0), 4) || '|' ||
            TO_CHAR(v_emp.hiredate, 'YYYY-MM-DD') || '|' ||
            RPAD(NVL(v_emp.sal, 0), 7) || '|' ||
            RPAD(NVL(v_emp.comm, 0), 7) || '|' ||
            v_emp.deptno
        );
    END LOOP;
    CLOSE c_duplicate_emp;
    
    IF c_duplicate_emp%ROWCOUNT = 0 THEN
        DBMS_OUTPUT.PUT_LINE('未找到重复记录');
    END IF;
END;
/

方案2:封装成存储过程(可复用)

如果需要多次使用,把逻辑封装成存储过程更方便:

CREATE OR REPLACE PROCEDURE find_duplicate_emp
IS
    CURSOR c_duplicate_emp IS
        SELECT e.*
        FROM emp e
        JOIN (
            SELECT ename, job, mgr, hiredate, sal, comm, deptno
            FROM emp
            GROUP BY ename, job, mgr, hiredate, sal, comm, deptno
            HAVING COUNT(*) > 1
        ) dup
        ON e.ename = dup.ename
        AND e.job = dup.job
        AND e.mgr = dup.mgr
        AND e.hiredate = dup.hiredate
        AND NVL(e.sal, 0) = NVL(dup.sal, 0)
        AND NVL(e.comm, 0) = NVL(dup.comm, 0)
        AND e.deptno = dup.deptno
        ORDER BY e.ename, e.empno;
    v_emp emp%ROWTYPE;
BEGIN
    DBMS_OUTPUT.PUT_LINE('重复的员工记录:');
    DBMS_OUTPUT.PUT_LINE('EMPNO | ENAME  | JOB       | MGR  | HIREDATE  | SAL   | COMM  | DEPTNO');
    DBMS_OUTPUT.PUT_LINE('------|--------|-----------|------|-----------|-------|-------|-------');
    
    OPEN c_duplicate_emp;
    LOOP
        FETCH c_duplicate_emp INTO v_emp;
        EXIT WHEN c_duplicate_emp%NOTFOUND;
        
        DBMS_OUTPUT.PUT_LINE(
            RPAD(v_emp.empno, 6) || '|' ||
            RPAD(v_emp.ename, 8) || '|' ||
            RPAD(v_emp.job, 11) || '|' ||
            RPAD(NVL(v_emp.mgr, 0), 4) || '|' ||
            TO_CHAR(v_emp.hiredate, 'YYYY-MM-DD') || '|' ||
            RPAD(NVL(v_emp.sal, 0), 7) || '|' ||
            RPAD(NVL(v_emp.comm, 0), 7) || '|' ||
            v_emp.deptno
        );
    END LOOP;
    CLOSE c_duplicate_emp;
    
    IF c_duplicate_emp%ROWCOUNT = 0 THEN
        DBMS_OUTPUT.PUT_LINE('未找到重复记录');
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('查询出错:' || SQLERRM);
        RAISE;  -- 抛出异常,方便上层处理
END find_duplicate_emp;
/

调用存储过程的方式很简单:

SET SERVEROUTPUT ON;
EXEC find_duplicate_emp;

你之前代码失败的可能原因排查:

  • 未处理NULL值:Oracle中NULL = NULL返回的是未知,不是真,所以如果你的重复行中有comm或sal为NULL的情况,直接用等于判断会匹配失败——这也是我在代码里加NVL()的原因。
  • 重复行定义不符:比如你只比较了部分字段,但复制的测试行在未比较的字段上有差异,导致没查出来。
  • 游标/循环逻辑错误:比如忘记打开游标、循环终止条件写错,或者没有正确处理游标遍历。

你可以根据自己实际的重复判断需求,修改分组查询中的字段列表。比如如果只认为ename和deptno相同就算重复,就把GROUP BY和JOIN条件改成这两个字段即可。

内容的提问来源于stack exchange,提问作者Carlos Johnes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:16:51