2026-08-03-crm-contract-no-global-unique.sql 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. -- 合同编号租户内全局唯一(含软删不复用)— 可重复执行
  2. -- 1) 消解已有 (contract_no, tenant_no) 撞号:保留 del_flag=0,软删行改号
  3. -- 2) 唯一索引改为 (contract_no, tenant_no)
  4. --
  5. -- 说明:若生产已执行过,旧索引 uk_contract_tenant_no_del 可能已不存在,
  6. -- 本脚本会先检查再 DROP/ADD,避免 1091。
  7. SET NAMES utf8mb4;
  8. -- 软删撞号改号:{原编号}~DEL~{id前8位}
  9. UPDATE crm_contract c
  10. INNER JOIN (
  11. SELECT contract_no, tenant_no
  12. FROM crm_contract
  13. GROUP BY contract_no, tenant_no
  14. HAVING COUNT(*) > 1
  15. ) d ON c.contract_no = d.contract_no AND c.tenant_no = d.tenant_no
  16. SET c.contract_no = CONCAT(c.contract_no, '~DEL~', LEFT(c.id, 8)),
  17. c.update_time = NOW()
  18. WHERE c.del_flag = 1
  19. AND c.contract_no NOT LIKE '%~DEL~%'
  20. AND c.contract_no NOT LIKE '%~DUP~%';
  21. -- 若仍有撞号(极端:两条都 del_flag=0),再改非 keep 的一条
  22. UPDATE crm_contract c
  23. INNER JOIN (
  24. SELECT contract_no, tenant_no, MIN(id) AS keep_id
  25. FROM crm_contract
  26. GROUP BY contract_no, tenant_no
  27. HAVING COUNT(*) > 1
  28. ) d ON c.contract_no = d.contract_no AND c.tenant_no = d.tenant_no AND c.id <> d.keep_id
  29. SET c.contract_no = CONCAT(c.contract_no, '~DUP~', LEFT(c.id, 8)),
  30. c.update_time = NOW()
  31. WHERE c.contract_no NOT LIKE '%~DUP~%';
  32. -- 有旧索引则删除
  33. SET @db := DATABASE();
  34. SET @sql := (
  35. SELECT IF(
  36. EXISTS(
  37. SELECT 1 FROM information_schema.statistics
  38. WHERE table_schema = @db
  39. AND table_name = 'crm_contract'
  40. AND index_name = 'uk_contract_tenant_no_del'
  41. ),
  42. 'ALTER TABLE crm_contract DROP INDEX `uk_contract_tenant_no_del`',
  43. 'SELECT ''skip DROP uk_contract_tenant_no_del'' AS info'
  44. )
  45. );
  46. PREPARE stmt FROM @sql;
  47. EXECUTE stmt;
  48. DEALLOCATE PREPARE stmt;
  49. -- 无新索引则添加
  50. SET @sql := (
  51. SELECT IF(
  52. EXISTS(
  53. SELECT 1 FROM information_schema.statistics
  54. WHERE table_schema = @db
  55. AND table_name = 'crm_contract'
  56. AND index_name = 'uk_contract_tenant_no'
  57. ),
  58. 'SELECT ''skip ADD uk_contract_tenant_no (already exists)'' AS info',
  59. 'ALTER TABLE crm_contract ADD UNIQUE KEY `uk_contract_tenant_no` (`contract_no`, `tenant_no`)'
  60. )
  61. );
  62. PREPARE stmt FROM @sql;
  63. EXECUTE stmt;
  64. DEALLOCATE PREPARE stmt;
  65. -- 验收:应为空
  66. SELECT contract_no, tenant_no, COUNT(*) AS cnt
  67. FROM crm_contract
  68. GROUP BY contract_no, tenant_no
  69. HAVING COUNT(*) > 1;
  70. SHOW INDEX FROM crm_contract WHERE Key_name LIKE 'uk_contract%';