2016-11-23 5 views
0

제품 테이블과 product_variants 테이블 (일대 다 테이블)이 있습니다.MySql - 제품 변형 테이블 (와이드 테이블) - 고유 NULL 포함

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 테이블은 다음과 같은 구조를 가지고 있습니다. 각 옵션은 전용 테이블에 대해 외래 키이고 고유 키는 모든 옵션의 조합입니다.

그런 다음 "ON DUPLICATE KEY UPDATE ..." 문을 사용하여 제품을 삽입하고 변형이 이미 존재하는 경우 기존 변형을 사용합니다.

문제는 특정 제품에는 색상이나 크기가 없기 때문입니다. 이 경우 고유 제한 조건이 실패하고 product_variants 테이블에 거의 빈 행이 많이 삽입됩니다.

이 문제를 해결하기 위해 각 옵션 테이블 (예 : "NO_COLOR", "NO_SIZE")에 대해 "NULL"값을 생성하고 해당 옵션 테이블의 옵션 열에 대한 기본값으로 사용합니다. product_variants 테이블.

권장되는 해결책입니까? 이 데이터를 구조화하는 더 좋은 방법이 있습니까? EAV 디자인을 피하고 싶습니다.

답변

1

거의 모든 경우에 올바른 해결책이 아니다 "값 누락"을 의미 마법의 값을 지정 감사드립니다. 그것이 NULL입니다.

"NO_COLOR"가 정수로 사용되는 방법이 명확하지 않습니다. 자동 증가 열에서 일반적으로 사용되지 않는 값 0에 매핑됩니다.

세 가지 고유 키 열의 해시가되도록 다른 열을 만들 수 있으며, 기본값은 ''로 설정되어 Null 문제를 피할 수 있습니다. 그런 다음 해시에 고유 제한 조건을 지정하십시오.

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 ..."문을 사용합니다. – mils

+0

@mils를 사용하면 트리거 내부 변경 사항을 포함하여 단일 트랜잭션에서 거의 모든 변경 작업을 수행 할 수 있습니다. 트리거의 변경 사항은 트리거를 생성 한 변경 사항과 동일한 트랜잭션의 일부입니다. –