# 车辆ID映射问题解决方案 ## 问题描述 在数据库合并过程中发现了车辆标识符不一致的问题: - **QAUP-Management**: `sys_vehicle_info.vehicle_id` = 自增数字ID(主键) - **CollisionAvoidanceSystem**: `vehicle_locations.vehicle_id` = 车牌号(字符串) 这导致两个系统的车辆数据无法正确关联。 ## 解决方案对比 ### 🥇 方案一:优化表结构(推荐) **特点**: - ✅ 保持数据完整性 - ✅ 支持双重关联方式 - ✅ 语义清晰,便于维护 - ⚠️ 需要修改表结构 **实施**: ```bash # 执行修复脚本 psql -h localhost -U postgres -d qaup -f sql/fix_vehicle_id_mapping.sql ``` **优势**: - 添加`license_plate`字段明确语义 - 添加`sys_vehicle_id`字段支持数字ID关联 - 更新所有相关视图使用正确的关联逻辑 - 提供数据同步函数 ### 🥈 方案二:视图层解决(简单) **特点**: - ✅ 不修改表结构 - ✅ 实施简单快速 - ⚠️ 依赖视图查询,性能稍逊 - ⚠️ 需要确保车牌号唯一性 **关联逻辑**: ```sql -- 通过车牌号关联 SELECT vi.*, vl.location, vl.speed FROM sys_vehicle_info vi LEFT JOIN vehicle_locations vl ON vl.vehicle_id = vi.license_plate_number; ``` ### 🥉 方案三:应用层处理(灵活) **特点**: - ✅ 数据库保持原样 - ✅ 灵活的映射逻辑 - ⚠️ 增加应用复杂性 - ⚠️ 性能开销相对较大 **实现方式**: - 在应用层维护车牌号到数字ID的映射关系 - 通过缓存提高查询性能 ## 推荐方案详解 ### 方案一实施后的效果 #### 1. 表结构变化 ```sql -- vehicle_locations表新增字段 ALTER TABLE vehicle_locations ADD COLUMN license_plate VARCHAR(50); -- 车牌号 ALTER TABLE vehicle_locations ADD COLUMN sys_vehicle_id BIGINT; -- 系统车辆ID ``` #### 2. 数据关联方式 ```sql -- 方式1:通过车牌号关联(主要方式) SELECT * FROM vehicle_complete_info WHERE license_plate_number = '京A12345'; -- 方式2:通过数字ID关联(可选) SELECT * FROM sys_vehicle_info vi JOIN vehicle_locations vl ON vl.sys_vehicle_id = vi.vehicle_id; ``` #### 3. 新增业务视图 **vehicle_info_with_location**:车辆信息与位置 ```sql SELECT sys_vehicle_id, vehicle_plate, brand, longitude, latitude, status FROM vehicle_info_with_location WHERE vehicle_plate = '京A12345'; ``` **vehicle_trajectory_view**:车辆轨迹 ```sql SELECT vehicle_plate, trajectory_date, total_distance FROM vehicle_trajectory_view WHERE vehicle_plate = '京A12345'; ``` ## 执行步骤 ### 立即执行(推荐) 1. **备份数据**(重要) ```bash pg_dump -h localhost -U postgres -d qaup > backup_before_fix_$(date +%Y%m%d_%H%M%S).sql ``` 2. **执行修复脚本** ```bash psql -h localhost -U postgres -d qaup -f sql/fix_vehicle_id_mapping.sql ``` 3. **验证结果** ```sql -- 检查新字段 \d vehicle_locations -- 测试视图 SELECT * FROM vehicle_complete_info LIMIT 5; -- 检查数据同步 SELECT COUNT(*) as total, COUNT(license_plate) as has_plate FROM vehicle_locations; ``` ### 如果选择其他方案 #### 方案二:仅更新视图 ```sql -- 只更新现有视图的关联逻辑 DROP VIEW IF EXISTS vehicle_complete_info; CREATE OR REPLACE VIEW vehicle_complete_info AS SELECT vi.*, vl.location, vl.speed, vl.timestamp FROM sys_vehicle_info vi LEFT JOIN LATERAL ( SELECT * FROM vehicle_locations WHERE vehicle_id = vi.license_plate_number ORDER BY timestamp DESC LIMIT 1 ) vl ON true; ``` #### 方案三:应用层映射 ```java // 在应用代码中处理映射 @Service public class VehicleMappingService { public String getPlateById(Long vehicleId) { // 从sys_vehicle_info查询车牌号 } public Long getIdByPlate(String licensePlate) { // 从sys_vehicle_info查询车辆ID } } ``` ## 使用建议 ### 开发中的最佳实践 1. **统一使用车牌号作为业务标识符** ```sql -- 推荐:使用车牌号查询 SELECT * FROM vehicle_info_with_location WHERE vehicle_plate = '京A12345'; ``` 2. **数据插入时同时设置两个字段** ```sql INSERT INTO vehicle_locations (vehicle_id, license_plate, sys_vehicle_id, ...) VALUES ('京A12345', '京A12345', 1001, ...); ``` 3. **定期执行数据同步** ```sql -- 如果有新的车辆信息录入,执行同步 SELECT update_sys_vehicle_id(); ``` ### 查询性能优化 ```sql -- 利用新建的索引 CREATE INDEX idx_vehicle_locations_license_plate ON vehicle_locations(license_plate); CREATE INDEX idx_vehicle_locations_sys_vehicle_id ON vehicle_locations(sys_vehicle_id); ``` ## 常见问题解答 ### Q1: 为什么推荐方案一? - **数据完整性**:支持严格的外键约束 - **查询性能**:专用索引优化 - **语义清晰**:字段名明确表达用途 - **向后兼容**:保留原有的vehicle_id字段 ### Q2: 原有代码需要修改吗? - **CollisionAvoidanceSystem**:不需要修改,继续使用vehicle_id字段 - **QAUP-Management**:建议使用新的视图进行查询 - **新功能开发**:推荐使用license_plate字段 ### Q3: 如果车牌号有重复怎么办? - 在sys_vehicle_info表上添加唯一约束: ```sql ALTER TABLE sys_vehicle_info ADD CONSTRAINT uk_license_plate UNIQUE (license_plate_number); ``` ### Q4: 数据迁移会丢失吗? - 不会,脚本使用ADD COLUMN IF NOT EXISTS确保安全 - 现有数据会自动复制到新字段 - 建议执行前先备份 ## 总结 推荐立即执行**方案一**的修复脚本,这将: - ✅ 彻底解决车辆ID映射问题 - ✅ 提供多种查询方式 - ✅ 保持系统兼容性 - ✅ 优化查询性能 执行命令: ```bash psql -h localhost -U postgres -d qaup -f sql/fix_vehicle_id_mapping.sql ```