migration_early_warning_columns.sql 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. -- ============================================================================
  2. -- 预警表(app_user.early_warning)列补齐 / 类型归一
  3. --
  4. -- 背景
  5. -- 排水「设备运行实时监测」页发布预警时插入失败,报:
  6. -- ERROR: 关系 "early_warning" 的 "warning_name" 字段不存在
  7. -- 实体 DrainageWarning.equipmentName 原先映射到 warning_name,
  8. -- 而早期建表脚本(sql/early_warning_system.sql)里设备名称列是 device_name。
  9. -- 实体已改为 device_name;本脚本负责把历史库的列形态补齐/统一。
  10. --
  11. -- 覆盖三种情况
  12. -- 1) 有 device_name → 跳过
  13. -- 2) 只有 warning_name → 新增 device_name,并把数据搬过去
  14. -- 3) 两者都没有(异常库) → 新增 device_name
  15. -- 并把 warning_level 由字符型统一为 integer(实体、查询、前端均为整数)。
  16. --
  17. -- 注意:不给 early_warning 加坐标列。坐标只在查询时从设备档案补齐后返回前端,
  18. -- 属于展示派生字段,落库会让预警历史随设备改动而失真。
  19. --
  20. -- 幂等:可重复执行,已到位的环境只会输出 NOTICE,不做任何改动。
  21. -- ============================================================================
  22. -- 首句独立 ROLLBACK:清掉上次失败执行残留的 aborted 事务,
  23. -- 否则重跑只会得到「当前事务被终止,事务块结束之前的查询被忽略」
  24. ROLLBACK;
  25. BEGIN;
  26. SET search_path TO app_user, public;
  27. -- ----------------------------------------------------------------------------
  28. -- 1. device_name:实体 DrainageWarning.equipmentName 的映射列
  29. -- ----------------------------------------------------------------------------
  30. DO $$
  31. DECLARE
  32. has_device_name boolean;
  33. has_warning_name boolean;
  34. BEGIN
  35. SELECT EXISTS (
  36. SELECT 1 FROM information_schema.columns
  37. WHERE table_schema = 'app_user' AND table_name = 'early_warning' AND column_name = 'device_name'
  38. ) INTO has_device_name;
  39. SELECT EXISTS (
  40. SELECT 1 FROM information_schema.columns
  41. WHERE table_schema = 'app_user' AND table_name = 'early_warning' AND column_name = 'warning_name'
  42. ) INTO has_warning_name;
  43. IF has_device_name THEN
  44. RAISE NOTICE 'early_warning.device_name 已存在,跳过';
  45. ELSE
  46. ALTER TABLE app_user.early_warning ADD COLUMN device_name varchar(256);
  47. IF has_warning_name THEN
  48. EXECUTE 'UPDATE app_user.early_warning SET device_name = warning_name WHERE device_name IS NULL';
  49. RAISE NOTICE '已新增 device_name,并把 warning_name 的数据搬迁过来';
  50. ELSE
  51. RAISE NOTICE '已新增 device_name(库中原本没有设备名称列)';
  52. END IF;
  53. END IF;
  54. END $$;
  55. COMMENT ON COLUMN app_user.early_warning.device_name IS '关联设备名称';
  56. -- ----------------------------------------------------------------------------
  57. -- 2. warning_level:字符型统一为 integer
  58. -- 实体字段是 Integer、查询条件也是整数;character varying 列在 KES 下
  59. -- 既可能插入报类型不符,也可能让 warning_level = 1 的等值查询走不到索引。
  60. -- 非数字历史值(如误填的中文)统一归一为 1,避免转换失败中断脚本。
  61. -- ----------------------------------------------------------------------------
  62. DO $$
  63. DECLARE
  64. v_type text;
  65. BEGIN
  66. SELECT data_type INTO v_type
  67. FROM information_schema.columns
  68. WHERE table_schema = 'app_user' AND table_name = 'early_warning' AND column_name = 'warning_level';
  69. IF v_type IS NULL THEN
  70. RAISE NOTICE 'early_warning.warning_level 不存在,跳过';
  71. ELSIF v_type IN ('integer', 'smallint', 'bigint', 'numeric', 'decimal') THEN
  72. RAISE NOTICE 'early_warning.warning_level 已是数值类型(%),跳过', v_type;
  73. ELSE
  74. ALTER TABLE app_user.early_warning ALTER COLUMN warning_level DROP DEFAULT;
  75. ALTER TABLE app_user.early_warning
  76. ALTER COLUMN warning_level TYPE integer
  77. USING (CASE WHEN trim(warning_level) ~ '^[0-9]+$' THEN trim(warning_level)::integer ELSE 1 END);
  78. RAISE NOTICE 'early_warning.warning_level 已由 % 转为 integer(非数字历史值已归一为 1)', v_type;
  79. END IF;
  80. END $$;
  81. COMMENT ON COLUMN app_user.early_warning.warning_level IS '预警级别(1严重 2重要 3一般 4常态)';
  82. -- ----------------------------------------------------------------------------
  83. -- 3. psgw_warning_scope_user:指定人员发布时的接收人列表
  84. -- 排水预警(DrainageWarningServiceImpl.publishWarning)在 publish_scope=3 时写入该表,
  85. -- 早期环境可能没有建表,导致「指定人员」发布直接失败。
  86. -- ----------------------------------------------------------------------------
  87. CREATE TABLE IF NOT EXISTS app_user.psgw_warning_scope_user (
  88. id varchar(64) NOT NULL,
  89. warning_id varchar(64),
  90. user_id bigint,
  91. user_name varchar(128),
  92. approved integer DEFAULT 0,
  93. approve_time timestamp,
  94. create_time timestamp,
  95. PRIMARY KEY (id)
  96. );
  97. CREATE INDEX IF NOT EXISTS idx_psgw_warning_scope_user_warning ON app_user.psgw_warning_scope_user (warning_id);
  98. COMMENT ON TABLE app_user.psgw_warning_scope_user IS '排水预警接收人员';
  99. -- ----------------------------------------------------------------------------
  100. -- 4. 旧版实体遗留列:current_value / threshold / unit / warning_time
  101. -- 这些列曾经被旧版 DrainageWarning 写入,现已被实体标为不落库。
  102. -- 若历史环境把它们建成了 NOT NULL 且无默认值,新代码不写就会触发非空约束,
  103. -- 这里统一放开非空限制(列本身保留,历史数据不动)。
  104. -- ----------------------------------------------------------------------------
  105. DO $$
  106. DECLARE
  107. col_name text;
  108. exists_col boolean;
  109. BEGIN
  110. FOREACH col_name IN ARRAY ARRAY['current_value', 'threshold', 'unit', 'warning_time'] LOOP
  111. SELECT EXISTS (
  112. SELECT 1 FROM information_schema.columns
  113. WHERE table_schema = 'app_user' AND table_name = 'early_warning' AND column_name = col_name
  114. ) INTO exists_col;
  115. IF exists_col THEN
  116. EXECUTE format('ALTER TABLE app_user.early_warning ALTER COLUMN %I DROP NOT NULL', col_name);
  117. RAISE NOTICE 'early_warning.% 已改为可空(该列不再由程序写入)', col_name;
  118. END IF;
  119. END LOOP;
  120. END $$;
  121. COMMIT;
  122. -- ----------------------------------------------------------------------------
  123. -- 核验(可选,取消注释后单独执行)
  124. -- ----------------------------------------------------------------------------
  125. -- SELECT column_name, data_type, is_nullable
  126. -- FROM information_schema.columns
  127. -- WHERE table_schema = 'app_user' AND table_name = 'early_warning'
  128. -- AND column_name IN ('device_name','warning_name','warning_level')
  129. -- ORDER BY column_name;