我今天偶然发现了一个棘手的问题,我想限制某个字段值的出现次数,这是我的表格:
CREATE TABLE `test_table` (
`id` varchar(40) COLLATE utf8_bin NOT NULL,
`create_time` datetime NOT NULL DEFAULT '2010-01-01 00:00:00',
`user_id` varchar(40) COLLATE utf8_bin NOT NULL,
`device_id` varchar(40) COLLATE utf8_bin NOT NULL,
`is_owner` boolean NOT NULL,
`user_nickname` varchar(45) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `un_device` (`device_id`,`is_owner`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
例如,我们有两个用户Bob
和Tom
,一个设备Echo
,user_id
,device_id
和{{1}之间的关系是:
独特的约束在我的案例中没有帮助,请帮助。
答案 0 :(得分:1)
解决方案可能是使用mysql触发器而不是约束。 Cou可以将触发器绑定到某些事件,并阻止或修改发生的操作。一般而言,如果要对具有复杂多重性的数据进行建模,则约束不会对您有所帮助。以下是如何为您的问题创建MYSQL触发器的示例(未经测试):
CREATE TRIGGER my_trigger BEFORE INSERT ON test_table
FOR EACH ROW
BEGIN
IF NEW.is_owner = TRUE AND EXISTS (SELECT * FROM test_table WHERE device_id = NEW.device_id AND is_owner = TRUE) THEN
SIGNAL sqlstate '99999'
SET message_text = "Can't insert because an other owner exists for that device";
END IF;
END$$
在此示例中,当有人尝试创建具有所有权且具有相同设备ID的第二个条目时,将创建SQL错误。您可以查看manual以获取更多信息。
答案 1 :(得分:1)
如果您使用null
代替false
来表明用户不是所有者,那么您可以使用唯一索引来提供此限制,因为in MySQL unique indexes allow multiple null values。显然,您需要使is_owner
字段为空,才能使其正常工作。
否则,此控件最好放在应用程序层中,而不是数据库中。在数据库中,您可以使用触发器来检查此情况,并防止raising an sql error设置额外的所有者记录。
答案 2 :(得分:-1)
您应该在device_id和user_id上使用约束来获取用户和设备(所有者与否)之间的唯一关系。使用这种方案,你不能拥有一个独特的约束条件,每个设备只有一个所有者" (或者至少我看不到一个)。