2016-11-23 1 views
0

私は製品テーブルとproduct_variantsテーブル(一対多)を持っています。MySql - 製品バリアントテーブル(ワイドテーブル) - 一意のNULL

product_variantsテーブルの構造は次の通りである:

CREATE TABLE product_variants (
    id int(11) NOT NULL AUTO_INCREMENT, 
    id_product int(11) NOT NULL, 
    id_colourSet int(11) DEFAULT NULL, 
    id_size int(11) DEFAULT NULL, 
    PRIMARY KEY (id), 
    UNIQUE KEY UNIQUE (id_product,id_colourSet,id_size), 
    KEY idx_prod (id_product), 
    KEY idx_colourSet (id_colourSet), 
    KEY idx_size (id_size), 
    CONSTRAINT fk_df_product_variants_id_colurSet FOREIGN KEY (id_colourSet) REFERENCES df_colour_sets (id_colourSet) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT fk_df_product_variants_id_product FOREIGN KEY (id_product) REFERENCES df_products (id) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT fk_df_product_variants_id_size FOREIGN KEY (id_size) REFERENCES df_sizes (id) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB 

オプションはコンパイル時に知られています。各オプションは専用テーブルに外部キーで割り当てられ、固有キーはすべてのオプションの組み合わせです。

ステートメントで商品を挿入し、バリアントがすでに存在する場合は、既存のバリアントを使用します。

問題は、特定の製品に色やサイズがないことです。この場合、ユニーク制約は失敗し、product_variantsテーブルにはほとんど空の行がたくさん挿入されます。

この問題を解決するために、それぞれのオプションテーブルの各オプション(たとえば "NO_COLOR"、 "NO_SIZE")に "NULL"値を作成し、それをオプションテーブルのデフォルト値として使用しています。 product_variantsテーブル。

これは推奨されるソリューションですか?このデータを構造化するより良い方法はありますか?私はEAVデザインを避けたいと思っています。

答えて

1

は「欠損値」は、ほぼすべてのケースで適切なソリューションではないことを意味する魔法の値の指定いただきありがとうございます。それがNULLのためのものです。

整数に「NO_COLOR」がどのように使用されているかについても明確ではありません。私は値0にマップされると思いますが、これは通常、自動インクリメント列では使用されません。

別の列を作成して、3つの一意のキー列のハッシュにすることができます。デフォルトでは ''に設定され、ヌル問題を回避します。次に、そのハッシュに一意制約を設定します。

CREATE TABLE product_variants (
    id int(11) NOT NULL AUTO_INCREMENT, 
    id_product int(11) NOT NULL, 
    id_colourSet int(11) DEFAULT NULL, 
    id_size int(11) DEFAULT NULL, 
    option_hash binary(16) NOT NULL, 
    PRIMARY KEY (id), 
    UNIQUE KEY (option_hash), 
    KEY idx_prod (id_product), 
    KEY idx_colourSet (id_colourSet), 
    KEY idx_size (id_size), 
    CONSTRAINT fk_df_product_variants_id_colurSet FOREIGN KEY (id_colourSet) REFERENCES df_colour_sets (id_colourSet) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT fk_df_product_variants_id_product FOREIGN KEY (id_product) REFERENCES df_products (id) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT fk_df_product_variants_id_size FOREIGN KEY (id_size) REFERENCES df_sizes (id) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB; 

CREATE TRIGGER product_variants_ins BEFORE INSERT ON product_variants 
FOR EACH ROW SET option_hash = UNHEX(MD5(CONCAT_WS('|', 
    COALESCE(id_product, ''), 
    COALESCE(id_colourSet, ''), 
    COALESCE(id_size, '')))); 

CREATE TRIGGER product_variants_upd BEFORE UPDATE ON product_variants 
FOR EACH ROW SET option_hash = UNHEX(MD5(CONCAT_WS('|', 
    COALESCE(id_product, ''), 
    COALESCE(id_colourSet, ''), 
    COALESCE(id_size, '')))); 
+0

トリガーはトランザクションで正常に動作しますか?例えば。多くの "INSERT ... ON DUPLICATE KEY UPDATE ..."ステートメントを1つのトランザクションで実行します。 – mils

+0

@milsを使用すると、トリガー内での変更を含め、1つのトランザクションで任意の数の変更を事実上行うことができます。トリガーの変更は、トリガーを発生させた変更と同じトランザクションの一部です。 –

関連する問題