SQL (MySQL): 强制一行两列不同值的最佳方式?
SQL (MySQL): Best way to force different values two columns of a row?
给出以下table:
CREATE TABLE `tbl_termsynonyms` (
`ts_term1Id` int(10) unsigned NOT NULL,
`ts_term2Id` int(10) unsigned NOT NULL,
PRIMARY KEY (`ts_term1Id`,`ts_term2Id`),
KEY `fk_tbl_termSynonyms_tbl_term_t_id2` (`ts_term2Id`),
CONSTRAINT `fk_tbl_termSynonyms_tbl_term_t_id1` FOREIGN KEY (`ts_term1Id`) REFERENCES `tbl_term` (`t_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_tbl_termSynonyms_tbl_term_t_id2` FOREIGN KEY (`ts_term2Id`) REFERENCES `tbl_term` (`t_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
如您所见,此 table 用于在 tbl_term table.
中引用同义词
示例:table tbl_term 包含单词 "fun" 和 "joke",id 为 34 和 71,这些 ID 一起保存为一行。
现在我想阻止术语引用自身的行,例如:
71 - 71
31 - 31
是否有(SQL 方法)可以轻松实现此目的?
在 SQL 中有一个简单的方法可以做到这一点:
alter table tbl_termsynonyms add constraint chk_ts_term1Id_ts_term2Id check (ts_term1Id <> ts_term2Id);
不幸的是,MySQL 忽略了检查约束,所以这在 MySQL 中不起作用。
唉,你唯一的选择就是使用触发器。
据推测,您的数据中可以有循环 -- 所以 3 是 4 的同义词,而 4 是 3 的同义词。如果是这样的话,我看不到将术语作为同义词的真正损害他们自己。
当你想查询 table:
时,你可以将它们过滤掉
create view vw_termsynonyms as
select ts.*
from tbl_termsynonyms ts
where ts_term1Id <> ts_term2Id;
您可以要求 ts_term1Id 必须小于 ts_term2Id。 MySQL 没有 CHECK 约束,因此您必须在触发器中执行。
CREATE TRIGGER MyTrigger BEFORE INSERT ON tbl_termsynonyms
FOR EACH ROW
SET NEW.ts_term1Id = LEAST(NEW.ts_term1Id, NEW.ts_term2Id),
NEW.ts_term2Id = GREATEST(NEW.ts_term1Id, NEW.ts_term2Id);
我还没有测试过,所以我不完全确定你可以在一个 SET 语句中完成它。您可能需要局部变量。
给出以下table:
CREATE TABLE `tbl_termsynonyms` (
`ts_term1Id` int(10) unsigned NOT NULL,
`ts_term2Id` int(10) unsigned NOT NULL,
PRIMARY KEY (`ts_term1Id`,`ts_term2Id`),
KEY `fk_tbl_termSynonyms_tbl_term_t_id2` (`ts_term2Id`),
CONSTRAINT `fk_tbl_termSynonyms_tbl_term_t_id1` FOREIGN KEY (`ts_term1Id`) REFERENCES `tbl_term` (`t_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_tbl_termSynonyms_tbl_term_t_id2` FOREIGN KEY (`ts_term2Id`) REFERENCES `tbl_term` (`t_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
如您所见,此 table 用于在 tbl_term table.
中引用同义词示例:table tbl_term 包含单词 "fun" 和 "joke",id 为 34 和 71,这些 ID 一起保存为一行。
现在我想阻止术语引用自身的行,例如:
71 - 71
31 - 31
是否有(SQL 方法)可以轻松实现此目的?
在 SQL 中有一个简单的方法可以做到这一点:
alter table tbl_termsynonyms add constraint chk_ts_term1Id_ts_term2Id check (ts_term1Id <> ts_term2Id);
不幸的是,MySQL 忽略了检查约束,所以这在 MySQL 中不起作用。
唉,你唯一的选择就是使用触发器。
据推测,您的数据中可以有循环 -- 所以 3 是 4 的同义词,而 4 是 3 的同义词。如果是这样的话,我看不到将术语作为同义词的真正损害他们自己。
当你想查询 table:
时,你可以将它们过滤掉create view vw_termsynonyms as
select ts.*
from tbl_termsynonyms ts
where ts_term1Id <> ts_term2Id;
您可以要求 ts_term1Id 必须小于 ts_term2Id。 MySQL 没有 CHECK 约束,因此您必须在触发器中执行。
CREATE TRIGGER MyTrigger BEFORE INSERT ON tbl_termsynonyms
FOR EACH ROW
SET NEW.ts_term1Id = LEAST(NEW.ts_term1Id, NEW.ts_term2Id),
NEW.ts_term2Id = GREATEST(NEW.ts_term1Id, NEW.ts_term2Id);
我还没有测试过,所以我不完全确定你可以在一个 SET 语句中完成它。您可能需要局部变量。