AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 17853
Accepted
ypercubeᵀᴹ
ypercubeᵀᴹ
Asked: 2012-05-15 15:02:25 +0800 CST2012-05-15 15:02:25 +0800 CST 2012-05-15 15:02:25 +0800 CST

是否有允许引用视图(而不仅仅是基表)的外键的 DBMS?

  • 772

受到 Django 建模问题的启发:Database Modeling with multiple many-to-many Relations in Django。db-design 类似于:

CREATE TABLE Book
( BookID INT NOT NULL
, BookTitle VARCHAR(200) NOT NULL
, PRIMARY KEY (BookID)
) ;

CREATE TABLE Tag
( TagID INT NOT NULL
, TagName VARCHAR(50) NOT NULL
, PRIMARY KEY (TagID)
) ;

CREATE TABLE BookTag
( BookID INT NOT NULL
, TagID INT NOT NULL
, PRIMARY KEY (BookID, TagID)
, FOREIGN KEY (BookID)  REFERENCES Book (BookID)
, FOREIGN KEY (TagID)   REFERENCES Tag (TagID)
) ;

CREATE TABLE Aspect
( AspectID INT NOT NULL
, AspectName VARCHAR(50) NOT NULL
, PRIMARY KEY (AspectID)
) ;

CREATE TABLE TagAspect
( TagID INT NOT NULL
, AspectID INT NOT NULL
, PRIMARY KEY (TagID, AspectID) 
, FOREIGN KEY (TagID)   REFERENCES Tag (TagID)
, FOREIGN KEY (AspectID)  REFERENCES Aspect (AspectID)
) ;

数据库图

问题是如何定义BookAspectRating表并强制执行参照完整性,因此不能(Book, Aspect)为无效的组合添加评级。

AFAIK,涉及子查询和多个表的复杂CHECK约束(或)可能解决此问题,但在任何 DBMS 中均不可用。ASSERTIONS

另一个想法是使用(伪代码)视图:

CREATE VIEW BookAspect_view
  AS
SELECT DISTINCT
    bt.BookId
  , ta.AspectId
FROM 
    BookTag AS bt
  JOIN 
    Tag AS t  ON t.TagID = bt.TagID
  JOIN 
    TagAspect AS ta  ON ta.TagID = bt.TagID 
WITH PRIMARY KEY (BookId, AspectId) ;

以及具有上述视图的外键的表:

CREATE TABLE BookAspectRating
( BookID INT NOT NULL
, AspectID INT NOT NULL
, PersonID INT NOT NULL
, Rating INT NOT NULL
, PRIMARY KEY (BookID, AspectID, PersonID)
, FOREIGN KEY (PersonID)   REFERENCES Person (PersonID)
, FOREIGN KEY (BookID, AspectID) 
    REFERENCES BookAspect_view (BookID, AspectID)
) ;

三个问题:

  • 是否有允许(可能物化)VIEW带有 a 的DBMS PRIMARY KEY?

  • 是否有允许 a FOREIGN KEYthat REFERENCESa VIEW(而不仅仅是 base TABLE)的 DBMS?

  • 是否可以通过其他方式解决这个完整性问题 - 使用可用的 DBMS 功能?


澄清:

因为可能没有 100% 令人满意的解决方案 - Django 问题甚至不是我的!- 我对可能攻击问题的一般策略更感兴趣,而不是详细的解决方案。因此,像“在 DBMS-X 中,这可以通过表 A 上的触发器来完成”这样的答案是完全可以接受的。

database-design foreign-key
  • 5 5 个回答
  • 7402 Views

5 个回答

  • Voted
  1. Justin Cave
    2012-05-15T15:23:14+08:002012-05-15T15:23:14+08:00

    在 Oracle 中,以声明方式强制执行此类约束的一种方法是创建一个物化视图,该视图设置为在提交时快速刷新,其查询标识所有无效行(即BookAspectRating在 中没有匹配的行BookAspect_view)。然后,您可以在该物化视图上创建一个简单的约束,如果物化视图中有任何行,就会违反该约束。这样做的好处是可以最大限度地减少您必须在物化视图中复制的数据量。但是,它可能会导致问题,因为约束仅在您提交事务时才被强制执行——许多应用程序并不是为了期望提交操作可能失败而编写的——并且因为违反约束可能有些困难与特定行或特定表关联。

    • 10
  2. Best Answer
    A-K
    2012-05-16T08:08:55+08:002012-05-16T08:08:55+08:00

    可以仅使用约束在模型中强制执行此业务规则。下表应该可以解决您的问题。使用它代替您的视图:

        CREATE TABLE BookAspectCommonTagLink
        (  BookID INT NOT NULL
        , AspectID INT NOT NULL
        , TagID INT NOT NULL
    --TagID is deliberately left out of PK
        , PRIMARY KEY (BookID, AspectID)
        , FOREIGN KEY (BookID, TagID) 
            REFERENCES BookTag (BookID, TagID)
        , FOREIGN KEY (AspectID, TagID) 
            REFERENCES AspectTag (AspectID, TagID)
        ) ;
    
    • 9
  3. Aaron Bertrand
    2012-05-15T15:14:19+08:002012-05-15T15:14:19+08:00

    我想您会发现,在很多情况下,复杂的业务规则不能仅通过模型来执行。这是其中一种情况,至少在 SQL Server 中,我认为触发器(最好是触发器而不是触发器)更好地服务于您的目的。

    • 8
  4. Erwin Smout
    2012-09-12T05:36:06+08:002012-09-12T05:36:06+08:00

    SIRA_PRISE允许这样做。

    虽然 FK 不再叫“FK”,而只是“数据库约束”,而“视图”实际上甚至不必定义为视图,您只需在声明中包含视图定义表达式即可数据库约束。

    你的约束看起来像

    SEMIMINUS(BOOKASPECT , JOIN(BOOKTAG , TAGASPECT))
    

    你就完成了。

    然而,在大多数 SQL DBMS 中,您必须对约束进行分析工作,确定如何违反约束并实现所有需要的触发器。

    • 4
  5. dezso
    2012-05-16T00:11:53+08:002012-05-16T00:11:53+08:00

    在 PostgreSQL 中,我无法想象一个不涉及触发器的解决方案,但它当然可以通过这种方式解决(无论是维护某种物化视图还是在触发器上之前BookAspectRating)。没有引用视图 ( ERROR: referenced relation "v_munkalap" is not a table) 的外键,更不用说主键了。

    • 3

相关问题

  • 过滤索引是否有助于改进基于输入时间的查询,还是应该避免这种情况?

  • MySQL VARCHAR 和 TEXT 数据类型有什么区别?

  • 存储计算值或根据要求重新计算它们更好吗?[复制]

  • 存储与计算聚合值

  • 在数据仓库中实现多对多关系有哪些方法?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve