【问题标题】:(PostgreSQL) "Advanced" Check Constraint Question(PostgreSQL)“高级”检查约束问题
【发布时间】:2011-07-09 17:57:40
【问题描述】:

我使用 PostgreSQL,但我正在寻找尽可能标准的 SQL 答案。

我有下表“文档”--

    Column  |          Type          | Modifiers              
------------+------------------------+--------------------
 id         | character varying(32)  | not null
 version    | integer                | not null default 1
 link_id    | character varying(32)  | 
 content    | character varying(128) | 
Indexes:
    "docs_pkey" PRIMARY KEY, btree (id, version)

id 和link_id 是针对相互之间有链接关系的文档,所以link_id 是自引用id。

问题与版本有关。现在 id 不再是主键(也不会是唯一的)并且不能被 link_id 作为外键引用 --

my_db=# ALTER TABLE docs ADD FOREIGN KEY(link_id) REFERENCES docs (id) ; 
ERROR:  there is no unique constraint matching given keys for referenced table "docs"

我试图搜索“如果存在”之类的检查约束,但没有找到任何东西。

任何提示将不胜感激。

【问题讨论】:

    标签: database postgresql foreign-keys constraints database-schema


    【解决方案1】:

    我通常是这样的:

    table document (id, common, columns, current_revision)
    table revision (id, doc_id, content, version)
    

    这意味着该文档与其修订版具有一对多关系,并且与当前修订版具有一对一关系。

    这样,您始终可以通过简单的连接为当前修订选择一个完整的文档,并且您的文档表中只有一个唯一的行,您可以在其中链接父/子关系,但仍然具有版本控制。

    【讨论】:

      【解决方案2】:

      尽可能贴近您的模型,您可以将表格分成两份,一份每个“文档”有 1 行,一个每个“版本”有 1 行:

      您有下表“版本”--

          Column  |          Type          | Modifiers              
      ------------+------------------------+--------------------
       id         | character varying(32)  | not null
       version    | integer                | not null default 1
       content    | character varying(128) | 
      Indexes:
          "versions_pkey" PRIMARY KEY, btree (id, version)
      

      以及下表“文档”--

          Column  |          Type          | Modifiers              
      ------------+------------------------+--------------------
       id         | character varying(32)  | not null
       link_id    | character varying(32)  | 
      Indexes:
          "docs_pkey" PRIMARY KEY, btree (id)
      

      现在

      my_db=# ALTER TABLE docs ADD FOREIGN KEY(link_id) REFERENCES docs (id) ; 
      

      是允许的,你也想要:

      my_db=# ALTER TABLE versions ADD FOREIGN KEY(id) REFERENCES docs; 
      

      当然,没有什么可以阻止您获得类似于原始表格的“组合”视图:

      CREATE VIEW v_docs AS
      SELECT id, version, link_id, content from docs join versions using(id);
      

      【讨论】:

      • 谢谢,我想接受你的回答,却发现 SO 有每个问题只能接受一个答案的限制。由于我更倾向于 jishi 的答案(仅仅是因为它更接近我的应用程序设计),所以我只能投赞成票。很抱歉。
      • @jishi 的回答很好 - 我很高兴你接受了它。您可能需要了解 deferrable 约束才能按照他建议的方式实施它
      【解决方案3】:

      根据您的需要,您可以简单地创建一个包含版本字段的 FOREIGN KEY。这是指向唯一行的唯一方法...

      如果这不起作用,您可以编写一个触发器(用于表上的所有 UPDATE 和 INSERT)来进行检查。请注意,您还需要在 docs 表上使用触发器,以限制对该表的修改会破坏键(例如键值本身的 DELETE 或 UPDATE)。

      您不能对 CHECK 约束执行此操作,因为 CHECK 约束不能访问另一个表中的数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-19
        • 2013-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多