简体   繁体   English

防止在SQL查询中重复?

[英]Preventing duplicates in an SQL query?

Is there an easy way when inserting a new record to make it fail if one of the fields is a duplicate of one of the other fields? 如果其中一个字段与其他字段之一重复,则插入新记录以使其失败时,是否有一种简便的方法?

I don´t want the field to be a primary key or anything like that... 我不希望该字段成为主键或类似的主键...

Set the column as unique . 将列设置为唯一

More on this 更多关于这个

http://php.about.com/od/mysqlcommands/g/add_unique.htm http://php.about.com/od/mysqlcommands/g/add_unique.htm

As has been said by hgulyan, if you want a table.col1 to be unique, add a unique constraint on the column. 正如hgulyan所说,如果您希望table.col1是唯一的,请在该列上添加唯一约束。

If what you mean is that you want the insert to fail if column table1.col1 = table1.col2, then you can implement this in a trigger. 如果您的意思是希望在列table1.col1 = table1.col2时插入操作失败,则可以在触发器中实现此操作。 See MYSQL Create Trigger . 请参见MYSQL创建触发器

To raise an exception in the trigger, so that the insert fails, see TRIGGERs that cause INSERTs to fail? 要在触发器中引发异常,以使插入失败,请参阅导致INSERT失败的TRIGGER? Possible? 可能?

Something like: 就像是:

CREATE TRIGGER Employee_beforeinsert before insert
ON Employee FOR EACH ROW
    BEGIN
    IF new.age = new.age2 THEN
        DECLARE dummy INT;

        SELECT 'Your meaningful error message goes here' INTO dummy 
        FROM Employee
        WHERE Employee.id=new.id
    END IF;
END;

The following is Standard SQL, rather than mySQL dialect, but mySQL is has a good level of compliance with the Standard and I trust you should be able to follow my point. 以下是标准SQL,而不是mySQL方言,但是mySQL与Standard的合规性很高,我相信您应该能够理解我的观点。

You didn't post your schema or sample data so I had to guess what your tables might look like: 您没有发布架构或示例数据,因此我不得不猜测您的表可能是什么样的:

CREATE TABLE Mothers
(
 mother_ID INTEGER NOT NULL UNIQUE
);

CREATE TABLE Children
(
 child_ID INTEGER NOT NULL UNIQUE
);

CREATE TABLE MothersOfTwins
(
 mother_ID INTEGER NOT NULL 
    UNIQUE REFERENCES Mothers (mother_ID), 
 twin_1_child_ID INTEGER 
    REFERENCES Children (child_ID), 
 twin_2_child_ID INTEGER 
    REFERENCES Children (child_ID), 
 CHECK (twin_1_child_ID <> twin_2_child_ID)
);

INSERT INTO Mothers (mother_ID) VALUES (101), (102), (103);

INSERT INTO Children (child_ID) VALUES (551), (552), (553), (554);

INSERT INTO MothersOfTwins (mother_ID, twin_1_child_ID, twin_2_child_ID) 
VALUES 
(101, 551, 552), 
(102, 552, 551);  -- duplicate

That last INSERT succeeds even though it should fail ie transposing the child_ID values between rows will fool any UNIQUE constraint you care to put on the columns. 最后一个INSERT成功,即使它失败了,即在行之间转换child_ID值也将使您想放在列上的所有UNIQUE约束都蒙混了。 I guess this is similar to the problem you are facing. 我想这与您面临的问题类似。

One solution to this problem is to create a base table which requires multiple rows to model siblings, using an 'occurrence' column with a constraint to ensure there cannot be more than two siblings (ie twins): 解决此问题的一种方法是创建一个基表,该基表需要使用多行来对同级进行建模,使用带有约束条件的“出现”列来确保不超过两个同级(即双胞胎):

DROP TABLE MothersOfTwins;

CREATE TABLE MothersOfTwinsBase
(
 mother_ID INTEGER NOT NULL
    REFERENCES Mothers (mother_ID), 
 twin_occurrence INTEGER NOT NULL
    CHECK (twin_occurrence BETWEEN 1 AND 2), 
 twin_child_ID INTEGER NOT NULL UNIQUE 
    REFERENCES Children (child_ID), 
 UNIQUE (mother_ID, twin_occurrence)
);

INSERT INTO MothersOfTwinsBase (mother_ID, twin_occurrence, twin_child_ID) 
VALUES 
(101, 1, 551), 
(101, 2, 552),
(102, 1, 553),
(103, 2, 554);

You can then recreate the data structure of your former base table using a VIEW eg 然后,您可以使用VIEW重新创建以前的基表的数据结构

CREATE VIEW MothersOfTwins
(
 mother_ID, 
 twin_1_child_ID, twin_2_child_ID
)
AS
SELECT M1.mother_ID, 
       M1.twin_child_ID AS twin_1_child_ID, 
       M2.twin_child_ID AS twin_2_child_ID
  FROM MothersOfTwinsBase AS M1 
       INNER JOIN MothersOfTwinsBase AS M2
          ON M1.mother_ID = M2.mother_ID
             AND M1.twin_occurrence = 1
             AND M2.twin_occurrence = 2
UNION ALL
SELECT M1.mother_ID, 
       M1.twin_child_ID AS twin_1_child_ID, 
       NULL AS twin_2_child_ID
  FROM MothersOfTwinsBase AS M1 
 WHERE NOT EXISTS (
                   SELECT *
                     FROM MothersOfTwinsBase AS M2
                          WHERE M1.mother_ID = M2.mother_ID
                                AND M2.twin_occurrence = 2
                  )
UNION ALL
SELECT M2.mother_ID, 
       NULL AS twin_1_child_ID, 
       M2.twin_child_ID AS twin_2_child_ID
  FROM MothersOfTwinsBase AS M2
 WHERE NOT EXISTS (
                   SELECT *
                     FROM MothersOfTwinsBase AS M1
                          WHERE M1.mother_ID = M2.mother_ID
                                AND M1.twin_occurrence = 1
                  );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM