PostgreSQL-修改扩展中的创建表语法

PostgreSQL-修改扩展中的创建表语法,sql,postgresql,postgis,postgresql-9.1,ddl,Sql,Postgresql,Postgis,Postgresql 9.1,Ddl,是否可以编写修改DDL语法的PostgreSQL扩展 我正在PostgreSQL和PostGIS之上创建一个扩展,以支持特定空间数据模型(OMT-G)的完整性约束。为此,我想修改CREATE TABLE语法,它使用以下语法接受约束S: CONSTRAINT constraint_name CHECK ( expression ) 但是我想创建自己的语法,就像下面的示例中的语法一样,然后调用我已经编写的函数或触发器 CREATE TABLE school_district ( id

是否可以编写修改DDL语法的PostgreSQL扩展

我正在PostgreSQL和PostGIS之上创建一个扩展,以支持特定空间数据模型(OMT-G)的完整性约束。为此,我想修改
CREATE TABLE
语法,它使用以下语法接受
约束
S:

CONSTRAINT constraint_name CHECK ( expression )
但是我想创建自己的语法,就像下面的示例中的语法一样,然后调用我已经编写的函数或触发器

CREATE TABLE school_district (
      id integer PRIMARY KEY,
      school_name varchar(120)
      geom geometry,

      SPATIAL_CONSTRAINT PLANAR_SUBDIVISION (geom),
      SPATIAL_CONSTRAINT CONTAINS school (geom)**
);

可能吗?如果是,怎么做?

正如其他人评论的那样,不可能通过扩展来改变Postgres语法。在黑客的邮件列表上有一些与此相关的讨论,但是没有人认为有任何可行的方法可以使Bison语法可扩展

您提出的另一个问题是,检查约束(看起来就是您在这里尝试执行的操作)无法安全地引用其他表

听起来您真正想要的是可扩展外键支持。这是社区实际上也希望看到的,至少对于阵列是这样。其思想是支持类似int[]的内容,其中每个元素都应被视为对另一个表的外键引用。您所描述的是类似的:您希望使用不同的运算符,而不是不同的数据类型

但就目前而言,我认为您能做的最好的事情是为用户提供一个函数,该函数将在表上放置一个适当的列和触发器。该列将是school表的外键。触发器将找到一个合适的学校,并在新列中填充它的主键。(您可能还需要school表上的BEFORE DELETE触发器来处理删除学校的操作。)


之所以需要外键字段,是因为外键触发器使用与普通查询不同的可见性规则进行操作,因此无法在用户空间中完全模拟它们。如果你不是那么偏执,你可以使用一个后插入触发器来查找学校,如果找不到,就会抛出一个错误。

对于任何纯DDL解决方案,最有希望的方法是使用,它在一个表上操作GiST,并且只有相对有限的运算符只在边界框上工作(例如&&&):

但是,这种冲突(即使几何体实际上没有重叠):

错误:冲突的键值违反排除约束“polygons\u geom\u excl” 详细信息:密钥(geom)=(0103000020E610000000000000500000000000000000000000000000000000F03F000000000000000000F03F000000000000004000000000000000400000000000000040000000004000000000000000400000000000000040000000000000000000000F03F000000000000F03F)与现有密钥(geom)冲突=(0103000020E610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000000000000000)


正如@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);

这样,如果您编辑
学区
学校
表,触发器将触发对
更新
插入
、或
删除
的检查,以查看条件是否仍然有效。

不,这是不可能的。但如果您想提供一个真实的示例,说明您真正想要实现的目标,则可能会有这不是其他的解决方案。只要使用
检查
语法就可以了。这应该可以实现你想要的。@Patrick,这实际上就是我想要实现的。添加一些语法糖,让空间开发人员更容易使用。例如,上面截取的第二个约束将证明,对于表中添加的每个新学区,都有一个学校(桌上学校)在它的边界内必须存在。@GordonLinoff,但我们的想法是为这个空间数据模型创建一个扩展。因此,最好只为它使用上面这样的语法。而且约束有点复杂,有很多函数,因此如果可能的话,这将简化使用。这仍然是不可能的。如果您想扩展syntax您必须修改源代码并直接用C编写功能。这可能不是一个非常可行的想法……如果您有许多重复的约束,并希望简化这些约束,请查看Tks@Jim。事实上,由于数据是空间的,因此不是外键。两个表之间的关系可能只是空间关系。(检查一个元素在地理上是否在另一个元素的边界内),没有外键。但是谢谢。我会想另一种方法来简化这些约束的使用。
INSERT INTO polygons(geom)
VALUES('SRID=4326;POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))');
RAISE EXCEPTION 'School % is not located in school district % (it is % away)',
                s.name, d.name, ST_Distance(s.geom, d.geom);