我有这个表,col1 col2 col3,col1是主键,现在我想为col2和col3添加唯一约束,我使用了alter table add constraint,但似乎表中已经有重复的记录,所以我必须删除它们以使其工作,但是,如果我需要保留所有现有记录,我如何确保新添加的记录是col2和col3中的唯一约束?
答案 0 :(得分:1)
如果我理解正确,您希望保留当前的重复项,但是您要确保不添加任何新的副本,对吧?我个人会按照上面的评论,但我知道如果这不符合您的业务需求。
不幸的是,当您描述约束时,约束不符合您的需求。您可能希望控制插入数据的软件中的重复逻辑,而不是表级。 例如,如果表中不存在val3,则以下内容仅添加行。合理?
INSERT INTO MyTable (col1, col2, col3, col4)
VALUES (val1, val2, val3, val4) WHERE NOT col3 = val3;
或者您可以触发INSTEAD OF触发器。 SQL有一个特殊的临时'插入'表,您可以在值进入之前对其进行比较。所以你说,“插入这些值,但等等!只有在temp'insert'表中的行与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触发器,因此它们不适用于更新,允许任何人的代码将值更改为重复。尝试UPDATE触发器。您可以将这些不断变化的INSERT改为更新。
答案 1 :(得分:0)
就个人而言,我会赞同对方的评论。你应该真正修复数据,然后添加约束。
然而,仅仅为了它,一个可能的解决方案可能是使用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引擎here。