2017-05-10 31 views
0

我遇到一个棘手的问题,我想限制一个字段的一些值的出现次数,这是我的表:MySQL限制MySQL字段的值(允许一个特定值和多个其他值)?今天

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; 

例如,我们有两个用户BobTom,和一个装置Echo,其中user_iddevice_idis_owner的关系是:

  1. 一个设备仅可具有一个所有者,这意味着只有一对(设备:回声,is_owner:真)是允许的。
  2. 设备可以有多个用户,这就是说允许多个外观(设备:Echo,is_owner:false)。

唯一的约束在我的情况不会有帮助,请帮助。

+0

你有错误的数据格式。你应该有一个表,每个设备一行,这应该有所有者。你应该有一个单独的表,每个设备和用户一行。 –

+0

您可以在应用程序逻辑强制执行此,或在查询本身 – Strawberry

+0

@Gordon Linoff它需要大量的工作要做,我们的应用程序目前的结构并不稳定,我们一直在试图躲避任何重大变化这将引入更多* bug *。 –

回答

1

如果您使用null而不是false来指示用户不是所有者,那么您可以使用唯一索引来提供此限制,因为in MySQL unique indexes allow multiple null values。显然,您需要使is_owner字段为空才能使用。

否则,此控件最好放置在应用程序层中,而不是数据库中。在数据库中,您可以使用触发器来检查此情况并防止由raising an sql error设置额外的所有者记录。

+0

听起来像一个可行的解决方案,我会尝试。 –

-1

您应该在device_id和user_id上对用户和设备(所有者与否)之间的唯一关系使用约束。有了这个方案,你不能有一个“每个设备只有一个所有者”的独特约束(或者至少我不能看到一个)。

+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$$ 

在这个例子中,当有人试图创建拥有第二项中的SQL错误将被创建并使用相同的设备ID 。你可以看看manual了解更多信息。

+0

在分布式场景中,如果两个事务试图同时写入相同的数据,触发器可能无法保证这些限制。 –

+0

我想道歉,我应该提到有一个类似的触发器,很像你的,但是当我的同事在将它应用到DBMS后尝试插入数十个数据时,由于某种未知的原因,它的有效性没有被观察到,它随机地抱怨即使数据库中不存在要插入的数据,更重要的是我们不能完全测试这个脚本,所以很难避免错误。 –

+0

你正在使用MySQL交易吗?您可能无法正确地在数据库中插入数据。如果你在多个表中插入数据(我在你的例子中假设),你应该将所有插入操作打包到一个事务中,并一次性提交。有关交易的更多信息,请参阅https://dev.mysql.com/doc/refman/5.7/en/commit.html。 – michip96

相关问题