Here is before trigger you can use to guarantee that id1 and id2 are inserted in min/max order
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.
From your question, I'm not completely sure if you're inserting multiple values per query, but you definitely should be. With MyISAM as the engine, there should not be a performance difference between the index being UNIQUE
or PRIMARY
; MyISAM doesn't treat them differently in this case. If you were using InnoDB, however, there would be a difference since it stores the data in primary key order. If you don't need the id
column, removing it and making domain
the primary key would help performance.
Changing the collation should help since ascii
is much simpler than utf8
, but you might want to use ascii_general_ci
instead of ascii_bin
since domain names are case-insensitive.
One other way to do the queries would be to get the number of rows, INSERT DELAYED
, flush the delayed writes, and then get the new row count. The difference in the counts would be the same as the affected rows. However, I don't think this would be significantly faster, but it would make the process more complex.
Best Answer
You may want to try creating a trigger that will check for the presence of (col1,col2) existing as (col2,col1)
Here is an example:
The trigger is designed to break on purpose when FOUND_COUNT is 1.
Here is the sample executed:
Give it a Try !!!
CAVEAT This does not work on bulk INSERTs. Only when inserting one row at a time.
I have used this technique and suggested it in other DBA StackExchange Questions
UPDATE 2012-02-29 11:46 EDT
I tried to INSERT the same four rows again.
Here is what I get
This trigger approach work well despite the quirky message.