具有多个NULL约束的SQL表

时间:2019-06-23 10:32:14

标签: mysql constraints

我正在使用MYSQL,并且具有设备表。每个设备都具有一个名为# domain example1.com RewriteCond %{HTTP_HOST} example1\.com [NC] RewriteCond %{HTTPS} off [OR] RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^ https://www.example1.com%{REQUEST_URI} [L,R=301] # domain example2.com RewriteCond %{HTTP_HOST} example2\.com [NC] RewriteCond %{HTTPS} off [OR] RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^ https://www.example2.com%{REQUEST_URI} [L,R=301] (不是pk)的ID和一个名为mac_address的列。

如果设备未激活,则其deleted_date等于时间戳,然后可以添加具有相同deleted_date的新设备。 如果该设备处于活动状态,则其mac_address等于NULL,因此添加具有相同deleted_date的新设备应该是不可行的。

我发现可能有两个设备在同一个mac_address下仍处于活动状态,这是错误的。经过一番研究,我发现无法将NULL与NULL进行比较,因为它不算作相同的值。

对于如何解决这个问题,我将不胜感激。

  • 两个具有相同mac_addressmac_address的设备为NULL: WRONG
  • 两个具有相同deleted_date的设备,一个mac_address为NULL,另一个具有值:确定
  • 两个具有相同deleted_datemac_address的设备都具有它们的值:确定

现在,这是表创建和约束的相关部分:

deleted_date

3 个答案:

答案 0 :(得分:2)

您不能仅对INSERT语句执行此操作,但是可以使用触发器。

drop trigger if exists t;
delimiter $$

create trigger t before insert on t
for each row
begin
        declare vcount int default 0;
        select ifnull(count(*),0) into vcount from t where mac_address = new.mac_address and delete_date is null; 
       if vcount <> 0 then
            SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'An error occurred';
        end if;
end $$
delimiter ;

请注意,您可能必须在UPDATE上执行类似的操作。

答案 1 :(得分:1)

我们将需要确定并解决以下问题:

  • 我们本来可能有什么问题
  • 如何处理插入
  • 如何处理更新

可能的问题

您可能有多个记录,它们具有相同的mac_addressnull delete_date。您需要确保每个具有mac_address null的{​​{1}}都有一条记录。如果您想对delete_date使用constraint,则可以将未删除记录的unique设置为在很遥远的将来的某个日期,并且会知道记录中有{{1 }}以后不会被删除。如果将来的日期是一个常数,那么可以解决您的问题,但是这种解决方案不是很好。我仍然会使用delete_date日期,但随后您需要采取其他措施。

在插入或更新之前触发

P.Salmon的答案描述了这种方法,我不会重复它,而是赞成他的答案。触发器的问题在于,当有更多记录要插入/更新并且触发器在早期引发错误时,将不会发生某些有效的插入或修改。

插入和更新问题

delete_date的问题在于新记录将nullinsert mac_address匹配的可能性。更新的问题是,更新的记录将导致重复的null与另一个具有delete_date mac_address的记录。您可以使用以下条件来执行insert selectnull

delete_date

处理旧记录

您可以在updatewhere not ((not (iot_devices.deleted_date is null)) and (iot_devices.mac_address = 'youvalue')) 上更新旧记录的delete_date作为触发器

''而不是null

您可以将delete_date的类型更改为insert,并将update设置为未删除的值。然后,您可以使用约束。但是,在这种情况下,通过varchar进行搜索将变得更加困难。

答案 2 :(得分:-1)

您是对的NULL无法与NULL比较

但您可以将“与”进行比较,因此

使用''空字符串,而不使用 NULL 作为默认值