0

シナリオ:複数の商品画像、1つのメイン画像。

現在、これを管理するための2つのテーブルがあります。1つは商品画像を保存するためのもので、もう1つはを保存するためのテーブルですmainProductImageIds。のリストを格納するテーブルには、製品IDごとに1つのメインイメージを適用するための+mainProductImageIdsの一意のインデックスがあります。prodidisMain

私の質問は以下の表に関連しています(1つの表のみを使用する場合)。isMain=11つにつき1つを強制するにはどうすればよいprodですか?すでにメイン画像になっているのでisMain=1うとするとエラーになるインデックス設定はあります+にunique_keyを置くことはできません。image_id=2image=1prodisMain

|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=3isMain=0isMain = 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私のフィールドallowが1つの値と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
于 2012-10-22T15:42:48.343 に答える