0

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

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

我的问题与下表有关(如果我打算只使用 1 个表)。我将如何执行 1isMain=1perprod?当我尝试设置时,是否有任何索引设置会出错isMain=1image_id=2因为image=1已经是主图像?您不能将 unique_key 放在prod+isMain

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

2 回答 2

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 的行被归零

于 2012-10-22T15:42:56.357 回答
0

我了解到,答案非常简单,并且与 MySQL 如何索引 NULL 值有关。他们在这里谈论:

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

所以只要我的isMain字段允许强制执行一个值和 NULL(可能是一个 ENUM),我就准备好了。只有当 isMain 设置为不同的值而不是设置为 NULL 时,才会强制执行 unique_index。

更新后的表如下所示:

|image_id |prod|isMain
|---------|----|------
|0        |1   |null
|1        |1   |1
|2        |1   |null
|3        |2   |1
|4        |3   |null
|5        |3   |1
于 2012-10-22T15:42:48.343 回答