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 / 问题 / 9155
Accepted
johannes
johannes
Asked: 2011-12-15 05:50:34 +0800 CST2011-12-15 05:50:34 +0800 CST 2011-12-15 05:50:34 +0800 CST

如何在数据库模式中表达这种约束?

  • 772

我在 BCNF 中有以下功能依赖项:

a,b -> c
a -> d
b -> d

有了附加约束,即 no aandb应该与 a 组合c,其中aandb具有不同d的 s。

例子:

a | d   b | d   a | b | c
-----   -----   ---------
1 | 3   5 | 3   1 | 5 | 6
2 | 4           2 | 5 | 7

第一行a,b,c是允许的 ( 1->3, 5->3),但第二行是禁止的,因为 ( 2->4, 5->3) 4 != 3。

这个额外的约束可以对我的数据产生两个影响。对于每一个a,b,c,都有两种冗余的方法来确定d。可以有违反约束的数据。我的模式如何反映这个额外的约束?

relational-theory constraint
  • 3 3 个回答
  • 1422 Views

3 个回答

  • Voted
  1. onedaywhen
    2011-12-15T09:51:39+08:002011-12-15T09:51:39+08:00

    简而言之,引入d第三个表以启用原始外键约束,例如 Transitional SQL-92 语法:

    CREATE TABLE T1
    (
     a INTEGER NOT NULL, 
     d INTEGER NOT NULL, 
     UNIQUE (a, d)
    );
    
    CREATE TABLE T2
    (
     b INTEGER NOT NULL, 
     d INTEGER NOT NULL, 
     UNIQUE (b, d)
    );
    
    CREATE TABLE T3
    (
     a INTEGER NOT NULL,
     b INTEGER NOT NULL, 
     c INTEGER NOT NULL, 
     d INTEGER NOT NULL, 
     UNIQUE (a, b, c),
     FOREIGN KEY (a, d) REFERENCES T1 (a, d), 
     FOREIGN KEY (b, d) REFERENCES T2 (b, d)
    );
    
    • 4
  2. Erwin Smout
    2011-12-15T15:19:26+08:002011-12-15T15:19:26+08:00

    “那么你的回答是‘不可能’吗?”

    很多事情都是可能的。在您的特殊情况下,在我看来,可以通过保持数据库单表(4 列)来强制执行“附加”约束。这将保证任何组合的 a,b 将始终对应于相同的 d(因为永远只能有一个 d)。您付出的代价是,不再有一种“自然”方式(即数据库本身非常合乎逻辑的结构的直接结果)将“自动”执行您的 a->d 和 b->d FD .

    众所周知,通过分解进行规范化的经典过程有时需要将某些 FD 恢复为数据库约束,因为在分解设计中,规则不能再表述为 FD。您的特殊情况似乎就是这样一种情况,您可以在“自动”执行 a->d 和 b->d 的设计之间进行选择,但是您必须付出额外的努力来执行您的附加约束,或者设计“自动”强制执行您的附加约束,但是您必须做额外的工作来强制执行 [对应于] 您的 a->d 和 b->d FD 的约束。

    在您的特定情况下,使用 onedaywhen 的解决方案可以使您提到的所有约束仅由数据库结构强制执行。但是,(a)这只是针对特定情况(例如您的示例)的解决方案,(b)您付出的代价是增加了冗余,因此更新数据库时会增加额外的复杂性(并且某些更新可能无法实现!!!) ,并且(c)仍然是一个事实,即并非所有可以想象的数据库约束都可以表示为 FD。

    (很抱歉发布第二个答案。我的 Stackoverflow 登录不允许我在这里发表评论。)

    • 3
  3. Best Answer
    onedaywhen
    2011-12-16T00:52:12+08:002011-12-16T00:52:12+08:00

    简而言之,创建一个ASSERTION确保在任何时候都不会违反业务规则的规则,例如完整标准 SQL-92 语法:

    CREATE TABLE T1
    (
     a INTEGER NOT NULL, 
     d INTEGER NOT NULL, 
     UNIQUE (a, d)
    );
    
    CREATE TABLE T2
    (
     b INTEGER NOT NULL, 
     d INTEGER NOT NULL, 
     UNIQUE (b, d)
    );
    
    CREATE TABLE T3
    (
     a INTEGER NOT NULL,
     b INTEGER NOT NULL, 
     c INTEGER NOT NULL, 
     UNIQUE (a, b, c)
    );
    
    CREATE ASSERTION no_a_and_b_should_be_combined_with_a_c_where_a_and_b_have_different_ds
       CHECK (
              NOT EXISTS (
                          SELECT *
                            FROM T3
                           WHERE NOT EXISTS (
                                             SELECT T1.d
                                               FROM T1
                                              WHERE T1.a = T3.a 
                                             INTERSECT        
                                             SELECT T2.d
                                               FROM T2
                                              WHERE T3.b = T3.b 
                                            )
                         )
             );
    

    坏消息是没有商业(或其他?)SQL 产品支持CREATE ASSERTION.

    大多数工业级 SQL 产品都支持触发器:可以在每个适用表的触发器中实现上述功能。MS Access 是我所知道的唯一支持CHECK约束子查询的商业产品,但我不认为它具有工业实力。还有其他解决方法,例如强制用户仅通过存储过程更新表,这些存储过程可以证明永远不会使数据库处于非法状态。

    • 3

相关问题

  • “hasMany”属于哪个范围?

  • 使字段唯一会使其被索引吗?

  • 关系设计 - 一个外键列中的多个表?

  • 命名表和视图时应该遵循什么标准?

  • 如何构建模型以正确有效地表示关系数据库上的树状数据?

Sidebar

Stats

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

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

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

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +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
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +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