说我有下表
item_a_id, item_b_id, value
其中item_a_id和item_b_id是复合主键。在我的例子中,a,b和b,a是等价的。因此,我想确保item_a_id< item_b_id。显然,应用程序逻辑会强制执行此操作,但有没有办法确保数据库也这样做?
答案 0 :(得分:3)
在相当当前版本的MySql中,您可以使用触发器emulate a check constraint来产生所需的行为。
答案 1 :(得分:2)
嗯,在您的情况下,您可以使用触发器在插入/更新之前检查值并交换它以确保item_a_id
始终小于item_b_id
。
假设表名为item_links
,您可以尝试:
DELIMITER |
CREATE TRIGGER ensure_a_b_before_insert BEFORE INSERT ON item_links
FOR EACH ROW
BEGIN
IF NEW.item_a_id > NEW.item_b_id THEN
SET @tmp = NEW.item_b_id;
SET NEW.item_b_id = NEW.item_a_id;
SET NEW.item_a_id = @tmp;
END IF;
END;
|
CREATE TRIGGER ensure_a_b_before_update BEFORE UPDATE ON item_links
FOR EACH ROW
BEGIN
IF NEW.item_a_id > NEW.item_b_id THEN
SET @tmp = NEW.item_b_id;
SET NEW.item_b_id = NEW.item_a_id;
SET NEW.item_a_id = @tmp;
END IF;
END;
|
DELIMITER ;
这是我测试插入时得到的结果:
mysql> INSERT INTO `item_links` (`item_a_id`, `item_b_id`, `value`)
-> VALUES ('1', '2', 'a')
-> , ('3', '2', 'b')
-> , ('4', '1', 'c');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM `item_links`;
+-----------+-----------+-------+
| item_a_id | item_b_id | value |
+-----------+-----------+-------+
| 1 | 2 | a |
| 2 | 3 | b |
| 1 | 4 | c |
+-----------+-----------+-------+
3 rows in set (0.00 sec)
更新也有效:
mysql> UPDATE `item_links`
-> SET `item_a_id` = 100, `item_b_id` = 20
-> WHERE `item_a_id` = 1 AND `item_b_id` = 2;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM `item_links`;
+-----------+-----------+-------+
| item_a_id | item_b_id | value |
+-----------+-----------+-------+
| 20 | 100 | a |
| 2 | 3 | b |
| 1 | 4 | c |
+-----------+-----------+-------+
3 rows in set (0.00 sec)