| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- -- ===========================================================================
- -- S6-FUNC-004-TOOLING-LEDGER-CRUD-1
- -- MoldToolList(模工具台账)补租户内业务编码唯一索引
- --
- -- 目的:MoldTypeCode 是模工具台账的业务编码,且被下游按值引用
- -- (ProdLineDetail.MoldTypeCode 同租户命中 896 行)。
- -- 本批为 FUNC-S6-004 增加 CRUD 后,必须由 DB 约束保证租户内唯一 ——
- -- 仅靠应用层「先查后插」存在 TOCTOU 竞态,并发下会插入重复编码。
- --
- -- 范围:**只新增一个唯一索引**。
- -- 不修改 tenant_id 可空性、不改任何列定义、不改字符集/collation、
- -- 不清洗历史数据、不删除任何行。
- --
- -- 前置实测(2026-09-01,aidopdev,只读):
- -- MoldToolList 共 290 行,全部 tenant_id = 824585161322565
- -- tenant_id IS NULL = 0
- -- MoldTypeCode IS NULL = 0
- -- TRIM(MoldTypeCode) = '' = 0
- -- MoldTypeCode <> TRIM(...) = 0
- -- GROUP BY tenant_id,MoldTypeCode HAVING COUNT(*)>1 = 0 组
- -- 现有索引:仅 PRIMARY(id)
- --
- -- ⚠️ tenant_id 可空的已知边界:MySQL 的 UNIQUE 不对 NULL 做相等判定,
- -- 因此若将来出现 tenant_id IS NULL 的行,唯一性对该行不生效。
- -- 当前 0 行,且应用层写入一律由服务端从 JWT 盖章 tenant_id,不会产生 NULL。
- -- 本批**不**把 tenant_id 改成 NOT NULL(属独立的 schema 变更,且实体侧
- -- ITenantIdFilter.TenantId 为 long?,硬化会被 CodeFirst 还原)。
- --
- -- ⚠️ 事务性:MySQL DDL 隐式提交,AutoVersionUpdate 不开显式事务。
- -- 故所有语句写成可安全重入:索引已存在则整段 no-op。
- -- ===========================================================================
- -- ---------------------------------------------------------------------------
- -- 01 · 前置守卫:新唯一键定义下不得存在重复,否则中止,不带病建索引、不清洗数据
- -- ---------------------------------------------------------------------------
- SET @dup := (SELECT COUNT(*) FROM (
- SELECT tenant_id, MoldTypeCode
- FROM MoldToolList
- GROUP BY tenant_id, MoldTypeCode
- HAVING COUNT(*) > 1) x);
- SET @g := IF(@dup = 0, 'DO 0', 'SELECT RAISE_MOLDTOOLLIST_DUPLICATE_TYPECODE_FOUND');
- PREPARE gstmt FROM @g;
- EXECUTE gstmt;
- DEALLOCATE PREPARE gstmt;
- -- ---------------------------------------------------------------------------
- -- 02 · 建唯一索引 uk_MoldToolList_tenant_type_code(tenant_id, MoldTypeCode)
- -- 条件:同名索引不存在才建;已存在则整段 no-op(可重入)
- -- ---------------------------------------------------------------------------
- SET @idx_exists := (SELECT COUNT(DISTINCT INDEX_NAME) FROM information_schema.STATISTICS
- WHERE TABLE_SCHEMA = DATABASE()
- AND TABLE_NAME = 'MoldToolList'
- AND INDEX_NAME = 'uk_MoldToolList_tenant_type_code');
- SET @s := IF(@idx_exists = 0,
- 'CREATE UNIQUE INDEX uk_MoldToolList_tenant_type_code ON MoldToolList (tenant_id, MoldTypeCode)',
- 'DO 0');
- PREPARE stmt FROM @s;
- EXECUTE stmt;
- DEALLOCATE PREPARE stmt;
|