Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL - Composite Unique Key with datetime

Tags:

mysql

I have a transaction table where several rows may be stored against three attributes (foo_id, bar_id), and the last attribute is deleted_at, the thought here is to ensure that I only have one active row at a time (deleted_at = '0000-00-00 00:00:00').

But I am getting the following error:

mysql> UPDATE epic_table SET deleted_at = NOW() WHERE (foo_id = '1' AND bar_id IN ('18'));
ERROR 1062 (23000): Duplicate entry '18-1-2015-08-08 16:35:46' for key 'epic_table_ibuk_1'

Here is the schema:

CREATE TABLE `epic_table` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `foo_id` bigint(20) unsigned NOT NULL,
  `bar_id` bigint(20) unsigned NOT NULL,
  `created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `deleted_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  UNIQUE KEY `epic_table_ibuk_1` (`foo_id`,`bar_id`,`deleted_at`),
  KEY `epic_table_ibfk_1` (`foo_id`),
  KEY `epic_table_ibfk_2` (`bar_id`),
  CONSTRAINT `epic_table_ibfk_1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`),
  CONSTRAINT `epic_table_ibfk_2` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8

The only thing that immediately stands out is that MySQL may not be considering the time portion of the datetime value, and therefore complaining about another row with 18-1-2015-08-08.

Any ideas how I can maintain the multiple row flexibility while being able to enforce that only one row is 'active' at any given time?

like image 849
Mike Purcell Avatar asked Aug 08 '15 17:08

Mike Purcell


People also ask

How to form a composite key to be unique in MySQL?

To form a composite key to be unique, you need to use ADD UNIQUE command. Following is the syntax − alter table yourTableName add unique yourUniqueName ( yourColumnName1,yourColumnName2,.......N); Let us first create a table. Following is the query − Now check the description of the table using DESC command. Following is the query −

Does every mysql table have a prime key?

Every table should have a PRIMARY KEY. In MySQL this implies two things: a UNIQUEness constraint, and an index. Any kind of index can be "composite" ("compound"), that is be composed of more than one column. It is rarely useful to have two UNIQUE keys in a single table. (Remember: PRIMARY counts as UNIQUE.

Is it possible to have two unique keys in a table?

In MySQL this implies two things: a UNIQUEness constraint, and an index. Any kind of index can be "composite" ("compound"), that is be composed of more than one column. It is rarely useful to have two UNIQUE keys in a single table.

Should I have unique (a) or un iQue (B) keys?

If you already have a unique key (a), it is unreasonable and unnecessary to have also have UNIQUE (a,b) or UNIQUE (b,a). On the other hand, it may be useful to have a non-unique INDEX (a,b) and/or INDEX (b,a).


1 Answers

Changing from a comment to an answer...

The statement:

UPDATE epic_table SET deleted_at = NOW() 
WHERE (foo_id = '1' AND bar_id IN ('18'));

attempts to set deleted_at for all rows with foo_id = 1 and bar_id = 18. Since foo_id, bar_id and deleted_at combination is marked as unique, such change ends up violating the unique constraint.

Only a slight change may be needed to the statement like so, knowing that only one record may have deleted_at = '0000-00-00 00:00:00':

UPDATE epic_table SET deleted_at = NOW() 
WHERE (foo_id = '1' AND bar_id IN ('18') and deleted_at = '0000-00-00 00:00:00');
like image 86
zedfoxus Avatar answered Oct 03 '22 20:10

zedfoxus