PostGIS系列课程之空间约束(三)
延迟约束和完整的表级数据结构。
线性网络约束
从一个简单的道路网络开始。
CREATE TABLE roads (pk bigint PRIMARY KEY,name text NOT NULL,geom geometry(LineString, 3005) NOT NULLCONSTRAINT geom_no_zero_length CHECK (ST_Length(geom) > 0)CONSTRAINT geom_no_self_intersection CHECK (ST_IsSimple(geom))
);
检查约束
我们在表定义中添加了几个简单的检查约束:
- 我们希望路段的长度不为零; 和,
- 我们希望我们的路段没有自动交叉路口,变得“简单”。
毫无疑问,PostgreSQL可以轻松管理这些约束。
INSERT INTO roads VALUES (0, 'Main', 'LINESTRING(0 0, 0 0)');
------------------------------
ERROR: new row for relation "roads" violates check constraint "geom_no_zero_length"
DETAIL: Failing row contains (0, Main,0102000020BD0B00000200000000000000000000000000000000000000000000...).
-----------------------------
INSERT INTO roads VALUES (1, 'Elm', 'LINESTRING(0 0, 5 5, 5 3, 0 5)');
-----------------------------
ERROR: new row for relation "roads" violates check constraint "geom_no_self_intersection"
DETAIL: Failing row contains (1, Elm,0102000020BD0B00000400000000000000000000000000000000000000000000...).
触发器约束
但是,大多数空间用户想要对线性网络数据实施的真正限制是连通性。 特别是在以下情况下,他们会喜欢它:
- 它们的网络是“节点”的,因此每个段都在另一个段的起点或终点处结束,而不是在一个段的中间。
- 他们的网络是“连接的”,因此每个其他网段都可以访问每个网段。
这两个条件不仅需要了解要插入的段,还需要超越 CHECK
约束来触发。
CREATE OR REPLACE FUNCTION noded_road_trigger()RETURNS trigger AS$$DECLAREc bigint;BEGIN-- How many roads does the end point of this -- road touch at the ends? Touches is not true-- when end points touch middles.SELECT Count(*)INTO cFROM roadsWHERE ST_Touches(roads.geom, NEW.geom);-- Have to touch at least one other segment in-- the network.IF c < 1 THENRAISE EXCEPTION 'road % is not connected to the network', NEW.pk;END IF;RETURN NEW;END;$$LANGUAGE 'plpgsql';-- Run for data additions and changes,
-- and allow deferal to end of transaction.
CREATE CONSTRAINT TRIGGER noded_road AFTER INSERT OR UPDATE ON roads DEFERRABLEFOR EACH ROW EXECUTE FUNCTION noded_road_trigger();
从一个小的种子网络开始,如下所示:
INSERT INTO roads VALUES (2, 'Grand', 'LINESTRING(0 0, 2 2)');
INSERT INTO roads VALUES (3, 'Grand', 'LINESTRING(2 2, 4 2)');
INSERT INTO roads VALUES (4, 'Oak', 'LINESTRING(0 2, 2 2)');
向网络添加两个新的细分:
INSERT INTO roads VALUES (5, 'Larch', 'LINESTRING(4 0, 6 0)');
-----------------------------
ERROR: road 5 is not connected to the network
CONTEXT: PL/pgSQL function noded_road_trigger() line 13 at RAISE
-----------------------------
INSERT INTO roads VALUES (6, 'Oak', 'LINESTRING(2 2, 4 0)');
-----------------------------
INSERT 0 1
这虽然有趣的。一个失败了,另一个成功了,为什么?因为当它们都需要连接的时候, “Oak” 段 需要在插入"Larch" 段之前插入到表中才能判断它们连接有效↓。
延缓约束
为了判断连接性,必须同时将这两个部分都放在适当的位置。 也许如果将它们放在事务块中,情况会好一些吗?
-- 删除数据进行新的测试
DELETE FROM roads WHERE pk = 6;
-- Does using a transaction block work?
BEGIN;INSERT INTO roads VALUES (5, 'Larch', 'LINESTRING(4 0, 6 0)');INSERT INTO roads VALUES (6, 'Oak', 'LINESTRING(2 2, 4 0)');
COMMIT;
不行?!
ERROR: road 5 is not connected to the network
CONTEXT: PL/pgSQL function noded_road_trigger() line 13 at RAISE
但是,当创建此约束触发器时,我们将其标记为 DEFERRABLE
。 如果我们可以让数据库等到所有记录都加载后再检查约束,那么我们的插入语句就可以了。
延迟约束校验,使用 SET CONSTRAINTS 命令(在事物块开始前)。
BEGIN;
SET CONSTRAINTS noded_road DEFERRED;
INSERT INTO roads VALUES (5, 'Larch', 'LINESTRING(4 0, 6 0)');
INSERT INTO roads VALUES (6, 'Oak', 'LINESTRING(2 2, 4 0)');
COMMIT;
成功! 因此,我们可以确保连接线。
强制约束
但是我们还能确保连通性吗? 如果每个网段都必须连接到另一个网段,则看起来是这样,但是实际上断开连接很容易:只需在一个延迟的事务中插入一组自连接的网段即可。
BEGIN;
SET CONSTRAINTS noded_road DEFERRED;
-- These aren't connected, do they fail on commit?
INSERT INTO roads VALUES (7, 'Sea', 'LINESTRING(6 1, 6 2)');
INSERT INTO roads VALUES (8, 'Isle', 'LINESTRING(6 2, 5 2)');
-- They do not! :(
COMMIT;
-- Clean up.
DELETE FROM roads WHERE pk IN (7, 8);
哦不,这很容易在表中插入单独的节点段的孤“岛”。 我们需要一个新的约束来检查所有段是否全局连接在一起。
表范围约束
我们已经使用``noded_road_trigger()` 保证了节点相连,因此我们只需要确保所有节点段都形成一个图,就可以使用 空间聚类 ,且公差为零。
CREATE OR REPLACE FUNCTION single_network_trigger()RETURNS trigger AS$$DECLAREc bigint;BEGIN-- All the segments are noded (touching)-- so clustering with zero distance will find-- all connected clusters.WITH clusters AS (SELECT ST_ClusterDBScan(geom, 0.0, 1) over () AS clusterFROM roads)SELECT Count(DISTINCT cluster)INTO cFROM clusters;-- If there's more than one cluster, we have-- separate islands in graph, and that's a no-no.IF c > 1 THENRAISE EXCEPTION 'network is not fully connected';END IF;RETURN NEW;END;$$LANGUAGE 'plpgsql';CREATE CONSTRAINT TRIGGER single_network AFTER INSERT OR UPDATE ON roads DEFERRABLEFOR EACH ROW EXECUTE FUNCTION single_network_trigger();
现在,当尝试批量插入节点但未连接的线组时,系统捕获到异常了!
BEGIN;
-- 延迟约束起作用了
SET CONSTRAINTS ALL DEFERRED;
-- These aren't connected, do they fail on commit?
INSERT INTO roads VALUES (7, 'Sea', 'LINESTRING(6 1, 6 2)');
INSERT INTO roads VALUES (8, 'Isle', 'LINESTRING(6 2, 5 2)');
-- They do!
COMMIT;
-----------------------------
ERROR: network is not fully connected
CONTEXT: PL/pgSQL function single_network_trigger() line 15 at RAISE
这种方法的缺点很明显:对于较大的表,在每次数据更新时检查群集的成本将对性能造成影响。 但是,对于成千上万条记录中的较小表,它应该可以正常工作。
排除约束?
排除约束 由于PostGIS空间算子的实现方式,它对PostGIS并不是很有用。
排除约束严格限于执行使用索引运算符定义的条件,不幸的是,PostGIS运算符都使用“边界框逻辑”而不是“几何逻辑”。 例如:
SELECT 'LINESTRING(0 0 10 10)'::geometry && 'POINT(5 4)';
返回 TRUE , 因为它测试线串的边界框和点的边界框是否相交。
排除约束条件“仅允许不与现有几何图形相交的新几何图形”可能有用。 但是无法使用PostGIS && 运算符来实现。
PostGIS系列课程之空间约束(三)相关推荐
- 大型企业网络配置系列课程详解(三)--OSPF高级配置与相关概念的理解
大型企业网络配置系列课程详解(三)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office&qu ...
- PostGIS系列课程之高级空间联合
更多更复杂的联合查询 在本节中,我们将对一般的空间查询做一些更复杂的事情. 创建一张人口普查表 我们已经在数据库中创建了一个名为nyc_census_sociodata的表. 该表包括有关纽约的有趣的 ...
- 银行从业中级系列课程之——银行管理(三)市场准入、非现场监管和现场检查
银行管理中级大纲 第三讲 市场准入.非现场监管和现场检查 现场检查与市场准入.非现场监管共同构成了银行业监管的 "三驾马车 " 考点1 市场准入 风险监管的第一关 行政许可实施程序 ...
- Mysql系列课程--第三章 建表 插数据
数据库模型图 /班级表/ CREATE TABLE `class` (`c_no` int(11) NOT NULL AUTO_INCREMENT,`c_name` varchar(45) NOT N ...
- mysql建立学号与课程编号的索引_数据库mysql 四约束 三范式 六索引
mysql 四约束 三范式 六索引 1.MySQL 约束 1.约束的作用 分类 表列的primary key主键,unique唯一键,not null非空等修饰符常常被称作约束(constraint) ...
- arcgis 快速制图插件_51GIS学院|ArcGIS空间数据分析系列课程的27个视频
51GIS学院 课程背景 迎接科学分析与国土空间规划,迅速掌握ArcGIS基础操作并进阶实战,推出本次ArcGIS空间数据分析系列课程.系列课程一,为ArcGIS基础与制图,课程目标为掌握ArcGIS ...
- 【假期重磅福利】更新三个Oracle系列课程,共153课时,最低免费获取
恩墨课程内测阶段共有630人参与我们的限时优惠活动,目前活动仍在继续,1元即可获得每周更新的<2019云和恩墨大讲堂>,以及<Oracle 12C 高手之路>课程,欢迎大家下载 ...
- 活动回顾 |《从 SRE 到 Anthos, 三堂课详解 DevOps 工具与实践》系列课程
在不久前结束的 Google Cloud 线上课堂中,我们用三节线上课程,由浅入深地讲解了 DevOps 中最重要的工程实现--SRE 系统可靠性工程(Site Reliability Enginee ...
- 吴恩达deeplearning.ai系列课程笔记+编程作业(15)序列模型(Sequence Models)-第三周 序列模型和注意力机制
第五门课 序列模型(Sequence Models) 第三周 序列模型和注意力机制(Sequence models & Attention mechanism) 文章目录 第五门课 序列模型( ...
最新文章
- Flask-RESTful的简单使用
- 使用特异性特征提取网络辅助分类任务
- MySQL学习之路:多实例无法启动排错
- InnerHTML、InnerText、outerHTML、outerText的区别
- 关于Android的一些设计【转】
- 【Linux】GCC程序开发工具(上)
- SSDT-BI之七:循环任务(容器)
- CCS的一些问题(转帖)
- Python元组、数组、列表的区别
- 巨坑:从Sqoop导入MySQL导入TINYINT(1)类型数据到hive(tinyint),数据为null
- Spring Boot 集成 JUnit5,优雅单元测试!
- 特征选择与特征提取(降维)
- 基于ansys命令流的水池静力学分析
- ENVI大气校正后遥感图像颜色变了及编辑头文件
- 新浪邮箱开通imap服务器,新浪邮箱申请
- cobalt strick 4.0 系列教程 (5)--- 获取立足点
- Mint-UI时间组件起始时间问题
- macos 中先安装了pyqt5再安装opencv出现的QtCore冲突问题
- MCAD/MCSD课程选择对比
- bootstrap 精美_基于Bootstrap 4和Vuejs构建的精美资源
热门文章
- SQL 提取数字并转换为数字格式
- 笔记本电脑wifi连接网络不能上网有感叹号
- linux gic驱动
- GIC/ITS代码分析(0)GIC/ITS框架介绍
- Python爬虫编程实践--task01
- C++-计算体质指数BMI值 信息学奥赛
- 关于主机的思维导图_关于开展思维导图培训的通知
- 【flutter】type ‘Null‘ is not a subtype of type ‘bool‘
- 魅族 linux驱动下载,魅族Meizu MX Flyme手机驱动官方正式版下载,适用于手机系统-驱动精灵...
- excel填充遇到的坑