我有这个表,col1 col2 col3,col1是主键,现在我想为col2和col3添加唯一约束,我使用alter table add constraint,但是表中似乎已经有重复的记录,所以我必须删除它们以使其工作,但是,如果我需要保留所有现有记录,我如何确保新添加的记录在 col2 和 col3 中是唯一约束?
2 回答
如果我理解正确,您想保留当前的重复项,但要确保不添加任何新的重复项,对吗?就我个人而言,我会遵循上面的评论,但我理解这是否不能满足您的业务需求。
不幸的是,约束不能满足您描述的需求。您可能希望控制插入数据的软件中的重复逻辑,而不是在表级别。例如,如果表中尚不存在 val3,则以下内容只会添加该行。说得通?
INSERT INTO MyTable (col1, col2, col3, col4)
VALUES (val1, val2, val3, val4) WHERE NOT col3 = val3;
或者您可以触发 INSTEAD OF 触发器。SQL 有一个特殊的临时“插入”表,您可以在输入值之前与它进行比较。所以您说,“插入这些值,但等等!仅当临时“插入”表中的行与 MyTable 中的现有行不匹配时才插入它们。”
CREATE TRIGGER no_duplicates_in_MyTable ON MyTable
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON
IF (NOT EXISTS (SELECT M.val3
FROM MyTable M, inserted I
WHERE M.val3 = I.val3))
INSERT INTO MyTable
SELECT val1, val2, val3, val4
FROM inserted
END
或者,您可以使用 AFTER INSERT 触发器在表级别处理逻辑,但这有点不稳定。在某些情况下,您可以删除现有的重复项。像这样的东西;
CREATE TRIGGER delete_duplicates_MyTable
AFTER INSERT ON MyTable
BEGIN
DELETE FROM MyTable
WHERE val3 NOT IN (SELECT MIN(val3)
FROM MyTable
WHERE val1 = new. val1)
AND val1 = new. val1;
END;
如果您有任何问题或这不符合您的业务需求,请告诉我。
编辑:@Rik 是正确的,这些是 INSERT 触发器,因此它们不适用于更新,允许任何人的代码将值更改为重复项。尝试更新触发器。您可以随意使用这些将 INSERT 更改为 UPDATE。
就我个人而言,我会同意其他人的评论。您应该真正修复数据,然后添加约束。
然而,仅仅为了它,一个可能的解决方案可能是使用 MERGE 引擎。基本上,您会将您现在拥有的数据保存在一个表中,并创建一个几乎相同的第二个表。唯一不同的是,这次索引是唯一的。
看这个例子:
CREATE TABLE t1 (
a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
message CHAR(20),
key whatever (message)
) ENGINE=MyISAM;
CREATE TABLE t2 (
a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
message CHAR(20),
unique key whatever (message)
) ENGINE=MyISAM;
INSERT INTO t1 (message) VALUES ('Testing'),('Testing'),('t1');
INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
CREATE TABLE total (
a INT NOT NULL AUTO_INCREMENT,
message CHAR(20), INDEX(a))
ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
select * from total;
/*Here you can see, that there are duplicate values*/
insert into total (message) values ('Testing');
/*but this results in a duplicate key error*/
insert into total (message) values ('it work\'s');
/*whereas this doesn't*/
在此处阅读有关 MERGE 引擎的更多信息。