QAUP_Management/sql/data_model_unification.sql
Tian jianyong 5e1e9f4507 统一了前后端到一个项目,实现了无人车的位置和超速检测,并发送到前端。
管理端在 Ruoyi 框架的基础上,对菜单进行了修改,并添加了司机信息、车辆信息和车辆类型管理。
2025-07-08 20:04:14 +08:00

441 lines
15 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- ============================================
-- 数据模型统一重构脚本
-- 目标统一vehicle_id为数字IDlicense_plate为车牌号
-- 创建时间2025-01-15
-- 执行模式方案B - 完全统一数据模型
-- ============================================
-- 开始事务
BEGIN;
-- 设置错误处理
\set ON_ERROR_STOP on
-- ============================================
-- 第一阶段:数据结构准备
-- ============================================
-- 创建车辆ID映射表临时
CREATE TABLE IF NOT EXISTS vehicle_id_mapping (
license_plate VARCHAR(50) PRIMARY KEY,
old_vehicle_id VARCHAR(50),
new_vehicle_id BIGINT
);
-- 填充映射表数据
INSERT INTO vehicle_id_mapping (license_plate, old_vehicle_id, new_vehicle_id)
SELECT
license_plate_number as license_plate,
NULL as old_vehicle_id,
vehicle_id as new_vehicle_id
FROM sys_vehicle_info
ON CONFLICT (license_plate) DO NOTHING;
-- 从CollisionAvoidanceSystem表中获取现有车牌号
INSERT INTO vehicle_id_mapping (license_plate, old_vehicle_id, new_vehicle_id)
SELECT DISTINCT
vehicle_id as license_plate,
vehicle_id as old_vehicle_id,
NULL::BIGINT as new_vehicle_id
FROM vehicle_locations
WHERE vehicle_id NOT IN (SELECT license_plate FROM vehicle_id_mapping)
ON CONFLICT (license_plate) DO NOTHING;
-- 为新车牌号分配数字ID
DO $$
DECLARE
max_id BIGINT;
rec RECORD;
BEGIN
-- 获取当前最大车辆ID
SELECT COALESCE(MAX(vehicle_id), 0) INTO max_id FROM sys_vehicle_info;
-- 为没有数字ID的车牌号分配新ID
FOR rec IN
SELECT license_plate FROM vehicle_id_mapping
WHERE new_vehicle_id IS NULL
ORDER BY license_plate
LOOP
max_id := max_id + 1;
UPDATE vehicle_id_mapping
SET new_vehicle_id = max_id
WHERE license_plate = rec.license_plate;
END LOOP;
END $$;
-- ============================================
-- 第二阶段QAUP-Management表结构变更
-- ============================================
-- 1. 重命名sys_vehicle_info表中的字段
ALTER TABLE sys_vehicle_info RENAME COLUMN license_plate_number TO license_plate;
-- 2. 为新车牌号添加车辆记录
INSERT INTO sys_vehicle_info (
vehicle_id, license_plate, vin_number, type_id, brand,
owning_unit, contact_person, phone_number, image_url,
create_by, create_time, update_by, update_time, remark
)
SELECT
vim.new_vehicle_id,
vim.license_plate,
'AUTO_' || vim.license_plate as vin_number,
1 as type_id, -- 默认类型,需要根据实际情况调整
'未知' as brand,
'自动导入' as owning_unit,
'系统' as contact_person,
'' as phone_number,
'' as image_url,
'system' as create_by,
NOW() as create_time,
'system' as update_by,
NOW() as update_time,
'数据模型统一时自动创建' as remark
FROM vehicle_id_mapping vim
WHERE vim.new_vehicle_id NOT IN (SELECT vehicle_id FROM sys_vehicle_info)
AND vim.old_vehicle_id IS NOT NULL;
-- ============================================
-- 第三阶段CollisionAvoidanceSystem表结构变更
-- ============================================
-- 1. 处理vehicle_locations表
-- 添加新字段
ALTER TABLE vehicle_locations ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE vehicle_locations ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;
-- 填充新字段数据
UPDATE vehicle_locations vl
SET
license_plate = vl.vehicle_id,
vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE vl.vehicle_id = vim.license_plate;
-- 2. 处理vehicle_trajectories表
-- 添加新字段
ALTER TABLE vehicle_trajectories ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE vehicle_trajectories ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;
-- 填充新字段数据
UPDATE vehicle_trajectories vt
SET
license_plate = vt.vehicle_id,
vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE vt.vehicle_id = vim.license_plate;
-- 3. 处理vehicle_commands表
-- 添加新字段
ALTER TABLE vehicle_commands ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE vehicle_commands ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;
-- 填充新字段数据
UPDATE vehicle_commands vc
SET
license_plate = vc.vehicle_id,
vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE vc.vehicle_id = vim.license_plate;
-- 4. 处理rule_violation_events表
-- 添加新字段
ALTER TABLE rule_violation_events ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE rule_violation_events ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;
-- 填充新字段数据(只处理车辆类型的事件)
UPDATE rule_violation_events rve
SET
license_plate = rve.subject_id,
vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE rve.subject_id = vim.license_plate
AND rve.subject_type = 'VEHICLE';
-- ============================================
-- 第四阶段:数据完整性验证
-- ============================================
-- 验证数据完整性
DO $$
DECLARE
missing_data_count INTEGER;
total_records INTEGER;
BEGIN
-- 检查vehicle_locations表
SELECT COUNT(*) INTO missing_data_count
FROM vehicle_locations
WHERE license_plate IS NULL OR vehicle_id_new IS NULL;
SELECT COUNT(*) INTO total_records FROM vehicle_locations;
IF missing_data_count > 0 THEN
RAISE EXCEPTION 'vehicle_locations表数据迁移不完整: %/%', missing_data_count, total_records;
END IF;
-- 检查vehicle_trajectories表
SELECT COUNT(*) INTO missing_data_count
FROM vehicle_trajectories
WHERE license_plate IS NULL OR vehicle_id_new IS NULL;
SELECT COUNT(*) INTO total_records FROM vehicle_trajectories;
IF missing_data_count > 0 THEN
RAISE EXCEPTION 'vehicle_trajectories表数据迁移不完整: %/%', missing_data_count, total_records;
END IF;
-- 检查vehicle_commands表
SELECT COUNT(*) INTO missing_data_count
FROM vehicle_commands
WHERE license_plate IS NULL OR vehicle_id_new IS NULL;
SELECT COUNT(*) INTO total_records FROM vehicle_commands;
IF missing_data_count > 0 THEN
RAISE EXCEPTION 'vehicle_commands表数据迁移不完整: %/%', missing_data_count, total_records;
END IF;
RAISE NOTICE '数据完整性验证通过!';
END $$;
-- ============================================
-- 第五阶段:结构清理和字段重命名
-- ============================================
-- 1. 删除旧字段,重命名新字段 - vehicle_locations
ALTER TABLE vehicle_locations DROP COLUMN vehicle_id;
ALTER TABLE vehicle_locations RENAME COLUMN vehicle_id_new TO vehicle_id;
-- 2. 删除旧字段,重命名新字段 - vehicle_trajectories
ALTER TABLE vehicle_trajectories DROP COLUMN vehicle_id;
ALTER TABLE vehicle_trajectories RENAME COLUMN vehicle_id_new TO vehicle_id;
-- 3. 删除旧字段,重命名新字段 - vehicle_commands
ALTER TABLE vehicle_commands DROP COLUMN vehicle_id;
ALTER TABLE vehicle_commands RENAME COLUMN vehicle_id_new TO vehicle_id;
-- 4. 删除旧字段,重命名新字段 - rule_violation_events
-- 注意这里需要谨慎处理因为subject_id可能不只是车辆ID
ALTER TABLE rule_violation_events ADD COLUMN IF NOT EXISTS subject_id_new VARCHAR(50);
UPDATE rule_violation_events SET subject_id_new =
CASE
WHEN subject_type = 'VEHICLE' THEN vehicle_id_new::VARCHAR
ELSE subject_id
END;
ALTER TABLE rule_violation_events DROP COLUMN subject_id;
ALTER TABLE rule_violation_events RENAME COLUMN subject_id_new TO subject_id;
-- ============================================
-- 第六阶段:重建索引和约束
-- ============================================
-- 1. vehicle_locations表索引
DROP INDEX IF EXISTS idx_vehicle_locations_vehicle_id;
DROP INDEX IF EXISTS idx_vehicle_locations_license_plate;
CREATE INDEX idx_vehicle_locations_vehicle_id ON vehicle_locations(vehicle_id);
CREATE INDEX idx_vehicle_locations_license_plate ON vehicle_locations(license_plate);
-- 2. vehicle_trajectories表索引
DROP INDEX IF EXISTS idx_vehicle_trajectories_vehicle_id;
DROP INDEX IF EXISTS idx_vehicle_trajectories_license_plate;
CREATE INDEX idx_vehicle_trajectories_vehicle_id ON vehicle_trajectories(vehicle_id);
CREATE INDEX idx_vehicle_trajectories_license_plate ON vehicle_trajectories(license_plate);
-- 3. vehicle_commands表索引
DROP INDEX IF EXISTS idx_vehicle_commands_vehicle_id;
DROP INDEX IF EXISTS idx_vehicle_commands_license_plate;
CREATE INDEX idx_vehicle_commands_vehicle_id ON vehicle_commands(vehicle_id);
CREATE INDEX idx_vehicle_commands_license_plate ON vehicle_commands(license_plate);
-- 4. rule_violation_events表索引
DROP INDEX IF EXISTS idx_rule_violations_license_plate;
CREATE INDEX idx_rule_violations_license_plate ON rule_violation_events(license_plate) WHERE subject_type = 'VEHICLE';
-- ============================================
-- 第七阶段:添加外键约束
-- ============================================
-- 添加外键约束(可选,根据需要启用)
-- ALTER TABLE vehicle_locations ADD CONSTRAINT fk_vehicle_locations_vehicle_id
-- FOREIGN KEY (vehicle_id) REFERENCES sys_vehicle_info(vehicle_id);
-- ALTER TABLE vehicle_trajectories ADD CONSTRAINT fk_vehicle_trajectories_vehicle_id
-- FOREIGN KEY (vehicle_id) REFERENCES sys_vehicle_info(vehicle_id);
-- ALTER TABLE vehicle_commands ADD CONSTRAINT fk_vehicle_commands_vehicle_id
-- FOREIGN KEY (vehicle_id) REFERENCES sys_vehicle_info(vehicle_id);
-- ============================================
-- 第八阶段:更新业务视图
-- ============================================
-- 删除旧视图
DROP VIEW IF EXISTS vehicle_complete_info;
DROP VIEW IF EXISTS vehicle_status_summary;
DROP VIEW IF EXISTS vehicle_info_with_location;
DROP VIEW IF EXISTS vehicle_trajectory_view;
-- 重新创建统一的业务视图
CREATE VIEW vehicle_complete_info AS
SELECT
vi.vehicle_id,
vi.license_plate,
vi.vin_number,
vi.type_id,
vt.type_name,
vi.brand,
vi.owning_unit,
vi.contact_person,
vi.phone_number,
vi.image_url,
vl.location,
vl.altitude,
vl.heading,
vl.speed,
vl.timestamp as last_location_time,
vl.data_quality,
vi.create_time,
vi.update_time
FROM sys_vehicle_info vi
LEFT JOIN sys_vehicle_type vt ON vi.type_id = vt.type_id
LEFT JOIN LATERAL (
SELECT * FROM vehicle_locations
WHERE vehicle_id = vi.vehicle_id
ORDER BY timestamp DESC
LIMIT 1
) vl ON true;
-- 车辆状态统计视图
CREATE VIEW vehicle_status_summary AS
SELECT
vehicle_type,
COUNT(*) as total_vehicles,
COUNT(CASE WHEN timestamp > NOW() - INTERVAL '5 minutes' THEN 1 END) as active_vehicles,
COUNT(CASE WHEN timestamp <= NOW() - INTERVAL '5 minutes' THEN 1 END) as inactive_vehicles,
AVG(speed) as avg_speed,
MAX(speed) as max_speed
FROM vehicle_locations vl
WHERE timestamp > NOW() - INTERVAL '24 hours'
GROUP BY vehicle_type;
-- 车辆信息与位置关联视图
CREATE VIEW vehicle_info_with_location AS
SELECT
vi.vehicle_id,
vi.license_plate,
vi.brand,
vi.owning_unit,
vt.type_name as vehicle_type_name,
vl.vehicle_type as location_vehicle_type,
vl.location,
ST_X(vl.location) as longitude,
ST_Y(vl.location) as latitude,
vl.altitude,
vl.heading,
vl.speed,
vl.timestamp as last_update_time,
CASE
WHEN vl.timestamp > NOW() - INTERVAL '5 minutes' THEN 'ACTIVE'
WHEN vl.timestamp > NOW() - INTERVAL '30 minutes' THEN 'INACTIVE'
ELSE 'OFFLINE'
END as status
FROM sys_vehicle_info vi
LEFT JOIN sys_vehicle_type vt ON vi.type_id = vt.type_id
LEFT JOIN LATERAL (
SELECT * FROM vehicle_locations
WHERE vehicle_id = vi.vehicle_id
ORDER BY timestamp DESC
LIMIT 1
) vl ON true;
-- 车辆轨迹查询视图
CREATE VIEW vehicle_trajectory_view AS
SELECT
vi.vehicle_id,
vi.license_plate,
vi.brand,
vt.trajectory_date,
vt.trajectory_line,
vt.total_distance,
vt.max_speed,
vt.avg_speed,
vt.duration_seconds,
vt.start_time,
vt.end_time
FROM sys_vehicle_info vi
INNER JOIN vehicle_trajectories vt ON vt.vehicle_id = vi.vehicle_id
LEFT JOIN sys_vehicle_type vtype ON vi.type_id = vtype.type_id;
-- ============================================
-- 第九阶段:添加字段注释
-- ============================================
-- sys_vehicle_info表字段注释
COMMENT ON COLUMN sys_vehicle_info.license_plate IS '车牌号(统一字段名)';
-- vehicle_locations表字段注释
COMMENT ON COLUMN vehicle_locations.vehicle_id IS '车辆ID数字主键关联sys_vehicle_info.vehicle_id';
COMMENT ON COLUMN vehicle_locations.license_plate IS '车牌号(业务标识符)';
-- vehicle_trajectories表字段注释
COMMENT ON COLUMN vehicle_trajectories.vehicle_id IS '车辆ID数字主键关联sys_vehicle_info.vehicle_id';
COMMENT ON COLUMN vehicle_trajectories.license_plate IS '车牌号(业务标识符)';
-- vehicle_commands表字段注释
COMMENT ON COLUMN vehicle_commands.vehicle_id IS '车辆ID数字主键关联sys_vehicle_info.vehicle_id';
COMMENT ON COLUMN vehicle_commands.license_plate IS '车牌号(业务标识符)';
-- rule_violation_events表字段注释
COMMENT ON COLUMN rule_violation_events.license_plate IS '车牌号仅当subject_type为VEHICLE时有效';
-- ============================================
-- 第十阶段:清理临时数据
-- ============================================
-- 删除临时映射表
DROP TABLE IF EXISTS vehicle_id_mapping;
-- ============================================
-- 最终验证
-- ============================================
DO $$
DECLARE
qaup_count INTEGER;
locations_count INTEGER;
trajectories_count INTEGER;
commands_count INTEGER;
violations_count INTEGER;
BEGIN
-- 统计各表记录数
SELECT COUNT(*) INTO qaup_count FROM sys_vehicle_info;
SELECT COUNT(*) INTO locations_count FROM vehicle_locations;
SELECT COUNT(*) INTO trajectories_count FROM vehicle_trajectories;
SELECT COUNT(*) INTO commands_count FROM vehicle_commands;
SELECT COUNT(*) INTO violations_count FROM rule_violation_events WHERE subject_type = 'VEHICLE';
-- 输出统计信息
RAISE NOTICE '==============================================';
RAISE NOTICE '数据模型统一重构完成!';
RAISE NOTICE '==============================================';
RAISE NOTICE '车辆信息记录: %', qaup_count;
RAISE NOTICE '位置记录: %', locations_count;
RAISE NOTICE '轨迹记录: %', trajectories_count;
RAISE NOTICE '指令记录: %', commands_count;
RAISE NOTICE '违规事件记录: %', violations_count;
RAISE NOTICE '==============================================';
RAISE NOTICE '主要改进:';
RAISE NOTICE '1. 统一vehicle_id为数字主键';
RAISE NOTICE '2. 统一license_plate为车牌号字段名';
RAISE NOTICE '3. 消除所有字段名不一致';
RAISE NOTICE '4. 重建了所有业务视图';
RAISE NOTICE '5. 优化了索引结构';
RAISE NOTICE '==============================================';
END $$;
-- 提交事务
COMMIT;
-- 显示完成消息
\echo '数据模型统一重构脚本执行完成!'
\echo '请验证数据完整性和功能正常性。'