cleanup_test_dirty_data.sql 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. -- ============================================================
  2. -- 测试脏数据清理脚本(《角色权限与菜单归类整合方案》B-7)
  3. -- 目标库: 192.168.16.251:3306/zxyj
  4. -- 使用方式: 逐段执行。每段先 SELECT 预览,确认无误后再执行 DELETE/UPDATE。
  5. -- 已排查修正: points_log 列名(task_id/amount)、自引用子查询 ERROR 1093、
  6. -- LIKE 通配符、users.role NOT NULL、role 为 MySQL 8.0 保留字需加反引号
  7. -- ============================================================
  8. -- 重要: 本文件含中文匹配模式,必须确保连接字符集为 utf8mb4,
  9. -- 否则 LIKE 匹配失效或报编码错误(命令行执行时: mysql --default-character-set=utf8mb4)
  10. SET NAMES utf8mb4;
  11. -- ------------------------------------------------------------
  12. -- 第 1 步:清理 TEST-Energy-Grant 测试任务
  13. -- 注意执行顺序: 先 1.2/1.4(依赖 tasks 关联),再 1.3 删除任务
  14. -- ------------------------------------------------------------
  15. -- 1.1 预览将被删除的任务
  16. SELECT id, family_id, creator_id, title, status, created_at
  17. FROM tasks
  18. WHERE title LIKE 'TEST-Energy-Grant%';
  19. -- 1.2 预览关联的积分流水(通过 task_id 关联,须先于 1.3 执行)
  20. SELECT pl.id, pl.child_id, pl.task_id, pl.amount, pl.description, pl.created_at
  21. FROM points_log pl
  22. INNER JOIN tasks t ON pl.task_id = t.id
  23. WHERE t.title LIKE 'TEST-Energy-Grant%';
  24. -- 1.3 (可选)确认后删除关联积分流水(必须在 1.4 之前执行)
  25. DELETE pl FROM points_log pl
  26. INNER JOIN tasks t ON pl.task_id = t.id
  27. WHERE t.title LIKE 'TEST-Energy-Grant%';
  28. -- 1.4 确认后删除任务
  29. DELETE FROM tasks WHERE title LIKE 'TEST-Energy-Grant%';
  30. -- ------------------------------------------------------------
  31. -- 第 2 步:清理乱码昵称/家庭名(UTF-8 按 latin1 误读产生的乱码,如"娴嬭瘯骞哥?瀹跺涵")
  32. -- 说明: MySQL LIKE 中 ? 不是通配符(通配符是 _ 和 %),乱码按实际片段匹配;
  33. -- 执行预览后如还有其他乱码片段,请自行补充 LIKE 条件
  34. -- ------------------------------------------------------------
  35. -- 2.1 预览乱码家庭
  36. SELECT id, name, invite_code, created_at
  37. FROM families
  38. WHERE name LIKE '%娴嬭瘯%' OR name LIKE '%瀹跺涵%';
  39. -- 2.2 预览乱码用户昵称
  40. SELECT id, nickname, phone, `role`, family_id, created_at
  41. FROM users
  42. WHERE nickname LIKE '%娴嬭瘯%' OR nickname LIKE '%瀹跺涵%';
  43. -- 2.3 确认后:清理乱码家庭
  44. -- 修正: MySQL 不允许 UPDATE users 时子查询 users 同表(ERROR 1093),
  45. -- 且 families 在 FROM 时不能作为 UPDATE 目标,改用多表 UPDATE JOIN
  46. -- 2.3a 解除用户与乱码家庭的关联
  47. UPDATE users u
  48. INNER JOIN families f ON u.family_id = f.id
  49. SET u.family_id = NULL
  50. WHERE f.name LIKE '%娴嬭瘯%' OR f.name LIKE '%瀹跺涵%';
  51. -- 2.3b 删除乱码家庭
  52. DELETE FROM families WHERE name LIKE '%娴嬭瘯%' OR name LIKE '%瀹跺涵%';
  53. -- 2.4 确认后:清理乱码昵称用户(软删或硬删二选一)
  54. -- 软删(推荐,users 表 deleted 列已由迁移 98 创建):
  55. UPDATE users SET deleted = 1 WHERE nickname LIKE '%娴嬭瘯%' OR nickname LIKE '%瀹跺涵%';
  56. -- 硬删(与软删二选一,默认注释):
  57. -- DELETE FROM users WHERE nickname LIKE '%娴嬭瘯%' OR nickname LIKE '%瀹跺涵%';
  58. -- ------------------------------------------------------------
  59. -- 第 3 步:历史数据角色口径修复(B-2 配套:审核已通过但 roles 未回写的存量用户)
  60. -- 说明: users.role 为 VARCHAR(20) NOT NULL(迁移 99),不会为 NULL;
  61. -- role 是 MySQL 8.0 保留关键字,必须用反引号包裹
  62. -- ------------------------------------------------------------
  63. -- 3.1 预览:营养师已审核通过但 roles 中无 nutritionist
  64. SELECT id, nickname, phone, `role`, roles, nutritionist_status
  65. FROM users
  66. WHERE nutritionist_status = 'approved'
  67. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%nutritionist%');
  68. -- 3.2 预览:规划师已审核通过但 roles 中无 teacher
  69. SELECT id, nickname, phone, `role`, roles, teacher_status
  70. FROM users
  71. WHERE teacher_status = 'approved'
  72. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%teacher%');
  73. -- 3.3 预览:管家已认证但 roles 中无 butler
  74. SELECT id, nickname, phone, `role`, roles, butler_status
  75. FROM users
  76. WHERE butler_status = 'approved'
  77. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%butler%');
  78. -- 3.4 预览:供应商已审核但 roles 中无 supplier
  79. SELECT id, nickname, phone, `role`, roles, vendor_status
  80. FROM users
  81. WHERE vendor_status = 'approved'
  82. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%supplier%');
  83. -- 3.5 确认后回写 roles(JSON 数组格式;roles 为 NULL/空则新建,已有 JSON 数组则追加)
  84. -- 营养师
  85. UPDATE users
  86. SET roles = CASE
  87. WHEN roles IS NULL OR roles = '' THEN CONCAT('["', `role`, '","nutritionist"]')
  88. WHEN roles LIKE '[%]' THEN REPLACE(roles, ']', ',"nutritionist"]')
  89. ELSE CONCAT(roles, ',nutritionist')
  90. END
  91. WHERE nutritionist_status = 'approved'
  92. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%nutritionist%');
  93. -- 规划师
  94. UPDATE users
  95. SET roles = CASE
  96. WHEN roles IS NULL OR roles = '' THEN CONCAT('["', `role`, '","teacher"]')
  97. WHEN roles LIKE '[%]' THEN REPLACE(roles, ']', ',"teacher"]')
  98. ELSE CONCAT(roles, ',teacher')
  99. END
  100. WHERE teacher_status = 'approved'
  101. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%teacher%');
  102. -- 管家
  103. UPDATE users
  104. SET roles = CASE
  105. WHEN roles IS NULL OR roles = '' THEN CONCAT('["', `role`, '","butler"]')
  106. WHEN roles LIKE '[%]' THEN REPLACE(roles, ']', ',"butler"]')
  107. ELSE CONCAT(roles, ',butler')
  108. END
  109. WHERE butler_status = 'approved'
  110. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%butler%');
  111. -- 供应商(含遗留 vendor 审核通过记录)
  112. UPDATE users
  113. SET roles = CASE
  114. WHEN roles IS NULL OR roles = '' THEN CONCAT('["', `role`, '","supplier"]')
  115. WHEN roles LIKE '[%]' THEN REPLACE(roles, ']', ',"supplier"]')
  116. ELSE CONCAT(roles, ',supplier')
  117. END
  118. WHERE vendor_status = 'approved'
  119. AND (roles IS NULL OR roles = '' OR roles NOT LIKE '%supplier%');
  120. -- ============================================================
  121. -- 执行完成后,受影响的已登录用户需重新登录以获取新 token 中的 roles
  122. -- ============================================================