避免生成重复标签值的一种方法是使用 MyISAM 表来生成唯一的序列号。MyISAM 支持您需要的 AUTO_INCREMENT 行为。
请参阅 MySQL 参考3.6.9 中的“MyISAM 注释”部分。使用 AUTO_INCREMENT
对于这种方法,您将创建一个单独的 MyISAM 表;该表的目的是生成唯一的序列号:例如
CREATE TABLE foo
( prefix VARHCAR(1) NOT NULL
, num INT UNSIGNED AUTO_INCREMENT
, PRIMARY KEY (prefix, num)
) Engine=MyISAM
假设标签前缀是一个字符,余数是一个数字:
INSERT INTO foo (prefix, num)
SELECT SUBSTR(t.label,1,1) AS prefix
, MAX(SUBSTR(t.label,2,8) AS num
FROM mytable
GROUP BY SUBSTR(t.label,1,1)
获取一个新的序列号,在新表中插入一行,为 prefix 提供一个值,为 num 列提供一个 NULL,然后检索为 num 列插入的值:
INSERT INTO foo (prefix,num) VALUES ('W',NULL);
SELECT LAST_INSERT_ID();
您可以使用它来构造要用于label
原始表中的列的值。
请注意,只有 MyISAM 引擎具有您想要的行为(为每个前缀分别递增 AUTO_INCREMENT 序列。)您的原始表可以是任何引擎。
这种方法避免了竞态条件,但确实引入了并发瓶颈,这是由于在 MyISAM 表上为插入而采取的排他锁。
避免竞争条件的另一种方法是在表上获得排他锁,然后执行 SELECT MAX(),然后执行插入,然后释放锁。但是这种方法引入了更多的并发瓶颈,序列化对单个资源的访问。
如果您的问题是关于识别现有的重复label
值,那么此查询将为您提供具有“重复”标签的行。(这只是为每个重复的标签挑选一行。)
SELECT t.label
, MAX(t.id)
FROM mytable t
GROUP BY t.label
HAVING COUNT(1) > 1
要将标签更新为唯一,您需要为这些行生成一个新标签。
在一条 SQL 语句中完成这项工作有点棘手。我试图提出一个声明,但它被破坏了,我没有时间修复它。