如何在无主键/唯一标识时删除数据库中重复字段的单条记录?
解决无主键表中重复记录删除的问题
这个场景太常见了——表没设主键或唯一约束,结果不小心出现了两条完全一样的记录,要删掉其中一条对吧?咱分不同数据库给你唠唠靠谱的操作方法,记得操作前一定要先备份数据,别手滑误删了!
通用核心思路
本质就是先给每条记录生成一个临时的唯一标识,把两条重复的记录区分开,再通过这个标识删除其中一条。不同数据库有不同的快捷方式,往下看:
MySQL/MariaDB 操作方法
- 快捷法(仅当确定只有两条重复时用):
直接用LIMIT删一条,数据库会随机选一条删掉(取决于存储引擎的扫描顺序):DELETE FROM your_table LIMIT 1; - 稳妥法(适合有更多重复的情况):
先加个自增临时列当唯一标识,删完再删掉这个列:-- 新增自增临时列 ALTER TABLE your_table ADD temp_id INT AUTO_INCREMENT PRIMARY KEY; -- 删除其中一条(比如temp_id为1的那条) DELETE FROM your_table WHERE temp_id = 1; -- 清理临时列 ALTER TABLE your_table DROP COLUMN temp_id;
SQL Server 操作方法
- 窗口函数法:
用ROW_NUMBER()给每条记录分配行号,再删掉行号为1的那条:WITH cte AS ( SELECT *, -- 这里ORDER BY (SELECT NULL)是随机分配行号,有可排序的列就换成它 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn FROM your_table ) DELETE FROM cte WHERE rn = 1; - 临时表中转法:
先把一条记录存到临时表,清空原表再导回去:-- 把一条记录存入临时表 SELECT TOP 1 * INTO #temp_table FROM your_table; -- 清空原表 TRUNCATE TABLE your_table; -- 把临时表的记录导回原表 INSERT INTO your_table SELECT * FROM #temp_table; -- 删除临时表 DROP TABLE #temp_table;
Oracle 操作方法
Oracle自带每行唯一的ROWID,用这个最方便:
- ROWID法:
DELETE FROM your_table WHERE ROWID IN ( SELECT ROWID FROM ( SELECT ROWID, ROW_NUMBER() OVER (ORDER BY NULL) AS rn FROM your_table ) WHERE rn = 1 ); - 临时列法(和MySQL类似):
-- 新增自增临时列 ALTER TABLE your_table ADD temp_id NUMBER GENERATED ALWAYS AS IDENTITY; -- 删除其中一条 DELETE FROM your_table WHERE temp_id = 1; -- 清理临时列 ALTER TABLE your_table DROP COLUMN temp_id;
重要提醒
- 操作前务必先备份数据,比如执行
SELECT * FROM your_table把记录导出保存,避免误操作。 - 处理完之后,建议给表加上主键或唯一约束,从根源上避免重复记录的产生。
内容的提问来源于stack exchange,提问作者Joe




