MySQL 将复合主键降级为更具限制性

MySQL Downgrading Composite Primary Key to be more restrictive

我有以下 table 用于跟踪正在观看支持票的用户

CREATE TABLE IF NOT EXISTS crm_ticketwatcher (
  ticketid int(10) unsigned NOT NULL DEFAULT '0',
  employeeid int(10) unsigned NOT NULL DEFAULT '0',
  contactid int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (ticketid,employeeid,contactid)
) ENGINE=MyISAM;

我想要一个从主键中删除 contactid 的降级脚本。

table内容有点像这样

ticketid|employeeid|contactid
--------|----------|---------
5       |5         |0
5       |8         |0
5       |0         |2
5       |0         |3

当我 运行 我的(不成功的)降级脚本时,

ALTER TABLE crm_ticketwatcher DROP PRIMARY KEY, ADD PRIMARY KEY (ticketid, employeeid);

我收到以下错误:

ERROR 1062 (23000) at line 1: Duplicate entry '306-0' for key 'PRIMARY'

因为现在有 2 行设置了主键 (5, 0)

从 table 中删除其他行并保存最后出现的行的最佳方法是什么?

我们使用的是 MySQL 5.7.13,因此无法使用 IGNORE 关键字。

谢谢。

ALTER TABLE Syntax 中所述:

IGNORE is a MySQL extension to standard SQL. It controls how ALTER TABLE works if there are duplicates on unique keys in the new table or if warnings occur when strict mode is enabled. If IGNORE is not specified, the copy is aborted and rolled back if duplicate-key errors occur. If IGNORE is specified, only one row is used of rows with duplicates on a unique key. The other conflicting rows are deleted. Incorrect values are truncated to the closest matching acceptable value.

因此,您可以这样做:

ALTER IGNORE TABLE crm_ticketwatcher
  DROP PRIMARY KEY,
  ADD PRIMARY KEY (ticketid, employeeid);

但是请注意,保留 "duplicate" 行中的哪一行将是不确定的。

如果您想要更确定的结果,或者正在使用 MySQL v5.7.4 及更高版本(IGNORE 已从中删除),您可以先使用多个执行自连接-table DELETE 语法:

DELETE c1
FROM   crm_ticketwatcher c1
  JOIN crm_ticketwatcher c2 USING (ticketid, employeeid)
WHERE  c1.contactid < c2.contactid -- or whatever logic you prefer