-- PostGIS 数据库初始化脚本 -- 创建精河县供水管理系统GIS相关表结构 -- 启用PostGIS扩展 CREATE EXTENSION IF NOT EXISTS postgis; CREATE EXTENSION IF NOT EXISTS postgis_topology; -- 创建空间索引 CREATE EXTENSION IF NOT EXISTS btree_gist; -- 创建GIS基础图层表 CREATE TABLE IF NOT EXISTS gis_base_map ( id BIGSERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, type VARCHAR(50) NOT NULL, description TEXT, is_active BOOLEAN DEFAULT true, order_index INTEGER DEFAULT 0, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- 创建索引 CREATE INDEX idx_gis_base_map_name ON gis_base_map(name); CREATE INDEX idx_gis_base_map_type ON gis_base_map(type); CREATE INDEX idx_gis_base_map_active ON gis_base_map(is_active); -- 创建IoT设备表 CREATE TABLE IF NOT EXISTS iot_device ( id BIGSERIAL PRIMARY KEY, device_code VARCHAR(50) UNIQUE NOT NULL, name VARCHAR(100) NOT NULL, device_type VARCHAR(20) NOT NULL, longitude DECIMAL(10, 8), latitude DECIMAL(11, 8), location_geom GEOMETRY(Point, 4326), gis_layer_name VARCHAR(50) NOT NULL, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- 创建空间索引 CREATE INDEX idx_iot_device_geom ON iot_device USING GIST(location_geom); CREATE INDEX idx_iot_device_code ON iot_device(device_code); CREATE INDEX idx_iot_device_active ON iot_device(is_active); CREATE INDEX idx_iot_device_layer ON iot_device(gis_layer_name); -- 插入默认数据 -- GIS基础图层数据 INSERT INTO gis_base_map (name, type, description, order_index) VALUES ('精河县基础底图', 'county', '精河县行政区划边界图', 1), ('管网数据', 'pipe_network', '供水管网矢量数据', 2), ('监测点位', 'monitoring_points', '水质、水压、流量监测点', 3) ON CONFLICT (name) DO NOTHING; -- 模拟IoT设备数据 INSERT INTO iot_device (device_code, name, device_type, longitude, latitude, gis_layer_name, is_active) VALUES ('SW001', '1号水位监测点', 'SW', 44.0321, 82.8973, 'water_level', true), ('SW002', '2号水位监测点', 'SW', 44.0365, 82.9058, 'water_level', true), ('SW003', '3号水位监测点', 'SW', 44.0410, 82.9110, 'water_level', true), ('YL001', '1号压力监测点', 'YL', 44.0289, 82.8925, 'water_pressure', true), ('YL002', '2号压力监测点', 'YL', 44.0356, 82.9018, 'water_pressure', true), ('YL003', '3号压力监测点', 'YL', 44.0432, 82.9153, 'water_pressure', true), ('LL001', '1号流量监测点', 'LL', 44.0301, 82.8987, 'water_flow', true), ('LL002', '2号流量监测点', 'LL', 44.0378, 82.9074, 'water_flow', true), ('WQ001', '1号水质监测点', 'WQ', 44.0345, 82.9021, 'water_quality', true), ('WQ002', '2号水质监测点', 'WQ', 44.0421, 82.9128, 'water_quality', true) ON CONFLICT (device_code) DO NOTHING; -- 更新设备的空间地理信息 UPDATE iot_device SET location_geom = ST_MakePoint(longitude, latitude) WHERE location_geom IS NULL AND longitude IS NOT NULL AND latitude IS NOT NULL; -- 创建视图:按图层类型分组的设备 CREATE OR REPLACE VIEW v_iot_devices_by_layer AS SELECT gis_layer_name, device_type, COUNT(*) as device_count, array_agg(device_code) as device_codes, array_agg(name) as device_names FROM iot_device WHERE is_active = true GROUP BY gis_layer_name, device_type; -- 创建视图:GIS图层统计 CREATE OR REPLACE VIEW v_gis_layers_stats AS SELECT gbm.name as layer_name, gbm.type as layer_type, gbm.description, id.device_count, CASE WHEN gbm.type = 'county' THEN '行政区划' WHEN gbm.type = 'pipe_network' THEN '管网数据' WHEN gbm.type = 'monitoring_points' THEN '监测点位' ELSE '其他' END as layer_category FROM gis_base_map gbm LEFT JOIN ( SELECT gis_layer_name, COUNT(*) as device_count FROM iot_device WHERE is_active = true GROUP BY gis_layer_name ) id ON gbm.name = id.gis_layer_name WHERE gbm.is_active = true; -- 创建触发器函数:自动更新updated_at字段 CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ language 'plpgsql'; -- 为相关表添加触发器 CREATE TRIGGER update_gis_base_map_updated_at BEFORE UPDATE ON gis_base_map FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_iot_device_updated_at BEFORE UPDATE ON iot_device FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- 授权(根据实际用户名调整) -- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO water_user; -- GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO water_user;