当FieldX = 1时,多个字段上的Mysql唯一索引

时间:2012-10-22 15:00:22

标签: mysql

场景:多个产品图片,一个主图片。

目前,我有2个表来管理它。一个用于存储产品图像,另一个用于存储mainProductImageIds。在存储mainProductImageIds列表的表格中,我在prodid + isMain上有一个唯一索引,以强制执行每个产品ID一个主图像

我的问题 与下表有关(如果我打算只使用1个表)。如何按isMain=1强制执行1 prod?当我尝试将isMain=1设置为image_id=2时,是否有任何索引设置会出错,因为image=1已经是主要图片了?您无法在prod + isMain上添加unique_key。

|image_id |prod|isMain
|---------|----|------
|0        |1   |0
|1        |1   |1
|2        |1   |0
|3        |2   |1
|4        |3   |0
|5        |3   |1

2 个答案:

答案 0 :(得分:1)

您可以尝试使用TRIGGER执行此操作。

CREATE TRIGGER check_unique BEFORE UPDATE ON `images`
    FOR EACH ROW
        SET NEW.isMain = IF(NEW.isMain = 0, 0,
            CASE WHEN ( SELECT MAX(isMain) FROM images AS q WHERE q.prod = NEW.prod ) = 1
            THEN NULL ELSE NEW.isMain END);

或更快(特别是如果已编入索引)

CREATE TRIGGER check_unique BEFORE UPDATE ON `images`
    FOR EACH ROW
        SET NEW.isMain = IF(NEW.isMain = 0, 0,
           IF (EXISTS ( SELECT * FROM images AS q WHERE q.prod = NEW.prod AND q.isMain = 1), NULL, 1));

这将允许始终将isMain设置为0;如果你想把它设置为1,那么它将检查isMain为1的同一产品没有其他行。

实施例

在下面的示例中,我无法将isMain = 1设置为prod=3,直到我在另一张isMain=0的图片上设置isMain = 1

CREATE TABLE images (
   image_id integer not null primary key auto_increment, 
   prod integer not null,     isMain integer not null );

INSERT INTO images VALUES (1, 1, 0), (2, 1, 1), (3, 2, 0), (4, 2, 1);

select * from images;
+----------+------+--------+
| image_id | prod | isMain |
+----------+------+--------+
|        1 |    1 |      0 |
|        2 |    1 |      1 |
|        3 |    2 |      0 |
|        4 |    2 |      1 |
+----------+------+--------+

CREATE TRIGGER check_unique BEFORE UPDATE
    ON `images` FOR EACH ROW
       SET NEW.isMain = IF(NEW.isMain = 0, 0, IF (EXISTS ( SELECT * FROM images AS q WHERE q.prod = NEW.prod AND q.isMain = 1), NULL, 1));

UPDATE images SET isMain = 1 WHERE image_id = 3;
ERROR 1048 (23000): Column 'isMain' cannot be null

UPDATE images SET isMain = 0 WHERE image_id = 4;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

UPDATE images SET isMain = 1 WHERE image_id = 3;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

您可以扩展此方法,以便始终可以将任何行的isMain设置为1 ,但该产品之前的isMain行将归零

答案 1 :(得分:0)

我知道,答案非常简单,与MySQL索引NULL值的方式有关。 Over Here他们谈论:

  

对于所有引擎,UNIQUE索引允许多个NULL值   可以包含NULL的列。

所以只要我的isMain字段允许强制执行一个值和NULL(可能是一个ENUM),我就全部设置好了。 unique_index仅在isMain设置为不同值时强制执行,而不是在设置为NULL时强制执行。

更新的表格如下所示:

|image_id |prod|isMain
|---------|----|------
|0        |1   |null
|1        |1   |1
|2        |1   |null
|3        |2   |1
|4        |3   |null
|5        |3   |1