migration_dispatch_user_id.sql 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 reporter_id / 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. -- · 名称列(reporter / verifier / handler / editor / assessor / create_by / update_by)
  26. -- **保留不删**,作为快照冗余:① 兼容存量数据;② 用户离职被删后仍能展示文字。
  27. -- 展示口径:以 *_id 反查 sys_user.nick_name 为准,查不到再退回名称快照。
  28. -- · create_by / update_by 是 RuoYi 通用字段,存的是**登录名 sys_user.user_name**,
  29. -- 故回填按 user_name 匹配;其余业务人员列存的是**昵称 sys_user.nick_name**,按 nick_name 匹配。
  30. -- · 不变更任何现存列的类型与取值,纯新增,不破坏既有功能。
  31. -- · dis_event_log / dis_plan_log 早在建模时就是 oper_user_id + oper_user_name 双字段,本脚本不涉及。
  32. --
  33. -- 幂等性:ADD COLUMN IF NOT EXISTS,可重复执行;回填只作用于 *_id IS NULL 的行。
  34. --
  35. -- ⚠️ KingbaseES 方言红线(本库实测):
  36. -- · `||` 在本实例被解析为**布尔 OR**,禁止用于字符串拼接,必须用 concat()。
  37. -- · information_schema.tables 会触发 sys_freespace() 权限校验,业务账号可能无权限,
  38. -- 判断表是否存在请用 to_regclass()。
  39. -- ⚠️ 客户端执行提示:
  40. -- · 语句失败后事务会挂起(25P02),后续查询一律报「当前事务被终止」,先执行 ROLLBACK; 再重试。
  41. -- · 选中运行时不要连带注释行,客户端会把注释并入语句并吃掉一个减号,导致语法错。
  42. -- · 本脚本为单事务,请整体执行(BEGIN; … COMMIT;),不要逐段选中执行。
  43. -- =====================================================================
  44. BEGIN;
  45. -- =====================================================================
  46. -- 一、补列
  47. -- =====================================================================
  48. -- 1.1 dis_event 事件主表
  49. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS reporter_id int8;
  50. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS verifier_id int8;
  51. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS handler_id int8;
  52. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS create_user_id int8;
  53. ALTER TABLE app_user.dis_event ADD COLUMN IF NOT EXISTS update_user_id int8;
  54. COMMENT ON COLUMN app_user.dis_event.reporter_id IS '接报人用户ID(sys_user.user_id);接报登记时固定取当前录入人员,与 reporter 快照同时写入';
  55. COMMENT ON COLUMN app_user.dis_event.verifier_id IS '核验人用户ID(sys_user.user_id);初判核实时的当前登录用户';
  56. COMMENT ON COLUMN app_user.dis_event.handler_id IS '责任处置人用户ID(sys_user.user_id);与 handler 快照、handler_phone 同时写入';
  57. COMMENT ON COLUMN app_user.dis_event.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  58. COMMENT ON COLUMN app_user.dis_event.update_user_id IS '最后修改人用户ID(sys_user.user_id);update_by 存登录名,本列存ID';
  59. -- 1.2 dis_plan 预案主表
  60. ALTER TABLE app_user.dis_plan ADD COLUMN IF NOT EXISTS create_user_id int8;
  61. ALTER TABLE app_user.dis_plan ADD COLUMN IF NOT EXISTS update_user_id int8;
  62. COMMENT ON COLUMN app_user.dis_plan.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  63. COMMENT ON COLUMN app_user.dis_plan.update_user_id IS '最后修改人用户ID(sys_user.user_id);update_by 存登录名,本列存ID';
  64. -- 1.3 dis_plan_version 预案版本快照表
  65. ALTER TABLE app_user.dis_plan_version ADD COLUMN IF NOT EXISTS editor_id int8;
  66. COMMENT ON COLUMN app_user.dis_plan_version.editor_id IS '修订人用户ID(sys_user.user_id);与 editor 名称快照同时写入';
  67. -- 1.4 dis_event_grade 事件分级标准表
  68. ALTER TABLE app_user.dis_event_grade ADD COLUMN IF NOT EXISTS create_user_id int8;
  69. ALTER TABLE app_user.dis_event_grade ADD COLUMN IF NOT EXISTS update_user_id int8;
  70. COMMENT ON COLUMN app_user.dis_event_grade.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  71. COMMENT ON COLUMN app_user.dis_event_grade.update_user_id IS '最后修改人用户ID(sys_user.user_id);update_by 存登录名,本列存ID';
  72. -- 1.5 dis_event_assess 事后评估表
  73. ALTER TABLE app_user.dis_event_assess ADD COLUMN IF NOT EXISTS assessor_id int8;
  74. ALTER TABLE app_user.dis_event_assess ADD COLUMN IF NOT EXISTS create_user_id int8;
  75. ALTER TABLE app_user.dis_event_assess ADD COLUMN IF NOT EXISTS update_user_id int8;
  76. COMMENT ON COLUMN app_user.dis_event_assess.assessor_id IS '评估人用户ID(sys_user.user_id);与 assessor 名称快照同时写入';
  77. COMMENT ON COLUMN app_user.dis_event_assess.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  78. COMMENT ON COLUMN app_user.dis_event_assess.update_user_id IS '最后修改人用户ID(sys_user.user_id);update_by 存登录名,本列存ID';
  79. -- 1.6 数字预案库 / 匹配记录(只有创建人,无人工操作列)
  80. ALTER TABLE app_user.dis_plan_library ADD COLUMN IF NOT EXISTS create_user_id int8;
  81. ALTER TABLE app_user.dis_plan_match_record ADD COLUMN IF NOT EXISTS create_user_id int8;
  82. COMMENT ON COLUMN app_user.dis_plan_library.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  83. COMMENT ON COLUMN app_user.dis_plan_match_record.create_user_id IS '创建人用户ID(sys_user.user_id);create_by 存登录名,本列存ID';
  84. -- 1.7 索引:列表可能按「我的接报 / 我核实的」筛选
  85. CREATE INDEX IF NOT EXISTS idx_dis_event_reporter_id ON app_user.dis_event(reporter_id);
  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 reporter_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.reporter_id IS NULL
  99. AND e.reporter IS NOT NULL
  100. AND e.reporter = m.nick_name
  101. AND m.cnt = 1;
  102. -- 2.2 dis_event —— 核验人(昵称)
  103. UPDATE app_user.dis_event e
  104. SET verifier_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.verifier_id IS NULL
  108. AND e.verifier IS NOT NULL
  109. AND e.verifier = m.nick_name
  110. AND m.cnt = 1;
  111. -- 2.3 dis_event —— 责任处置人(昵称)
  112. UPDATE app_user.dis_event e
  113. SET handler_id = m.user_id
  114. FROM (SELECT nick_name, min(user_id) AS user_id, count(*) AS cnt
  115. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY nick_name) m
  116. WHERE e.handler_id IS NULL
  117. AND e.handler IS NOT NULL
  118. AND e.handler = m.nick_name
  119. AND m.cnt = 1;
  120. -- 2.4 dis_event —— 创建人 / 修改人(登录名)
  121. UPDATE app_user.dis_event e
  122. SET create_user_id = m.user_id
  123. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  124. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  125. WHERE e.create_user_id IS NULL
  126. AND e.create_by IS NOT NULL
  127. AND e.create_by = m.user_name
  128. AND m.cnt = 1;
  129. UPDATE app_user.dis_event e
  130. SET update_user_id = m.user_id
  131. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  132. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  133. WHERE e.update_user_id IS NULL
  134. AND e.update_by IS NOT NULL
  135. AND e.update_by = m.user_name
  136. AND m.cnt = 1;
  137. -- 2.5 dis_plan —— 创建人 / 修改人(登录名)
  138. UPDATE app_user.dis_plan p
  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 p.create_user_id IS NULL
  143. AND p.create_by IS NOT NULL
  144. AND p.create_by = m.user_name
  145. AND m.cnt = 1;
  146. UPDATE app_user.dis_plan p
  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 p.update_user_id IS NULL
  151. AND p.update_by IS NOT NULL
  152. AND p.update_by = m.user_name
  153. AND m.cnt = 1;
  154. -- 2.6 dis_plan_version —— 修订人(昵称)
  155. UPDATE app_user.dis_plan_version v
  156. SET editor_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 v.editor_id IS NULL
  160. AND v.editor IS NOT NULL
  161. AND v.editor = m.nick_name
  162. AND m.cnt = 1;
  163. -- 2.7 dis_event_grade —— 创建人 / 修改人(登录名)
  164. UPDATE app_user.dis_event_grade g
  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 g.create_user_id IS NULL
  169. AND g.create_by IS NOT NULL
  170. AND g.create_by = m.user_name
  171. AND m.cnt = 1;
  172. UPDATE app_user.dis_event_grade g
  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 g.update_user_id IS NULL
  177. AND g.update_by IS NOT NULL
  178. AND g.update_by = m.user_name
  179. AND m.cnt = 1;
  180. -- 2.8 dis_event_assess —— 评估人(昵称)
  181. UPDATE app_user.dis_event_assess a
  182. SET assessor_id = m.user_id
  183. FROM (SELECT nick_name, min(user_id) AS user_id, count(*) AS cnt
  184. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY nick_name) m
  185. WHERE a.assessor_id IS NULL
  186. AND a.assessor IS NOT NULL
  187. AND a.assessor = m.nick_name
  188. AND m.cnt = 1;
  189. -- 2.9 dis_event_assess —— 创建人 / 修改人(登录名)
  190. UPDATE app_user.dis_event_assess a
  191. SET create_user_id = m.user_id
  192. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  193. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  194. WHERE a.create_user_id IS NULL
  195. AND a.create_by IS NOT NULL
  196. AND a.create_by = m.user_name
  197. AND m.cnt = 1;
  198. UPDATE app_user.dis_event_assess a
  199. SET update_user_id = m.user_id
  200. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  201. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  202. WHERE a.update_user_id IS NULL
  203. AND a.update_by IS NOT NULL
  204. AND a.update_by = m.user_name
  205. AND m.cnt = 1;
  206. -- 2.10 dis_plan_library / dis_plan_match_record —— 创建人(登录名)
  207. UPDATE app_user.dis_plan_library l
  208. SET create_user_id = m.user_id
  209. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  210. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  211. WHERE l.create_user_id IS NULL
  212. AND l.create_by IS NOT NULL
  213. AND l.create_by = m.user_name
  214. AND m.cnt = 1;
  215. UPDATE app_user.dis_plan_match_record r
  216. SET create_user_id = m.user_id
  217. FROM (SELECT user_name, min(user_id) AS user_id, count(*) AS cnt
  218. FROM app_user.sys_user WHERE del_flag = '0' GROUP BY user_name) m
  219. WHERE r.create_user_id IS NULL
  220. AND r.create_by IS NOT NULL
  221. AND r.create_by = m.user_name
  222. AND m.cnt = 1;
  223. COMMIT;
  224. -- =====================================================================
  225. -- 三、执行后自检(另开查询窗口执行,不属于本事务)
  226. -- =====================================================================
  227. -- 1) 列是否补齐
  228. -- SELECT table_name, column_name FROM information_schema.columns
  229. -- WHERE table_schema = 'app_user' AND column_name LIKE '%_id'
  230. -- AND table_name IN ('dis_event','dis_plan','dis_plan_version','dis_event_grade',
  231. -- 'dis_event_assess','dis_plan_library','dis_plan_match_record')
  232. -- ORDER BY table_name, column_name;
  233. -- 2) 回填覆盖率(total = 有名称的行数,filled = 已回填用户ID的行数)
  234. -- SELECT 'dis_event.reporter' AS col, count(reporter) AS total, count(reporter_id) AS filled FROM app_user.dis_event
  235. -- UNION ALL SELECT 'dis_event.verifier', count(verifier), count(verifier_id) FROM app_user.dis_event
  236. -- UNION ALL SELECT 'dis_event.handler', count(handler), count(handler_id) FROM app_user.dis_event
  237. -- UNION ALL SELECT 'dis_event.create_by', count(create_by), count(create_user_id) FROM app_user.dis_event
  238. -- UNION ALL SELECT 'dis_plan.create_by', count(create_by), count(create_user_id) FROM app_user.dis_plan
  239. -- UNION ALL SELECT 'dis_plan_version.editor', count(editor), count(editor_id) FROM app_user.dis_plan_version;
  240. -- 3) 名称与ID是否对得上(应返回 0 行)
  241. -- SELECT id, reporter, reporter_id FROM app_user.dis_event e
  242. -- WHERE reporter_id IS NOT NULL
  243. -- AND NOT EXISTS (SELECT 1 FROM app_user.sys_user u WHERE u.user_id = e.reporter_id AND u.nick_name = e.reporter);