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

MariaDB双主键表删除首个主键重复行的技术求助

解决MariaDB中删除复合主键表中id重复行的问题

问题分析

你的表使用(id, name)作为复合主键,这种设计本身允许同一id对应不同name的行存在。之前用CTE执行DELETE无效,是因为MariaDB不支持直接从CTE删除原表数据——CTE仅作为临时查询结果,无法直接关联原表完成删除操作。

可行解决方案

方法1:通过ROW_NUMBER()子查询关联删除

这种方法能精准控制保留哪一行(通过ORDER BY指定优先级):

-- 先验证要删除的行(执行删除前务必先做这一步)
SELECT p1.*
FROM product_names p1
JOIN (
    SELECT id, name,
           ROW_NUMBER() OVER (PARTITION BY id ORDER BY name) AS rn
    FROM product_names
) p2 ON p1.id = p2.id AND p1.name = p2.name
WHERE p2.rn > 1;

-- 确认无误后执行删除
DELETE p1
FROM product_names p1
JOIN (
    SELECT id, name,
           ROW_NUMBER() OVER (PARTITION BY id ORDER BY name) AS rn
    FROM product_names
) p2 ON p1.id = p2.id AND p1.name = p2.name
WHERE p2.rn > 1;
  • 说明:PARTITION BY id按id分组,ORDER BY name决定每组内保留的行(示例中保留name排序最靠前的行,即name='a'的行)。如果需要按其他字段优先级保留,替换ORDER BY后的字段即可(比如smth或创建时间)。

方法2:通过聚合函数筛选保留行

如果只需要保留每个id对应的某一行(比如name最小/最大的行),可以用NOT IN结合聚合查询:

-- 先验证
SELECT *
FROM product_names
WHERE (id, name) NOT IN (
    SELECT id, MIN(name)
    FROM product_names
    GROUP BY id
);

-- 执行删除
DELETE FROM product_names
WHERE (id, name) NOT IN (
    SELECT id, MIN(name)
    FROM product_names
    GROUP BY id
);
  • 说明:MIN(name)会选择每个id中name最小的行,若要保留name最大的行,替换为MAX(name)即可。

后续优化建议

删除重复行后,建议调整表结构避免后续再出现id重复的情况:

-- 删除原复合主键
ALTER TABLE product_names DROP PRIMARY KEY;
-- 将id设为主键(确保id唯一)
ALTER TABLE product_names ADD PRIMARY KEY (id);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 20:05:36