404 lines
15 KiB
PL/PgSQL
404 lines
15 KiB
PL/PgSQL
-- ============================================
|
||
-- 统一数据库迁移脚本
|
||
-- 将CollisionAvoidanceSystem的空间数据表合并到QAUP-Management数据库
|
||
-- 创建时间: 2025-01-15
|
||
-- 版本: 1.0.0
|
||
-- ============================================
|
||
|
||
-- ============================================
|
||
-- 第一步:启用PostGIS扩展
|
||
-- ============================================
|
||
-- 启用PostGIS扩展(如果尚未启用)
|
||
CREATE EXTENSION IF NOT EXISTS postgis;
|
||
CREATE EXTENSION IF NOT EXISTS postgis_topology;
|
||
|
||
-- 验证PostGIS版本
|
||
SELECT PostGIS_Version();
|
||
|
||
-- ============================================
|
||
-- 第二步:创建更新时间戳函数(如果不存在)
|
||
-- ============================================
|
||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||
RETURN NEW;
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- ============================================
|
||
-- 第三步:创建空间数据核心表
|
||
-- ============================================
|
||
|
||
-- 1. 车辆位置表 (vehicle_locations) - 规范化版本
|
||
-- 只存储位置相关数据,车辆基础信息通过关联sys_vehicle_info表获取
|
||
CREATE TABLE IF NOT EXISTS vehicle_locations (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
|
||
-- 车辆ID(关联sys_vehicle_info.vehicle_id)
|
||
-- 注意:存储数字ID,不是车牌号
|
||
vehicle_id BIGINT NOT NULL,
|
||
|
||
-- PostGIS空间字段 (WGS84坐标系)
|
||
location GEOMETRY(POINT, 4326) NOT NULL,
|
||
|
||
-- 位置相关属性
|
||
altitude DOUBLE PRECISION,
|
||
heading DOUBLE PRECISION CHECK (heading >= 0 AND heading < 360),
|
||
speed DOUBLE PRECISION CHECK (speed >= 0),
|
||
|
||
-- 时间戳
|
||
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
-- 数据质量指标
|
||
data_quality VARCHAR(20),
|
||
|
||
-- 审计字段
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 车辆位置表索引
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_locations_vehicle_id ON vehicle_locations(vehicle_id);
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_locations_timestamp ON vehicle_locations(timestamp DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_locations_location_gist ON vehicle_locations USING GIST(location);
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_locations_compound ON vehicle_locations(vehicle_id, timestamp DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_locations_data_quality ON vehicle_locations(data_quality);
|
||
|
||
-- 2. 机场区域表 (airport_areas)
|
||
CREATE TABLE IF NOT EXISTS airport_areas (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
area_id VARCHAR(50) NOT NULL UNIQUE,
|
||
name VARCHAR(100) NOT NULL,
|
||
type VARCHAR(30) NOT NULL,
|
||
description VARCHAR(500),
|
||
|
||
-- PostGIS空间字段
|
||
boundary GEOMETRY(POLYGON, 4326) NOT NULL,
|
||
|
||
-- 速度和限制
|
||
speed_limit_kph DOUBLE PRECISION,
|
||
restricted BOOLEAN DEFAULT false,
|
||
allowed_vehicle_types JSONB,
|
||
allowed_aircraft_types JSONB,
|
||
max_height DOUBLE PRECISION,
|
||
max_weight DOUBLE PRECISION,
|
||
|
||
-- 时间控制
|
||
active_time TIMESTAMP WITH TIME ZONE,
|
||
expiry_time TIMESTAMP WITH TIME ZONE,
|
||
|
||
-- 区域属性
|
||
enabled BOOLEAN NOT NULL DEFAULT true,
|
||
priority INTEGER NOT NULL DEFAULT 1 CHECK (priority >= 1),
|
||
|
||
-- 版本控制
|
||
version BIGINT NOT NULL DEFAULT 1,
|
||
|
||
-- 审计字段
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 机场区域表索引
|
||
CREATE INDEX IF NOT EXISTS idx_airport_areas_area_id ON airport_areas(area_id);
|
||
CREATE INDEX IF NOT EXISTS idx_airport_areas_type ON airport_areas(type);
|
||
CREATE INDEX IF NOT EXISTS idx_airport_areas_enabled ON airport_areas(enabled);
|
||
CREATE INDEX IF NOT EXISTS idx_airport_areas_boundary_gist ON airport_areas USING GIST(boundary);
|
||
CREATE INDEX IF NOT EXISTS idx_airport_areas_allowed_vehicles_gin ON airport_areas USING GIN(allowed_vehicle_types);
|
||
|
||
-- 3. 车辆轨迹表 (vehicle_trajectories)
|
||
CREATE TABLE IF NOT EXISTS vehicle_trajectories (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
vehicle_id BIGINT NOT NULL,
|
||
trajectory_date DATE NOT NULL,
|
||
|
||
-- PostGIS轨迹线
|
||
trajectory_line GEOMETRY(LINESTRING, 4326),
|
||
|
||
-- 统计信息
|
||
total_distance DOUBLE PRECISION,
|
||
max_speed DOUBLE PRECISION,
|
||
avg_speed DOUBLE PRECISION,
|
||
duration_seconds INTEGER,
|
||
point_count INTEGER,
|
||
|
||
-- 时间范围
|
||
start_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||
end_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||
|
||
-- 审计字段
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 车辆轨迹表索引
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_trajectories_vehicle_id ON vehicle_trajectories(vehicle_id);
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_trajectories_date ON vehicle_trajectories(trajectory_date DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_vehicle_trajectories_line_gist ON vehicle_trajectories USING GIST(trajectory_line);
|
||
|
||
-- ============================================
|
||
-- 第四步:创建规则引擎表
|
||
-- ============================================
|
||
|
||
-- 1. 空间规则表 (spatial_rules)
|
||
CREATE TABLE IF NOT EXISTS spatial_rules (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
rule_id VARCHAR(50) NOT NULL UNIQUE,
|
||
rule_name VARCHAR(100) NOT NULL,
|
||
|
||
-- 规则类型分类
|
||
rule_category VARCHAR(30) NOT NULL CHECK (rule_category IN (
|
||
'ACCESS_CONTROL', 'SPEED_LIMIT', 'VEHICLE_RESTRICTION', 'HEIGHT_LIMIT',
|
||
'WEIGHT_LIMIT', 'TIME_RESTRICTION', 'PRIORITY_CONTROL', 'SAFETY_ZONE', 'CUSTOM'
|
||
)),
|
||
|
||
rule_type VARCHAR(50) NOT NULL,
|
||
|
||
-- 空间对象关联
|
||
spatial_object_type VARCHAR(30) NOT NULL CHECK (spatial_object_type IN (
|
||
'AREA', 'ROAD', 'INTERSECTION', 'CUSTOM_GEOMETRY'
|
||
)),
|
||
spatial_object_id VARCHAR(50),
|
||
custom_geometry GEOMETRY(POLYGON, 4326),
|
||
|
||
-- 规则参数
|
||
rule_parameters JSONB NOT NULL DEFAULT '{}',
|
||
applicable_vehicle_types JSONB DEFAULT '[]',
|
||
applicable_aircraft_types JSONB DEFAULT '[]',
|
||
|
||
-- 告警配置
|
||
alert_level VARCHAR(20) NOT NULL DEFAULT 'WARNING' CHECK (alert_level IN (
|
||
'INFO', 'WARNING', 'CRITICAL', 'EMERGENCY'
|
||
)),
|
||
alert_message VARCHAR(500),
|
||
response_actions JSONB DEFAULT '[]',
|
||
|
||
-- 规则状态
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' CHECK (status IN (
|
||
'ACTIVE', 'INACTIVE', 'SUSPENDED', 'EXPIRED'
|
||
)),
|
||
|
||
-- 时间控制
|
||
effective_from TIMESTAMP WITH TIME ZONE,
|
||
effective_until TIMESTAMP WITH TIME ZONE,
|
||
time_patterns JSONB DEFAULT '[]',
|
||
|
||
-- 优先级
|
||
priority INTEGER NOT NULL DEFAULT 1 CHECK (priority >= 1),
|
||
version BIGINT NOT NULL DEFAULT 1,
|
||
|
||
-- 审计字段
|
||
created_by VARCHAR(50),
|
||
updated_by VARCHAR(50),
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 空间规则表索引
|
||
CREATE INDEX IF NOT EXISTS idx_spatial_rules_rule_id ON spatial_rules(rule_id);
|
||
CREATE INDEX IF NOT EXISTS idx_spatial_rules_category ON spatial_rules(rule_category);
|
||
CREATE INDEX IF NOT EXISTS idx_spatial_rules_status ON spatial_rules(status);
|
||
CREATE INDEX IF NOT EXISTS idx_spatial_rules_custom_geometry_gist ON spatial_rules USING GIST(custom_geometry);
|
||
CREATE INDEX IF NOT EXISTS idx_spatial_rules_parameters_gin ON spatial_rules USING GIN(rule_parameters);
|
||
|
||
-- 2. 规则违反事件表 (rule_violation_events)
|
||
CREATE TABLE IF NOT EXISTS rule_violation_events (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
event_id VARCHAR(50) NOT NULL UNIQUE,
|
||
|
||
-- 关联规则
|
||
rule_id VARCHAR(50) NOT NULL,
|
||
|
||
-- 违规主体
|
||
subject_type VARCHAR(20) NOT NULL CHECK (subject_type IN ('VEHICLE', 'AIRCRAFT')),
|
||
subject_id VARCHAR(50) NOT NULL,
|
||
|
||
-- 违规详情
|
||
violation_type VARCHAR(50) NOT NULL,
|
||
violation_details JSONB NOT NULL DEFAULT '{}',
|
||
|
||
-- 位置信息
|
||
location GEOMETRY(POINT, 4326) NOT NULL,
|
||
spatial_context VARCHAR(100),
|
||
|
||
-- 违规数据
|
||
actual_value JSONB,
|
||
threshold_value JSONB,
|
||
|
||
-- 严重程度
|
||
severity VARCHAR(20) NOT NULL CHECK (severity IN ('LOW', 'MEDIUM', 'HIGH', 'CRITICAL')),
|
||
|
||
-- 响应状态
|
||
response_status VARCHAR(20) NOT NULL DEFAULT 'PENDING' CHECK (response_status IN (
|
||
'PENDING', 'ACKNOWLEDGED', 'IN_PROGRESS', 'RESOLVED', 'IGNORED'
|
||
)),
|
||
|
||
-- 响应动作记录
|
||
response_actions_taken JSONB DEFAULT '[]',
|
||
response_details JSONB DEFAULT '{}',
|
||
|
||
-- 时间信息
|
||
detected_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
acknowledged_at TIMESTAMP WITH TIME ZONE,
|
||
resolved_at TIMESTAMP WITH TIME ZONE,
|
||
|
||
-- 审计字段
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 规则违反事件表索引
|
||
CREATE INDEX IF NOT EXISTS idx_rule_violations_rule_id ON rule_violation_events(rule_id);
|
||
CREATE INDEX IF NOT EXISTS idx_rule_violations_subject ON rule_violation_events(subject_type, subject_id);
|
||
CREATE INDEX IF NOT EXISTS idx_rule_violations_severity ON rule_violation_events(severity);
|
||
CREATE INDEX IF NOT EXISTS idx_rule_violations_status ON rule_violation_events(response_status);
|
||
CREATE INDEX IF NOT EXISTS idx_rule_violations_detected_at ON rule_violation_events(detected_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_rule_violations_location_gist ON rule_violation_events USING GIST(location);
|
||
|
||
-- ============================================
|
||
-- 第五步:创建业务关联视图
|
||
-- ============================================
|
||
|
||
-- 车辆完整信息视图(基础信息 + 最新位置)- 规范化版本
|
||
CREATE OR REPLACE 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 OR REPLACE VIEW vehicle_status_summary AS
|
||
SELECT
|
||
COUNT(*) as total_vehicles,
|
||
COUNT(CASE WHEN last_location_time > NOW() - INTERVAL '5 minutes' THEN 1 END) as active_vehicles,
|
||
COUNT(CASE WHEN last_location_time > NOW() - INTERVAL '30 minutes' AND last_location_time <= NOW() - INTERVAL '5 minutes' THEN 1 END) as inactive_vehicles,
|
||
COUNT(CASE WHEN last_location_time IS NULL OR last_location_time <= NOW() - INTERVAL '30 minutes' THEN 1 END) as offline_vehicles,
|
||
AVG(speed) as avg_speed,
|
||
MAX(speed) as max_speed
|
||
FROM vehicle_complete_info;
|
||
|
||
-- ============================================
|
||
-- 第六步:创建触发器
|
||
-- ============================================
|
||
|
||
-- 为新表创建自动更新时间戳的触发器
|
||
CREATE TRIGGER trigger_vehicle_locations_updated_at
|
||
BEFORE UPDATE ON vehicle_locations
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION update_updated_at_column();
|
||
|
||
CREATE TRIGGER trigger_airport_areas_updated_at
|
||
BEFORE UPDATE ON airport_areas
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION update_updated_at_column();
|
||
|
||
CREATE TRIGGER trigger_spatial_rules_updated_at
|
||
BEFORE UPDATE ON spatial_rules
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION update_updated_at_column();
|
||
|
||
-- ============================================
|
||
-- 第七步:添加表注释
|
||
-- ============================================
|
||
|
||
-- 添加表和视图注释
|
||
COMMENT ON TABLE vehicle_locations IS '车辆位置信息表(规范化版本)- 只存储位置相关数据,车辆基础信息通过关联sys_vehicle_info表获取';
|
||
COMMENT ON COLUMN vehicle_locations.vehicle_id IS '车辆ID,关联sys_vehicle_info.vehicle_id(数字主键)';
|
||
COMMENT ON VIEW vehicle_complete_info IS '车辆完整信息视图 - 包含基础信息和最新位置,通过vehicle_id关联';
|
||
|
||
-- ============================================
|
||
-- 第八步:添加外键约束(可选)
|
||
-- ============================================
|
||
|
||
-- 外键约束:确保vehicle_id在sys_vehicle_info表中存在
|
||
-- 注意:只有在确保数据完整性的情况下才启用
|
||
-- ALTER TABLE vehicle_locations
|
||
-- ADD CONSTRAINT fk_vehicle_locations_vehicle_id
|
||
-- FOREIGN KEY (vehicle_id) REFERENCES sys_vehicle_info(vehicle_id)
|
||
-- ON DELETE CASCADE ON UPDATE CASCADE;
|
||
|
||
-- ============================================
|
||
-- 第八步:插入示例配置数据
|
||
-- ============================================
|
||
|
||
-- 插入默认机场区域(示例)
|
||
INSERT INTO airport_areas (area_id, name, type, description, boundary, enabled) VALUES
|
||
('RUNWAY_01', '跑道01区域', 'RUNWAY', '主跑道区域',
|
||
ST_GeomFromText('POLYGON((116.3 39.9, 116.31 39.9, 116.31 39.91, 116.3 39.91, 116.3 39.9))', 4326),
|
||
true)
|
||
ON CONFLICT (area_id) DO NOTHING;
|
||
|
||
-- 插入默认安全规则(示例)
|
||
INSERT INTO spatial_rules (rule_id, rule_name, rule_category, rule_type, spatial_object_type, spatial_object_id,
|
||
rule_parameters, alert_level, status) VALUES
|
||
('SPEED_LIMIT_RUNWAY', '跑道限速规则', 'SPEED_LIMIT', 'MAX_SPEED', 'AREA', 'RUNWAY_01',
|
||
'{"max_speed_kph": 30}', 'WARNING', 'ACTIVE')
|
||
ON CONFLICT (rule_id) DO NOTHING;
|
||
|
||
-- ============================================
|
||
-- 验证脚本执行结果
|
||
-- ============================================
|
||
|
||
-- 检查PostGIS扩展
|
||
SELECT name, default_version, installed_version
|
||
FROM pg_available_extensions
|
||
WHERE name IN ('postgis', 'postgis_topology');
|
||
|
||
-- 检查新创建的表
|
||
SELECT schemaname, tablename, tableowner
|
||
FROM pg_tables
|
||
WHERE tablename IN (
|
||
'vehicle_locations', 'airport_areas', 'vehicle_trajectories',
|
||
'spatial_rules', 'rule_violation_events'
|
||
)
|
||
ORDER BY tablename;
|
||
|
||
-- 检查空间索引
|
||
SELECT schemaname, tablename, indexname, indexdef
|
||
FROM pg_indexes
|
||
WHERE indexname LIKE '%gist%'
|
||
AND tablename IN ('vehicle_locations', 'airport_areas', 'vehicle_trajectories', 'spatial_rules', 'rule_violation_events')
|
||
ORDER BY tablename, indexname;
|
||
|
||
-- 检查视图
|
||
SELECT schemaname, viewname, viewowner
|
||
FROM pg_views
|
||
WHERE viewname IN ('vehicle_complete_info', 'vehicle_status_summary')
|
||
ORDER BY viewname;
|
||
|
||
-- ============================================
|
||
-- 迁移完成提示
|
||
-- ============================================
|
||
|
||
DO $$
|
||
BEGIN
|
||
RAISE NOTICE '==============================================';
|
||
RAISE NOTICE '数据库迁移完成!';
|
||
RAISE NOTICE '已成功合并CollisionAvoidanceSystem的空间数据表到QAUP-Management数据库';
|
||
RAISE NOTICE '新增表:vehicle_locations, airport_areas, vehicle_trajectories, spatial_rules, rule_violation_events';
|
||
RAISE NOTICE '新增视图:vehicle_complete_info, vehicle_status_summary';
|
||
RAISE NOTICE '已启用PostGIS扩展支持空间数据操作';
|
||
RAISE NOTICE '==============================================';
|
||
END $$; |