migration_dispatch_user_id.sql 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. -- =====================================================================
  2. -- 应急与指挥调度模块(dispatch)—— 人员字段补存「用户ID」迁移脚本
  3. -- 数据库:KingbaseES(PG 兼容模式),业务 schema = app_user
  4. --
  5. -- 背景(问题):
  6. -- 原设计只在业务表里存人员的「名称快照」(接报人 / 核验人 / 责任处置人 / 修订人 /
  7. -- 评估人 / 创建人 / 修改人),没有存 sys_user.user_id,导致:
  8. -- ① 用户改名后,历史数据无法再关联到本人;
  9. -- ② 无法按用户维度筛选(如「查我的接报」);
  10. -- ③ 与日志表的 oper_user_id 口径不一致(日志早就存了 id + 名称两份)。
  11. --
  12. -- 本脚本做什么:
  13. -- 1) 补 *_id 列(int8,与 sys_user.user_id 同类型):
  14. -- dis_event verifier_id / handler_id / create_user_id / update_user_id
  15. -- dis_plan create_user_id / update_user_id
  16. -- dis_plan_version editor_id
  17. -- dis_event_grade create_user_id / update_user_id
  18. -- dis_event_assess assessor_id / create_user_id / update_user_id
  19. -- dis_plan_library create_user_id
  20. -- dis_plan_match_record create_user_id
  21. -- 2) 按名称回填存量数据的 *_id —— **仅当该名称在 sys_user 中唯一命中时才回填**,
  22. -- 命中多条或查不到的一律留空,避免张冠李戴。
  23. --
  24. -- 口径说明(重要):
  25. -- · 名称列(verifier / handler / editor / assessor / create_by / update_by)
  26. -- **保留不删**,作为快照冗余:① 兼容存量数据;② 用户离职被删后仍能展示文字。
  27. -- 展示口径:以 *_id 反查 sys_user.nick_name 为准,查不到再退回名称快照。
  28. -- · dis_event 接报人统一由 create_user_id 关联,不再保留 reporter / reporter_id;
  29. -- 该表 create_by / update_by 亦已移除,审计只使用 create_user_id / update_user_id。
  30. -- · dis_plan_library 已移除 create_by,创建人只使用 create_user_id,不再按旧名称回填。
  31. -- · create_by / update_by 是 RuoYi 通用字段,存的是**登录名 sys_user.user_name**,
  32. -- 故回填按 user_name 匹配;其余业务人员列存的是**昵称 sys_user.nick_name**,按 nick_name 匹配。
  33. -- · 不变更任何现存列的类型与取值,纯新增,不破坏既有功能。
  34. -- · dis_event_log / dis_plan_log 早在建模时就是 oper_user_id + oper_user_name 双字段,本脚本不涉及。
  35. --
  36. -- 幂等性:ADD COLUMN IF NOT EXISTS,可重复执行;回填只作用于 *_id IS NULL 的行。
  37. --
  38. -- ⚠️ KingbaseES 方言红线(本库实测):
  39. -- · `||` 在本实例被解析为**布尔 OR**,禁止用于字符串拼接,必须用 concat()。
  40. -- · information_schema.tables 会触发 sys_freespace() 权限校验,业务账号可能无权限,
  41. -- 判断表是否存在请用 to_regclass()。
  42. -- ⚠️ 客户端执行提示:
  43. -- · 语句失败后事务会挂起(25P02),后续查询一律报「当前事务被终止」,先执行 ROLLBACK; 再重试。
  44. -- · 选中运行时不要连带注释行,客户端会把注释并入语句并吃掉一个减号,导致语法错。
  45. -- · 本脚本为单事务,请整体执行(BEGIN; … COMMIT;),不要逐段选中执行。
  46. -- =====================================================================
  47. BEGIN;
  48. -- =====================================================================
  49. -- 一、补列
  50. -- =====================================================================
  51. -- 1.1 dis_event 事件主表
  52. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS verifier_id int8;
  53. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS handler_id int8;
  54. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS create_user_id int8;
  55. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS update_user_id int8;
  56. COMMENT ON COLUMN app_user.dis_event.verifier_id IS '核验人用户ID(sys_user.user_id);初判核实时的当前登录用户';
  57. COMMENT ON COLUMN app_user.dis_event.handler_id IS '责任处置人用户ID(sys_user.user_id);与 handler 快照、handler_phone 同时写入';
  58. COMMENT ON COLUMN app_user.dis_event.create_user_id IS '创建人用户ID(sys_user.user_id)';
  59. COMMENT ON COLUMN app_user.dis_event.update_user_id IS '最后修改人用户ID(sys_user.user_id)';
  60. -- 1.2 dis_plan 预案主表
  61. ALTER TABLE app_user.dis_plan ADD COLUMN IF NOT EXISTS create_user_id int8;
  62. ALTER TABLE app_user.dis_plan ADD COLUMN IF NOT EXISTS update_user_id int8;
  63. COMMENT ON COLUMN app_user.dis_plan.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  64. COMMENT ON COLUMN app_user.dis_plan.update_user_id IS '最后修改人用户ID(sys_user.user_id);update_by 存登录名,本列存ID';
  65. -- 1.3 dis_plan_version 预案版本快照表
  66. ALTER TABLE app_user.dis_plan_version ADD COLUMN IF NOT EXISTS editor_id int8;
  67. COMMENT ON COLUMN app_user.dis_plan_version.editor_id IS '修订人用户ID(sys_user.user_id);与 editor 名称快照同时写入';
  68. -- 1.4 dis_event_grade 事件分级标准表
  69. ALTER TABLE app_user.dis_event_grade ADD COLUMN IF NOT EXISTS create_user_id int8;
  70. ALTER TABLE app_user.dis_event_grade ADD COLUMN IF NOT EXISTS update_user_id int8;
  71. COMMENT ON COLUMN app_user.dis_event_grade.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  72. COMMENT ON COLUMN app_user.dis_event_grade.update_user_id IS '最后修改人用户ID(sys_user.user_id);update_by 存登录名,本列存ID';
  73. -- 1.5 dis_event_assess 事后评估表
  74. ALTER TABLE app_user.dis_event_assess ADD COLUMN IF NOT EXISTS assessor_id int8;
  75. ALTER TABLE app_user.dis_event_assess ADD COLUMN IF NOT EXISTS create_user_id int8;
  76. ALTER TABLE app_user.dis_event_assess ADD COLUMN IF NOT EXISTS update_user_id int8;
  77. COMMENT ON COLUMN app_user.dis_event_assess.assessor_id IS '评估人用户ID(sys_user.user_id);与 assessor 名称快照同时写入';
  78. COMMENT ON COLUMN app_user.dis_event_assess.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  79. COMMENT ON COLUMN app_user.dis_event_assess.update_user_id IS '最后修改人用户ID(sys_user.user_id);update_by 存登录名,本列存ID';
  80. -- 1.6 数字预案库 / 匹配记录(只有创建人,无人工操作列)
  81. ALTER TABLE app_user.dis_plan_library ADD COLUMN IF NOT EXISTS create_user_id int8;
  82. ALTER TABLE app_user.dis_plan_match_record ADD COLUMN IF NOT EXISTS create_user_id int8;
  83. COMMENT ON COLUMN app_user.dis_plan_library.create_user_id IS '创建人用户ID(sys_user.user_id)';
  84. COMMENT ON COLUMN app_user.dis_plan_match_record.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  85. -- 1.7 索引:列表可能按「我的接报 / 我核实的」筛选
  86. CREATE INDEX IF NOT EXISTS idx_dis_event_verifier_id ON app_user.dis_event(verifier_id);
  87. CREATE INDEX IF NOT EXISTS idx_dis_event_handler_id ON app_user.dis_event(handler_id);
  88. -- =====================================================================
  89. -- 二、存量数据回填
  90. -- 匹配口径:昵称列 → sys_user.nick_name;create_by/update_by → sys_user.user_name。
  91. -- 只回填「唯一命中」的名称;同名(如两个「张伟」)或查不到的一律留空。
  92. -- =====================================================================
  93. -- 2.1 dis_event —— 核验人(昵称)
  94. UPDATE app_user.dis_event e
  95. SET verifier_id = m.user_id
  96. FROM (SELECT nick_name, min(user_id) AS user_id, count(*) AS cnt
  97. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY nick_name) m
  98. WHERE e.verifier_id IS NULL
  99. AND e.verifier IS NOT NULL
  100. AND e.verifier = m.nick_name
  101. AND m.cnt = 1;
  102. -- 2.2 dis_event —— 责任处置人(昵称)
  103. UPDATE app_user.dis_event e
  104. SET handler_id = m.user_id
  105. FROM (SELECT nick_name, min(user_id) AS user_id, count(*) AS cnt
  106. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY nick_name) m
  107. WHERE e.handler_id IS NULL
  108. AND e.handler IS NOT NULL
  109. AND e.handler = m.nick_name
  110. AND m.cnt = 1;
  111. -- 2.5 dis_plan —— 创建人 / 修改人(登录名)
  112. UPDATE app_user.dis_plan p
  113. SET create_user_id = m.user_id
  114. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  115. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  116. WHERE p.create_user_id IS NULL
  117. AND p.create_by IS NOT NULL
  118. AND p.create_by = m.user_name
  119. AND m.cnt = 1;
  120. UPDATE app_user.dis_plan p
  121. SET update_user_id = m.user_id
  122. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  123. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  124. WHERE p.update_user_id IS NULL
  125. AND p.update_by IS NOT NULL
  126. AND p.update_by = m.user_name
  127. AND m.cnt = 1;
  128. -- 2.6 dis_plan_version —— 修订人(昵称)
  129. UPDATE app_user.dis_plan_version v
  130. SET editor_id = m.user_id
  131. FROM (SELECT nick_name, min(user_id) AS user_id, count(*) AS cnt
  132. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY nick_name) m
  133. WHERE v.editor_id IS NULL
  134. AND v.editor IS NOT NULL
  135. AND v.editor = m.nick_name
  136. AND m.cnt = 1;
  137. -- 2.7 dis_event_grade —— 创建人 / 修改人(登录名)
  138. UPDATE app_user.dis_event_grade g
  139. SET create_user_id = m.user_id
  140. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  141. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  142. WHERE g.create_user_id IS NULL
  143. AND g.create_by IS NOT NULL
  144. AND g.create_by = m.user_name
  145. AND m.cnt = 1;
  146. UPDATE app_user.dis_event_grade g
  147. SET update_user_id = m.user_id
  148. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  149. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  150. WHERE g.update_user_id IS NULL
  151. AND g.update_by IS NOT NULL
  152. AND g.update_by = m.user_name
  153. AND m.cnt = 1;
  154. -- 2.8 dis_event_assess —— 评估人(昵称)
  155. UPDATE app_user.dis_event_assess a
  156. SET assessor_id = m.user_id
  157. FROM (SELECT nick_name, min(user_id) AS user_id, count(*) AS cnt
  158. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY nick_name) m
  159. WHERE a.assessor_id IS NULL
  160. AND a.assessor IS NOT NULL
  161. AND a.assessor = m.nick_name
  162. AND m.cnt = 1;
  163. -- 2.9 dis_event_assess —— 创建人 / 修改人(登录名)
  164. UPDATE app_user.dis_event_assess a
  165. SET create_user_id = m.user_id
  166. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  167. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  168. WHERE a.create_user_id IS NULL
  169. AND a.create_by IS NOT NULL
  170. AND a.create_by = m.user_name
  171. AND m.cnt = 1;
  172. UPDATE app_user.dis_event_assess a
  173. SET update_user_id = m.user_id
  174. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  175. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  176. WHERE a.update_user_id IS NULL
  177. AND a.update_by IS NOT NULL
  178. AND a.update_by = m.user_name
  179. AND m.cnt = 1;
  180. -- 2.10 dis_plan_match_record —— 创建人(登录名);预案库不再保留 create_by。
  181. UPDATE app_user.dis_plan_match_record r
  182. SET create_user_id = m.user_id
  183. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  184. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  185. WHERE r.create_user_id IS NULL
  186. AND r.create_by IS NOT NULL
  187. AND r.create_by = m.user_name
  188. AND m.cnt = 1;
  189. COMMIT;
  190. -- =====================================================================
  191. -- 三、执行后自检(另开查询窗口执行,不属于本事务)
  192. -- =====================================================================
  193. -- 1) 列是否补齐
  194. -- SELECT table_name, column_name FROM information_schema.columns
  195. -- WHERE table_schema = 'app_user' AND column_name LIKE '%_id'
  196. -- AND table_name IN ('dis_event','dis_plan','dis_plan_version','dis_event_grade',
  197. -- 'dis_event_assess','dis_plan_library','dis_plan_match_record')
  198. -- ORDER BY table_name, column_name;
  199. -- 2) 回填覆盖率(total = 有名称的行数,filled = 已回填用户ID的行数)
  200. -- SELECT 'dis_event.verifier' AS col, count(verifier) AS total, count(verifier_id) AS filled FROM app_user.dis_event
  201. -- UNION ALL SELECT 'dis_event.handler', count(handler), count(handler_id) FROM app_user.dis_event
  202. -- UNION ALL SELECT 'dis_plan.create_by', count(create_by), count(create_user_id) FROM app_user.dis_plan
  203. -- UNION ALL SELECT 'dis_plan_version.editor', count(editor), count(editor_id) FROM app_user.dis_plan_version;
  204. -- 3) 名称与ID是否对得上(应返回 0 行)
  205. -- SELECT id, verifier, verifier_id FROM app_user.dis_event e
  206. -- WHERE verifier_id IS NOT NULL
  207. -- AND NOT EXISTS (SELECT 1 FROM app_user.sys_user u WHERE u.user_id = e.verifier_id AND u.nick_name = e.verifier);