2026-10-28-prod-relink-deleted-child-refs.sql 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. -- 【生产环境脚本】
  2. -- 依据生产备份 zkxw_2026-10-28_094047.sql.gz(2026-10-28 09:40)核对后编写。
  3. -- 不要在测试库执行。测试库已用同目录下文件名带【测试数据库脚本】的文件处理过。
  4. -- 生产库请执行本文件。2026-10-27 18:04 那份脚本的待修复集合与本备份一致,但请以本文件为准。
  5. --
  6. -- 背景:保存步骤产出物、协议样本、捐赠样本时曾经整表软删再插入,
  7. -- 下游仍指向 del_flag=1 的旧行。代码尚未发到生产,本备份仍是修复前的数据。
  8. -- 策略:只在同业务键下恰好有一条有效行时改指。找不到或有多条时不动。
  9. -- 幂等:已指向有效行的记录不会进入映射;重复执行影响行数为 0。
  10. -- MySQL 5.7。跨表字符串比较统一 utf8mb4_general_ci,避免 1267。
  11. -- 本脚本未在任何库执行。
  12. --
  13. -- 相对该备份的预期影响:
  14. -- 质检工单 production_step_output_id 11
  15. -- 生产工单 protocol_sample_id -> 协议样本 16
  16. -- 生产工单 protocol_sample_id -> 捐赠样本 70
  17. -- 质检短信 protocol_sample_id 15
  18. -- 按样本缴费方案 0
  19. -- 缴费方案有 3 条仍指向已软删协议样本,但同租户同编码下没有有效样本,本脚本不改:
  20. -- ZKZX34000856、ZKZX34000175、ZKZX34000199
  21. -- 样本接收、质检工单上的样本 id 在该备份中已指向有效行,本脚本不包含这两处。
  22. --
  23. -- 与 2026-10-27 18:04 备份相比,上述 11 / 16 / 70 / 15 条映射没有变化。
  24. -- 过夜新增、本脚本不会改到的行:
  25. -- 废液 NK-UBMC202603005:原有效产出物 F2755086E1AE49C1B10FA6E4624D5AE7 已被软删,
  26. -- 当前有效行是 3513B95B3FDC400C9744277B8919DAB4。没有质检工单指向被删的那一行。
  27. -- 新捐赠样本 KYJZ2026100055、KYJZ2026100056、KYJZ2026100057。
  28. -- KYJZ2026100055 另有一条已软删样本,没有生产工单指向它。
  29. -- ---------------------------------------------------------------------------
  30. -- 1. 质检工单 -> 步骤产出物
  31. -- 同一步骤、同租户,名称、条码、产出类型一致,且只有一条有效产出物
  32. -- ---------------------------------------------------------------------------
  33. DROP TEMPORARY TABLE IF EXISTS tmp_qc_output_relink;
  34. CREATE TEMPORARY TABLE tmp_qc_output_relink (
  35. qc_id VARCHAR(64) NOT NULL COLLATE utf8mb4_general_ci,
  36. new_output_id VARCHAR(64) NOT NULL COLLATE utf8mb4_general_ci,
  37. PRIMARY KEY (qc_id)
  38. ) ENGINE=MEMORY;
  39. INSERT INTO tmp_qc_output_relink (qc_id, new_output_id)
  40. SELECT q.id, MIN(live.id)
  41. FROM biz_qc_work_order q
  42. JOIN biz_production_task_step_output old
  43. ON old.id = q.production_step_output_id
  44. AND old.del_flag = 1
  45. JOIN biz_production_task_step_output live
  46. ON live.step_id = old.step_id
  47. AND live.tenant_no = old.tenant_no
  48. AND live.del_flag = 0
  49. AND live.id <> old.id
  50. AND IFNULL(live.output_name, '') = IFNULL(old.output_name, '')
  51. AND IFNULL(live.output_barcode, '') = IFNULL(old.output_barcode, '')
  52. AND IFNULL(live.output_type_id, '') = IFNULL(old.output_type_id, '')
  53. WHERE q.del_flag = 0
  54. AND IFNULL(q.production_step_output_id, '') <> ''
  55. GROUP BY q.id
  56. HAVING COUNT(*) = 1;
  57. UPDATE biz_qc_work_order q
  58. JOIN tmp_qc_output_relink m ON m.qc_id = q.id
  59. SET q.production_step_output_id = m.new_output_id,
  60. q.update_time = NOW()
  61. WHERE q.del_flag = 0
  62. AND q.production_step_output_id <> m.new_output_id;
  63. DROP TEMPORARY TABLE IF EXISTS tmp_qc_output_relink;
  64. -- ---------------------------------------------------------------------------
  65. -- 2. 生产工单 / 缴费方案 / 质检短信 -> 协议样本或捐赠样本
  66. -- 同租户、同编码恰好一条有效样本
  67. -- ---------------------------------------------------------------------------
  68. DROP TEMPORARY TABLE IF EXISTS tmp_sample_ref_relink;
  69. CREATE TEMPORARY TABLE tmp_sample_ref_relink (
  70. row_id VARCHAR(64) NOT NULL COLLATE utf8mb4_general_ci,
  71. new_sample_id VARCHAR(64) NOT NULL COLLATE utf8mb4_general_ci,
  72. PRIMARY KEY (row_id)
  73. ) ENGINE=MEMORY;
  74. -- 生产工单 -> 采集协议样本
  75. INSERT INTO tmp_sample_ref_relink (row_id, new_sample_id)
  76. SELECT w.id, MIN(live.id)
  77. FROM biz_production_work_order w
  78. JOIN biz_protocol_sample old
  79. ON old.id COLLATE utf8mb4_general_ci = w.protocol_sample_id COLLATE utf8mb4_general_ci
  80. AND old.del_flag = 1
  81. JOIN biz_protocol_sample live
  82. ON live.del_flag = 0
  83. AND live.tenant_no COLLATE utf8mb4_general_ci = old.tenant_no COLLATE utf8mb4_general_ci
  84. AND IFNULL(live.sample_code, '') COLLATE utf8mb4_general_ci = IFNULL(old.sample_code, '') COLLATE utf8mb4_general_ci
  85. AND IFNULL(live.sample_code, '') <> ''
  86. AND live.id COLLATE utf8mb4_general_ci <> old.id COLLATE utf8mb4_general_ci
  87. WHERE w.del_flag = 0
  88. GROUP BY w.id
  89. HAVING COUNT(*) = 1;
  90. UPDATE biz_production_work_order w
  91. JOIN tmp_sample_ref_relink m
  92. ON m.row_id COLLATE utf8mb4_general_ci = w.id COLLATE utf8mb4_general_ci
  93. SET w.protocol_sample_id = m.new_sample_id,
  94. w.update_time = NOW()
  95. WHERE w.del_flag = 0;
  96. DELETE FROM tmp_sample_ref_relink;
  97. -- 生产工单 -> 科研捐赠样本(工单的 protocol_sample_id 存捐赠样本 ID)
  98. INSERT INTO tmp_sample_ref_relink (row_id, new_sample_id)
  99. SELECT w.id, MIN(live.id)
  100. FROM biz_production_work_order w
  101. JOIN biz_research_donation_sample old
  102. ON old.id COLLATE utf8mb4_general_ci = w.protocol_sample_id COLLATE utf8mb4_general_ci
  103. AND old.del_flag = 1
  104. JOIN biz_research_donation_sample live
  105. ON live.del_flag = 0
  106. AND live.tenant_no COLLATE utf8mb4_general_ci = old.tenant_no COLLATE utf8mb4_general_ci
  107. AND IFNULL(live.sample_code, '') COLLATE utf8mb4_general_ci = IFNULL(old.sample_code, '') COLLATE utf8mb4_general_ci
  108. AND IFNULL(live.sample_code, '') <> ''
  109. AND live.id COLLATE utf8mb4_general_ci <> old.id COLLATE utf8mb4_general_ci
  110. WHERE w.del_flag = 0
  111. GROUP BY w.id
  112. HAVING COUNT(*) = 1;
  113. UPDATE biz_production_work_order w
  114. JOIN tmp_sample_ref_relink m
  115. ON m.row_id COLLATE utf8mb4_general_ci = w.id COLLATE utf8mb4_general_ci
  116. SET w.protocol_sample_id = m.new_sample_id,
  117. w.update_time = NOW()
  118. WHERE w.del_flag = 0;
  119. DELETE FROM tmp_sample_ref_relink;
  120. -- 按样本缴费方案。该备份中可唯一匹配的行数为 0,下面语句不会改数据。
  121. INSERT INTO tmp_sample_ref_relink (row_id, new_sample_id)
  122. SELECT p.id, MIN(live.id)
  123. FROM biz_protocol_sample_payment p
  124. JOIN biz_protocol_sample old
  125. ON old.id COLLATE utf8mb4_general_ci = p.protocol_sample_id COLLATE utf8mb4_general_ci
  126. AND old.del_flag = 1
  127. JOIN biz_protocol_sample live
  128. ON live.del_flag = 0
  129. AND live.tenant_no COLLATE utf8mb4_general_ci = old.tenant_no COLLATE utf8mb4_general_ci
  130. AND IFNULL(live.sample_code, '') COLLATE utf8mb4_general_ci = IFNULL(old.sample_code, '') COLLATE utf8mb4_general_ci
  131. AND IFNULL(live.sample_code, '') <> ''
  132. AND live.id COLLATE utf8mb4_general_ci <> old.id COLLATE utf8mb4_general_ci
  133. WHERE p.del_flag = 0
  134. GROUP BY p.id
  135. HAVING COUNT(*) = 1;
  136. UPDATE biz_protocol_sample_payment p
  137. JOIN tmp_sample_ref_relink m
  138. ON m.row_id COLLATE utf8mb4_general_ci = p.id COLLATE utf8mb4_general_ci
  139. SET p.protocol_sample_id = m.new_sample_id,
  140. p.update_time = NOW()
  141. WHERE p.del_flag = 0;
  142. DELETE FROM tmp_sample_ref_relink;
  143. -- 质检短信。del_flag 是字符 '0'
  144. INSERT INTO tmp_sample_ref_relink (row_id, new_sample_id)
  145. SELECT s.id, MIN(live.id)
  146. FROM biz_qc_sms_notification s
  147. JOIN biz_protocol_sample old
  148. ON old.id COLLATE utf8mb4_general_ci = s.protocol_sample_id COLLATE utf8mb4_general_ci
  149. AND old.del_flag = 1
  150. JOIN biz_protocol_sample live
  151. ON live.del_flag = 0
  152. AND live.tenant_no COLLATE utf8mb4_general_ci = old.tenant_no COLLATE utf8mb4_general_ci
  153. AND IFNULL(live.sample_code, '') COLLATE utf8mb4_general_ci = IFNULL(old.sample_code, '') COLLATE utf8mb4_general_ci
  154. AND IFNULL(live.sample_code, '') <> ''
  155. AND live.id COLLATE utf8mb4_general_ci <> old.id COLLATE utf8mb4_general_ci
  156. WHERE s.del_flag = '0'
  157. GROUP BY s.id
  158. HAVING COUNT(*) = 1;
  159. UPDATE biz_qc_sms_notification s
  160. JOIN tmp_sample_ref_relink m
  161. ON m.row_id COLLATE utf8mb4_general_ci = s.id COLLATE utf8mb4_general_ci
  162. SET s.protocol_sample_id = m.new_sample_id,
  163. s.update_time = NOW()
  164. WHERE s.del_flag = '0';
  165. DROP TEMPORARY TABLE IF EXISTS tmp_sample_ref_relink;