でこれを試してみることができます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であった行はゼロになります。