patternsqlMinor
Unique combination key MySQL
Viewed 0 times
combinationuniquemysqlkey
Problem
Lets say I have a table with 3 fields:
What I want is a primary/unique key that is any combination of id1 and id2. For example if I have this record already in the database:
I should not be able to insert a record like:
Right now I have id1 and id2 as my composite primary key however I am able to insert the data above, is there anyway to prevent this on the database level?
- id1
- id2
- mapTypeId
What I want is a primary/unique key that is any combination of id1 and id2. For example if I have this record already in the database:
- 1, 2, 3
I should not be able to insert a record like:
- 2, 1, 3
Right now I have id1 and id2 as my composite primary key however I am able to insert the data above, is there anyway to prevent this on the database level?
Solution
Here is before trigger you can use to guarantee that id1 and id2 are inserted in min/max order
Here is some Sample Data:
Here it is the Sample Data Loaded
Watch What Happens When I Insert the Rows:
Now, no matter what order id1 and id2 are entered, id1 will always be less than or equal to id2
This may not be contextually what you want because id1 and id2 are unique identifiers.
DELIMITER $
CREATE TRIGGER mytable_bi BEFORE INSERT ON mytable
FOR EACH ROW
BEGIN
DECLARE sum INT;
SET sum = NEW.id1 + NEW.id2;
SET NEW.id1 = (NEW.id1 + NEW.id2 - ABS(NEW.id1 - NEW.id2)) / 2;
SET NEW.id2 = sum - NEW.id1;
END $
DELIMITER ;Here is some Sample Data:
DROP DATABASE IF EXISTS ryanzec;
CREATE DATABASE ryanzec;
USE ryanzec
CREATE TABLE mytable
(
id1 INT NOT NULL,
id2 INT NOT NULL,
mapTypeId INT NOT NULL,
primary key (id1,id2)
);
DELIMITER $
CREATE TRIGGER mytable_bi BEFORE INSERT ON mytable
FOR EACH ROW
BEGIN
DECLARE sum INT;
SET sum = NEW.id1 + NEW.id2;
SET NEW.id1 = (NEW.id1 + NEW.id2 - ABS(NEW.id1 - NEW.id2)) / 2;
SET NEW.id2 = sum - NEW.id1;
END $
DELIMITER ;
INSERT INTO mytable VALUES (1,2,3);
INSERT INTO mytable VALUES (2,1,3);
INSERT INTO mytable VALUES (5,4,6);
INSERT INTO mytable VALUES (4,5,6);
SELECT * FROM mytable;Here it is the Sample Data Loaded
mysql> DROP DATABASE IF EXISTS ryanzec;
Query OK, 1 row affected (0.03 sec)
mysql> CREATE DATABASE ryanzec;
Query OK, 1 row affected (0.00 sec)
mysql> USE ryanzec
Database changed
mysql> CREATE TABLE mytable
-> (
-> id1 INT NOT NULL,
-> id2 INT NOT NULL,
-> mapTypeId INT NOT NULL,
-> primary key (id1,id2)
-> );
Query OK, 0 rows affected (0.10 sec)
mysql> DELIMITER $
mysql> CREATE TRIGGER mytable_bi BEFORE INSERT ON mytable
-> FOR EACH ROW
-> BEGIN
-> DECLARE sum INT;
-> SET sum = NEW.id1 + NEW.id2;
-> SET NEW.id1 = (NEW.id1 + NEW.id2 - ABS(NEW.id1 - NEW.id2)) / 2;
-> SET NEW.id2 = sum - NEW.id1;
-> END $
Query OK, 0 rows affected (0.10 sec)
mysql> DELIMITER ;Watch What Happens When I Insert the Rows:
mysql> INSERT INTO mytable VALUES (1,2,3);
Query OK, 1 row affected (0.06 sec)
mysql> INSERT INTO mytable VALUES (2,1,3);
ERROR 1062 (23000): Duplicate entry '1-2' for key 'PRIMARY'
mysql> INSERT INTO mytable VALUES (5,4,6);
Query OK, 1 row affected (0.07 sec)
mysql> INSERT INTO mytable VALUES (4,5,6);
ERROR 1062 (23000): Duplicate entry '4-5' for key 'PRIMARY'
mysql> SELECT * FROM mytable;
+-----+-----+-----------+
| id1 | id2 | mapTypeId |
+-----+-----+-----------+
| 1 | 2 | 3 |
| 4 | 5 | 6 |
+-----+-----+-----------+
2 rows in set (0.00 sec)
mysql>Now, no matter what order id1 and id2 are entered, id1 will always be less than or equal to id2
This may not be contextually what you want because id1 and id2 are unique identifiers.
Code Snippets
DELIMITER $$
CREATE TRIGGER mytable_bi BEFORE INSERT ON mytable
FOR EACH ROW
BEGIN
DECLARE sum INT;
SET sum = NEW.id1 + NEW.id2;
SET NEW.id1 = (NEW.id1 + NEW.id2 - ABS(NEW.id1 - NEW.id2)) / 2;
SET NEW.id2 = sum - NEW.id1;
END $$
DELIMITER ;DROP DATABASE IF EXISTS ryanzec;
CREATE DATABASE ryanzec;
USE ryanzec
CREATE TABLE mytable
(
id1 INT NOT NULL,
id2 INT NOT NULL,
mapTypeId INT NOT NULL,
primary key (id1,id2)
);
DELIMITER $$
CREATE TRIGGER mytable_bi BEFORE INSERT ON mytable
FOR EACH ROW
BEGIN
DECLARE sum INT;
SET sum = NEW.id1 + NEW.id2;
SET NEW.id1 = (NEW.id1 + NEW.id2 - ABS(NEW.id1 - NEW.id2)) / 2;
SET NEW.id2 = sum - NEW.id1;
END $$
DELIMITER ;
INSERT INTO mytable VALUES (1,2,3);
INSERT INTO mytable VALUES (2,1,3);
INSERT INTO mytable VALUES (5,4,6);
INSERT INTO mytable VALUES (4,5,6);
SELECT * FROM mytable;mysql> DROP DATABASE IF EXISTS ryanzec;
Query OK, 1 row affected (0.03 sec)
mysql> CREATE DATABASE ryanzec;
Query OK, 1 row affected (0.00 sec)
mysql> USE ryanzec
Database changed
mysql> CREATE TABLE mytable
-> (
-> id1 INT NOT NULL,
-> id2 INT NOT NULL,
-> mapTypeId INT NOT NULL,
-> primary key (id1,id2)
-> );
Query OK, 0 rows affected (0.10 sec)
mysql> DELIMITER $$
mysql> CREATE TRIGGER mytable_bi BEFORE INSERT ON mytable
-> FOR EACH ROW
-> BEGIN
-> DECLARE sum INT;
-> SET sum = NEW.id1 + NEW.id2;
-> SET NEW.id1 = (NEW.id1 + NEW.id2 - ABS(NEW.id1 - NEW.id2)) / 2;
-> SET NEW.id2 = sum - NEW.id1;
-> END $$
Query OK, 0 rows affected (0.10 sec)
mysql> DELIMITER ;mysql> INSERT INTO mytable VALUES (1,2,3);
Query OK, 1 row affected (0.06 sec)
mysql> INSERT INTO mytable VALUES (2,1,3);
ERROR 1062 (23000): Duplicate entry '1-2' for key 'PRIMARY'
mysql> INSERT INTO mytable VALUES (5,4,6);
Query OK, 1 row affected (0.07 sec)
mysql> INSERT INTO mytable VALUES (4,5,6);
ERROR 1062 (23000): Duplicate entry '4-5' for key 'PRIMARY'
mysql> SELECT * FROM mytable;
+-----+-----+-----------+
| id1 | id2 | mapTypeId |
+-----+-----+-----------+
| 1 | 2 | 3 |
| 4 | 5 | 6 |
+-----+-----+-----------+
2 rows in set (0.00 sec)
mysql>Context
StackExchange Database Administrators Q#22085, answer score: 3
Revisions (0)
No revisions yet.