Mysql 限制表中无主键删除的行数

Mysql 限制表中无主键删除的行数,mysql,sql,Mysql,Sql,我在一个系统上工作,由于某种原因,有人创建了一个“categories”表,但没有PK'ing该类别的ID。我刚刚发现,现在该表有一个所有行的副本,并导致我的一些查询出现问题 我的问题是:有没有一种方法可以删除重复的行,将“原始”保留在表中,而不依赖于索引 以下是从类别中选择*: +-----------+-------------+ | categoria | descripcion | +-----------+-------------+ | 1 | Int.Cons.

我在一个系统上工作,由于某种原因,有人创建了一个“categories”表,但没有PK'ing该类别的ID。我刚刚发现,现在该表有一个所有行的副本,并导致我的一些查询出现问题

我的问题是:有没有一种方法可以删除重复的行,将“原始”保留在表中,而不依赖于索引

以下是
从类别中选择*

+-----------+-------------+
| categoria | descripcion |
+-----------+-------------+
|         1 | Int.Cons.   |
|         2 | Delegado    |
|         3 | Personal    |
|         4 | Comun       |
|         5 | Proveedor   |
|         6 | Menor/Inc   |
|        11 | N/Categoria |
|         1 | Int.Cons.   |
|         2 | Delegado    |
|         3 | Personal    |
|         4 | Comun       |
|         5 | Proveedor   |
|         6 | Menor/Inc   |
|        11 | N/Categoria |
+-----------+-------------+

表上没有定义索引。

在您给出的示例中,您可以非常轻松地执行此操作:

 CREATE TABLE xyz AS SELECT DISTINCT FROM categories;
 DROP TABLE categories;
 ALTER TABLE xyz RENAME categories;
 CREATE UNIQUE INDEX idx_nn_c_1 ON categories(id);

(在运行之前检查SQL,否则您将在
DROP
行中丢失一个表)

在您给出的示例中,您可以非常轻松地执行此操作:

 CREATE TABLE xyz AS SELECT DISTINCT FROM categories;
 DROP TABLE categories;
 ALTER TABLE xyz RENAME categories;
 CREATE UNIQUE INDEX idx_nn_c_1 ON categories(id);
(在运行之前检查SQL,否则您将在
下拉
行中丢失一个表)

测试此操作

 delete a from yourtable a1 , yourtable a2 where a1.categoria=a2.categoria
测试这个

 delete a from yourtable a1 , yourtable a2 where a1.categoria=a2.categoria

您可以通过几种方式删除记录。我可能会建议使用临时表,然后正确地重新填充该表:

create temporary table temp_categories as 
    select c.id, c.descripcion
    from categories c
    group by c.id;

truncate table categories;

insert into categories(id, descripcion)
    select id, descripcion
    from temp_categories;


alter table add constraint primary key (id);
alter table add constraint unq_categories_descripcion unique (descripcion);

您可以通过几种方式删除记录。我可能会建议使用临时表,然后正确地重新填充该表:

create temporary table temp_categories as 
    select c.id, c.descripcion
    from categories c
    group by c.id;

truncate table categories;

insert into categories(id, descripcion)
    select id, descripcion
    from temp_categories;


alter table add constraint primary key (id);
alter table add constraint unq_categories_descripcion unique (descripcion);

如果/因为创建一个新表不是一个选项,您可以运行类似这样的操作;但您需要重复运行它,直到所有重复项都消失为止

DELETE FROM categories 
WHERE (categoria, descripcion) IN (
   SELECT categoria, descripcion 
   FROM categories 
   GROUP BY categoria, descripcion 
   HAVING COUNT(*) > 1
)
LIMIT 1
;

编辑:实际上,这应该具有临时表解决方案的优点,而不存在风险(因为真正的临时表是基于会话/连接的,如果连接失败,您将丢失数据)


显然,“NEWCOPY--”可以/应该替换为您知道的表中不存在的前缀。

如果/因为创建新表不是一个选项,您可以运行类似的操作;但您需要重复运行它,直到所有重复项都消失为止

DELETE FROM categories 
WHERE (categoria, descripcion) IN (
   SELECT categoria, descripcion 
   FROM categories 
   GROUP BY categoria, descripcion 
   HAVING COUNT(*) > 1
)
LIMIT 1
;

编辑:实际上,这应该具有临时表解决方案的优点,而不存在风险(因为真正的临时表是基于会话/连接的,如果连接失败,您将丢失数据)


显然,“NEWCOPY---”可以/应该替换为一个前缀,您知道该前缀在表中不存在。

我认为MySQL不支持with子句:oops对不起,我认为它在MSSQL中不支持with子句:oops对不起,我认为它在MSSQL中可以工作,但我在db中没有CREATE table权限。不知怎么的,它可以与临时表一起工作吗?您可以将数据转储到平面文件中,截断类别表并重新加载数据。这可以工作,但我在db中没有创建表的权限。不知怎么的,它能与临时表一起工作吗?你也可以将数据转储到一个平面文件中,截断类别表并重新加载数据!我只想补充一点,由于缺乏特权,我不得不创建一个临时表(创建临时表temp_categories),但一切都正常。谢谢工作得很有魅力!我只想补充一点,由于缺乏特权,我不得不创建一个临时表(创建临时表temp_categories),但一切都正常。谢谢我最终选择了临时表解决方案,但如果有人也缺乏临时表的创建权限,这可能是一个很好的选择。@Sebastianb请参阅编辑以获得另一种选择(比临时表更安全)。我最终选择了临时表解决方案,但如果有人也缺乏创建临时表的权限,这可能是一个很好的选择。@Sebastianb请参阅编辑以了解另一种选择(比临时表更安全)。