-- v3.5.4 商品规格:SPU + SKU -- 1) 新建规格/SKU 表 2) 订单快照列 3) SPU 去掉 sku/barcode 唯一 4) 存量默认 SKU 回填 -- 销售单位枚举(Prisma 用字符串枚举映射;MySQL 用 VARCHAR,此处仅建表) CREATE TABLE IF NOT EXISTS common_product_spec_attr ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, product_id BIGINT UNSIGNED NOT NULL, name VARCHAR(32) NOT NULL, sort_order INT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (id), KEY idx_spec_attr_product (product_id, sort_order), CONSTRAINT fk_spec_attr_product FOREIGN KEY (product_id) REFERENCES common_product_item (id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS common_product_spec_value ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, attr_id BIGINT UNSIGNED NOT NULL, name VARCHAR(64) NOT NULL, sort_order INT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (id), KEY idx_spec_value_attr (attr_id, sort_order), CONSTRAINT fk_spec_value_attr FOREIGN KEY (attr_id) REFERENCES common_product_spec_attr (id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS common_product_sku ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, product_id BIGINT UNSIGNED NOT NULL, sku_code VARCHAR(32) NOT NULL, barcode_69 VARCHAR(32) NOT NULL, spec_key VARCHAR(128) NOT NULL DEFAULT '', spec_text VARCHAR(128) NOT NULL DEFAULT '', price DECIMAL(10, 2) NOT NULL, benefit_amount DECIMAL(10, 2) NULL, status VARCHAR(16) NOT NULL DEFAULT 'DRAFT', allow_on_site_pickup TINYINT(1) NOT NULL DEFAULT 0, allow_online_purchase TINYINT(1) NOT NULL DEFAULT 1, allow_cross_city_delivery TINYINT(1) NOT NULL DEFAULT 1, sale_unit VARCHAR(16) NOT NULL DEFAULT 'BOTTLE', bottles_per_unit INT NOT NULL DEFAULT 1, is_default TINYINT(1) NOT NULL DEFAULT 0, sort_order INT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (id), UNIQUE KEY uk_product_sku_code (sku_code), UNIQUE KEY uk_product_sku_barcode (barcode_69), UNIQUE KEY uk_product_sku_spec_key (product_id, spec_key), KEY idx_product_sku_status (product_id, status), KEY idx_product_sku_default (product_id, is_default), CONSTRAINT fk_product_sku_product FOREIGN KEY (product_id) REFERENCES common_product_item (id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS common_product_sku_spec ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, sku_id BIGINT UNSIGNED NOT NULL, value_id BIGINT UNSIGNED NOT NULL, PRIMARY KEY (id), UNIQUE KEY uk_sku_spec (sku_id, value_id), KEY idx_sku_spec_value (value_id), CONSTRAINT fk_sku_spec_sku FOREIGN KEY (sku_id) REFERENCES common_product_sku (id) ON DELETE CASCADE, CONSTRAINT fk_sku_spec_value FOREIGN KEY (value_id) REFERENCES common_product_spec_value (id) ON DELETE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 订单快照列 ALTER TABLE user_order ADD COLUMN sku_id BIGINT UNSIGNED NULL AFTER product_id, ADD COLUMN sale_unit VARCHAR(16) NOT NULL DEFAULT 'BOTTLE' AFTER quantity, ADD COLUMN bottles_per_unit INT NOT NULL DEFAULT 1 AFTER sale_unit; ALTER TABLE user_order ADD KEY idx_order_sku_id (sku_id); -- SPU:去掉 sku_code / barcode_69 唯一(保留普通索引);若索引名不同可手工调整 ALTER TABLE common_product_item DROP INDEX sku_code; ALTER TABLE common_product_item DROP INDEX barcode_69; ALTER TABLE common_product_item ADD INDEX idx_product_item_sku_code (sku_code); ALTER TABLE common_product_item ADD INDEX idx_product_item_barcode_69 (barcode_69); -- 存量商品回填默认 SKU(无规格,瓶装) INSERT INTO common_product_sku ( product_id, sku_code, barcode_69, spec_key, spec_text, price, benefit_amount, status, allow_on_site_pickup, allow_online_purchase, allow_cross_city_delivery, sale_unit, bottles_per_unit, is_default, sort_order, created_at, updated_at ) SELECT p.id, p.sku_code, p.barcode_69, '', COALESCE(p.spec, ''), p.price, p.benefit_amount, p.status, p.allow_on_site_pickup, p.allow_online_purchase, p.allow_cross_city_delivery, 'BOTTLE', 1, 1, 0, NOW(3), NOW(3) FROM common_product_item p WHERE NOT EXISTS ( SELECT 1 FROM common_product_sku s WHERE s.product_id = p.id );