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

Oracle删除表重复行SQL执行报错、结果异常问题求助

问题成因

该问题由两个独立错误共同导致:

  • 字段精度定义错误
    建表时commission字段声明为numeric(5),Oracle中数值类型NUMBER(总长度, 小数位数)如果省略小数位数参数,默认小数位数为0,即仅能存储整数。你插入的0.11~0.15区间的佣金值,入库时会被自动截断为0,这是所有记录commission字段显示为0的根本原因,和删除操作无关。
  • 删除语句语法不兼容Oracle
    你编写的DELETE 别名 FROM (子查询) 别名 WHERE 条件是MySQL、SQL Server支持的多表删除语法,Oracle不支持该语法结构,执行时不会按照预期逻辑删除重复行,最终出现操作结果不符合预期的问题。
正确操作步骤

1. 修复字段定义,修正错误数据

首先调整commission字段的精度,让它支持存储2位小数的佣金值,再修正已经被截断为0的错误数据:

-- 修改字段精度,总长度5位,保留2位小数,满足佣金存储需求
ALTER TABLE salesmen MODIFY commission NUMERIC(5,2);

-- 若当前表内都是被截断的错误数据+重复数据,可直接清空后重新插入正确值
TRUNCATE TABLE salesmen;
INSERT INTO salesmen (salesman_id, name, city, commission) VALUES (5001, 'james hoog', 'new york', 0.15);
INSERT INTO salesmen (salesman_id, name, city, commission) VALUES (5002, 'nail knite', 'paris', 0.13);
INSERT INTO salesmen (salesman_id, name, city, commission) VALUES (5005, 'pit alex', 'london', 0.11);
INSERT INTO salesmen (salesman_id, name, city, commission) VALUES (5006, 'mc lyon', 'paris', 0.14);
INSERT INTO salesmen (salesman_id, name, city, commission) VALUES (5007, 'paul adam', 'rome', 0.13);
INSERT INTO salesmen (salesman_id, name, city, commission) VALUES (5003, 'lauson hen', 'san jose', 0.12);

注意:如果你之前多次执行插入已经生成了多批重复数据,不需要执行TRUNCATE清空,直接走下一步去重逻辑即可,去重完成后单独更新commission字段为正确值即可。

2. 执行Oracle兼容的重复行删除逻辑

Oracle中推荐通过内置的ROWID(每行数据的唯一物理地址标识)配合窗口函数去重,执行效率高且逻辑稳定:

-- 执行删除前先查询核对待删除的重复行,确认无误后再执行DELETE
SELECT * FROM salesmen
WHERE ROWID IN (
    SELECT rid
    FROM (
        SELECT 
            ROWID AS rid,
            ROW_NUMBER() OVER (
                PARTITION BY salesman_id, name, city, commission 
                ORDER BY ROWID
            ) AS rn
        FROM salesmen
    )
    WHERE rn > 1
);

-- 核对无误后执行删除,每个重复分组仅保留ROWID最小的第一条记录
DELETE FROM salesmen
WHERE ROWID IN (
    SELECT rid
    FROM (
        SELECT 
            ROWID AS rid,
            ROW_NUMBER() OVER (
                PARTITION BY salesman_id, name, city, commission 
                ORDER BY ROWID
            ) AS rn
        FROM salesmen
    )
    WHERE rn > 1
);

-- 执行提交生效
COMMIT;

如果表数据量较小,也可以用临时表中转去重:

-- 创建临时表存储去重后的数据
CREATE GLOBAL TEMPORARY TABLE salesmen_tmp ON COMMIT PRESERVE ROWS AS
SELECT DISTINCT salesman_id, name, city, commission FROM salesmen;

-- 清空原表重复数据
TRUNCATE TABLE salesmen;

-- 插回去重后的数据
INSERT INTO salesmen SELECT * FROM salesmen_tmp;
COMMIT;

-- 清理临时表
DROP TABLE salesmen_tmp;

内容的提问来源于stack exchange,提问作者Franck yao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:36:18