就纯DDL解决方案而言,最有前途的方法是使用
CREATE TABLE ... CONSTRAINT ... EXCLUDE
,它在单个表上运行GiST,并且只有相对有限的运算符仅适用于边界框(例如&&)。
CREATE TABLE polygons (
geom geometry(Polygon,4326),
EXCLUDE USING gist (geom WITH &&)
);
INSERT INTO polygons(geom)
VALUES('SRID=4326;POLYGON ((0 0, 0 1, 1 0, 0 0))');
但是,这会产生冲突(即使几何图形实际上并没有重叠):
INSERT INTO polygons(geom)
VALUES('SRID=4326;POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))');
错误:冲突的键值违反了排除约束“polygons_geom_excl”
详细信息:键(geom)=(0103000020E61000000100000005000000000000000000F03F000000000000F03F000000000000F03F0000000000000040000000000000004000000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F)与现有键(geom)=(0103000020E61000000100000004000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000)冲突。
![enter image description here](https://istack.dev59.com/03MQR.webp)
如@Jim所述,构建一个表的约束条件时最好的方法是创建一个好的
触发器函数,并在两个表上使用它。通常应该用PL/pgSQL编写它,您可以嵌入有用的消息,例如:
RAISE EXCEPTION 'School % is not located in school district % (it is % away)',
s.name, d.name, ST_Distance(s.geom, d.geom);
这样,如果您编辑了
school_district
或
schools
表中的任何一个,触发器将在
UPDATE
、
INSERT
或
DELETE
时进行检查,以确定条件是否仍然有效。
CHECK
语法即可。这样就可以实现您想要的功能。 - Gordon Linoff