Preventing duplicates in an SQL query?
Is there an easy way when inserting a new record to make it fail if o开发者_开发问答ne 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.
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.
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. See MYSQL Create Trigger.
To raise an exception in the trigger, so that the insert fails, see TRIGGERs that cause INSERTs to fail? 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.
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 i.e. transposing the child_ID values between rows will fool any UNIQUE
constraint you care to put on the columns. 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 (i.e. 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
e.g.
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
);
精彩评论