延迟约束和完整的表级数据结构。

线性网络约束

从一个简单的道路网络开始。

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系列课程之空间约束(三)相关推荐

  1. 大型企业网络配置系列课程详解(三)--OSPF高级配置与相关概念的理解

    大型企业网络配置系列课程详解(三)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office&qu ...

  2. PostGIS系列课程之高级空间联合

    更多更复杂的联合查询 在本节中,我们将对一般的空间查询做一些更复杂的事情. 创建一张人口普查表 我们已经在数据库中创建了一个名为nyc_census_sociodata的表. 该表包括有关纽约的有趣的 ...

  3. 银行从业中级系列课程之——银行管理(三)市场准入、非现场监管和现场检查

    银行管理中级大纲 第三讲 市场准入.非现场监管和现场检查 现场检查与市场准入.非现场监管共同构成了银行业监管的 "三驾马车 " 考点1 市场准入 风险监管的第一关 行政许可实施程序 ...

  4. Mysql系列课程--第三章 建表 插数据

    数据库模型图 /班级表/ CREATE TABLE `class` (`c_no` int(11) NOT NULL AUTO_INCREMENT,`c_name` varchar(45) NOT N ...

  5. mysql建立学号与课程编号的索引_数据库mysql 四约束 三范式 六索引

    mysql 四约束 三范式 六索引 1.MySQL 约束 1.约束的作用 分类 表列的primary key主键,unique唯一键,not null非空等修饰符常常被称作约束(constraint) ...

  6. arcgis 快速制图插件_51GIS学院|ArcGIS空间数据分析系列课程的27个视频

    51GIS学院 课程背景 迎接科学分析与国土空间规划,迅速掌握ArcGIS基础操作并进阶实战,推出本次ArcGIS空间数据分析系列课程.系列课程一,为ArcGIS基础与制图,课程目标为掌握ArcGIS ...

  7. 【假期重磅福利】更新三个Oracle系列课程,共153课时,最低免费获取

    恩墨课程内测阶段共有630人参与我们的限时优惠活动,目前活动仍在继续,1元即可获得每周更新的<2019云和恩墨大讲堂>,以及<Oracle 12C 高手之路>课程,欢迎大家下载 ...

  8. 活动回顾 |《从 SRE 到 Anthos, 三堂课详解 DevOps 工具与实践》系列课程

    在不久前结束的 Google Cloud 线上课堂中,我们用三节线上课程,由浅入深地讲解了 DevOps 中最重要的工程实现--SRE 系统可靠性工程(Site Reliability Enginee ...

  9. 吴恩达deeplearning.ai系列课程笔记+编程作业(15)序列模型(Sequence Models)-第三周 序列模型和注意力机制

    第五门课 序列模型(Sequence Models) 第三周 序列模型和注意力机制(Sequence models & Attention mechanism) 文章目录 第五门课 序列模型( ...

最新文章

  1. Flask-RESTful的简单使用
  2. 使用特异性特征提取网络辅助分类任务
  3. MySQL学习之路:多实例无法启动排错
  4. InnerHTML、InnerText、outerHTML、outerText的区别
  5. 关于Android的一些设计【转】
  6. 【Linux】GCC程序开发工具(上)
  7. SSDT-BI之七:循环任务(容器)
  8. CCS的一些问题(转帖)
  9. Python元组、数组、列表的区别
  10. 巨坑:从Sqoop导入MySQL导入TINYINT(1)类型数据到hive(tinyint),数据为null
  11. Spring Boot 集成 JUnit5,优雅单元测试!
  12. 特征选择与特征提取(降维)
  13. 基于ansys命令流的水池静力学分析
  14. ENVI大气校正后遥感图像颜色变了及编辑头文件
  15. 新浪邮箱开通imap服务器,新浪邮箱申请
  16. cobalt strick 4.0 系列教程 (5)--- 获取立足点
  17. Mint-UI时间组件起始时间问题
  18. macos 中先安装了pyqt5再安装opencv出现的QtCore冲突问题
  19. MCAD/MCSD课程选择对比
  20. bootstrap 精美_基于Bootstrap 4和Vuejs构建的精美资源

热门文章

  1. SQL 提取数字并转换为数字格式
  2. 笔记本电脑wifi连接网络不能上网有感叹号
  3. linux gic驱动
  4. GIC/ITS代码分析(0)GIC/ITS框架介绍
  5. Python爬虫编程实践--task01
  6. C++-计算体质指数BMI值 信息学奥赛
  7. 关于主机的思维导图_关于开展思维导图培训的通知
  8. 【flutter】type ‘Null‘ is not a subtype of type ‘bool‘
  9. 魅族 linux驱动下载,魅族Meizu MX Flyme手机驱动官方正式版下载,适用于手机系统-驱动精灵...
  10. excel填充遇到的坑