标签: referential-integrity

我如何证明删除外键的行为不会破坏现有数据?

TL;DR:证明在实践中,alter table table_name drop foreign key constraint_name语句的执行不会破坏现有数据。重要的考虑是语句本身的执行;考虑无关紧要的事后数据更改。(打个比方:打开马厩门是有害的行为,而不是马螺栓。)

我和我的老板对于是否在 MySQL/InnoDB 数据库中使用外键有不同的看法。我赞成使用它们来强制执行 RI 并利用ON DELETE CASCADEON UPDATE RESTRICT/ SET NULL,而他反对(相信他可以在应用程序级别强制执行 RI)。

他的论点主要是:

  1. Drupal 不使用它们,没有它们也能正常工作,那我们为什么要这样做呢?
  2. 当您需要更改数据和/或结构时,它们太不灵活了。
  3. 他已将它们从现有表中删除以进行更改,这导致数据损坏仅在数周或数月后才在高流量/高活动站点上引起注意,因此他宁愿不使用它们。

我的论点主要是:

  1. 并非 Drupal 5-7(MyISAM、SQLite 3)支持的所有数据库/数据库引擎默认都强制执行FK,因此 Drupal 仅将它们保留为文档,而这在 D8 中可能有所不同。
  2. 是的,它们可能很难处理,但也许问题在于开发人员的规划/设计不当,而不是 FK。
  3. 当然,在 DBMS 级别不使用 FK 强制执行 RI 比其他方式更有可能导致数据损坏。(例如,当现有内容引用必须具有特定状态的用户时,D6 的用户引用模块不限制更改用户状态)。
  4. 让代码做/尝试 DBMS 已经做的事情是在浪费时间和资源。他如何保证他的代码与 DBMS 一样好(或比 DBMS 更好)?

从本质上讲,如果我能证明删除外键本身的行为(无论后续数据插入/更新如何)不会破坏现有数据,他就会认同我的想法。我看不出有什么方法可以证明它们的有用性/优势,因为我不确定如何令人满意地观察/记录drop foreign key执行后立即产生的效果,而不是将执行前的数据与执行后的数据进行比较。

那么,我如何通过证明以后删除/更改外键的行为不会破坏现有数据,而使用它们不会导致任何问题来说服我的老板我们应该使用外键?我如何最好地设置实际使用测试?

注意:我不太想证明我使用 FK 是正确的(从自负的角度来看),但是在 DBMS 级别使用它们比在应用程序代码中使用它们更有益于数据和应用程序代码等级。

mysql innodb foreign-key database-design referential-integrity

5
推荐指数
2
解决办法
1828
查看次数

当子表为空时截断 Oracle 中的父表

假设我有一个parent由子表引用的父表child。该表parent已填充但未填充child。试图截断parent结果

 ORA-02449: unique/primary keys in table referenced by foreign keys  
Run Code Online (Sandbox Code Playgroud)

有没有办法向child空的 DBMS 提示,以便不需要禁用外键约束?

oracle referential-integrity truncate

4
推荐指数
2
解决办法
2万
查看次数

数组列的外键

我有一张桌子:

CREATE TABLE methods
(
    method_id serial PRIMARY KEY,
    method_name varchar(100)
);
Run Code Online (Sandbox Code Playgroud)

我现在想创建一个包含以下列的表:

CREATE TABLE experiments 
(
    method integer[] REFERENCES methods(method_id),
    trials integer
);
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

键列“method”和“method_id”是不兼容的类型:整数[]和整数。

我知道列必须是相同的类型,我还看到有些人已经尝试在数组问题上解决这个外键:

PostgreSQL 9.3 开发:Array ELEMENT 外键

我的兴趣是 'method' 应该是一个整数数组,引用来自表 'methods' 的 'method_id',但我无法弄清楚。我认为上面的链接可能是一个解决方案,但似乎没有实现(?)

一些帖子建议使用连接/连接表:

数组成员的外键约束?

我是一个绝对的初学者,我还无法弄清楚。对我来说,首先要了解如何解决数组上的外键问题。可以将多个方法视为形成一类方法。每个班级可以有一定数量的试验。

postgresql referential-integrity array

4
推荐指数
1
解决办法
9003
查看次数

包含自引用表的复杂删除级联

图表

上图是我的数据结构图。它代表一个层次结构,可以包含三种不同类型的“元素”:“A”、“B”和“C”。的关系表明删除级联行为我也喜欢用,如果它是可能的。

所有类型都有共同的属性,包括显示层次结构(父级和索引)中的位置和元素类型的列。这些公共列存储在ElementBase表中。

每种类型的元素还具有独特的属性,这些属性根据元素类型存储在相应的表中。

中的每一行ADataBDataCData引用 中的唯一主行ElementBase。“A”和“C”元素也各自引用“B”元素。“B”元素可以有0个或多个“S”。

我的问题是:如何维护引用完整性并支持级联删除之类的功能?

我希望能够从中删除一行ElementBase并在其中包含相应的行ADataBData或者CData也可以删除。例如,如果从 中删除了“B”类型的元素ElementBase,则首先BData应删除相应的行,然后需要在表ElementBaseCData表中删除所有引用它的“C”类型元素,并且所有“A” "-type 元素需要将它们的引用设置为NULLin AData

最重要的是:如果我删除的元素有任何类型的子元素,我希望相同的逻辑在层次结构中递归运行。

由于ElementBase是自引用,我无法使用该ON DELETE CASCADE表中的简单功能。我也不能使用它,AData或者CData因为它们都引用了BData这可能会导致“多个级联路径”,这在 SQL Server 中显然是邪恶的。

我发现的另一种选择是INSTEAD OF触发器。问题是这种行为必须是递归的,我无法弄清楚如何使它们能够递归并最终在最后进行原始删除。

trigger database-design sql-server referential-integrity cascade

4
推荐指数
1
解决办法
870
查看次数

发现违反对称约束

假设我有一个Friends包含列的表Friend1ID, Friend2ID。我选择用两条记录来代表每段友谊,比如 (John, Jeff) 和 (Jeff, John)。因此,每对朋友应该恰好出现在表中两次。

有时,这个约束被违反,即一对朋友在表中只出现一次。我如何编写一个查询来识别所有这些情况(理想情况下,使用合理的标准 SQL)?换句话说,我希望查询返回此表中的行列表,其中没有对应的行与交换字段。

另一个问题:有没有办法在 MySQL 中强制执行这种参照完整性?

mysql database-design constraint referential-integrity

3
推荐指数
1
解决办法
649
查看次数

当两个 FK 列需要在同一个表中匹配自己时的参照完整性?

可能我的设计是错误的,或者只是有更好的方法。我将使用一个非常简单的例子:

    --------- dbo.Book----------
   |                            |
   |  BookID int identity (1,1) |
   |  ShelfID int FK            |--
    ----------------------------   |
                                   |
    --------- dbo.Row-----------   |    
   |                            |  |    
 --|  RowID int identity (1,1)  |  |    
|   ----------------------------   |    
|                                  |        
|   -------- dbo.Shelf----------   | 
|  |                            |  |
|  |  ShelfID int identity (1,1)|--
 --|  RowID int FK              |
    ----------------------------
Run Code Online (Sandbox Code Playgroud)

足够简单。

但是如果我想分配一个没有架子的行怎么办?也许我们还知道行而不是货架:

    --------- dbo.Book----------
   |                            |
   |  BookID int identity (1,1) |
   |  RowID int FK              | <-- New
   |  ShelfID int FK …
Run Code Online (Sandbox Code Playgroud)

foreign-key database-design sql-server referential-integrity

2
推荐指数
1
解决办法
422
查看次数

INSTEAD OF 触发器内的确定性

参考我之前关于首选设计的问题,以避免循环或多个更新路径参照完整性通过ON UPDATE CASCADE和级联更新和删除ON DELETE CASCADE,我正在尝试使用触发器作为替代方案。

对于这个例子,我试图尽可能地简化设计。

我有一张Parent桌子和一张Child桌子;ParentChild共享一列,ParentName。每当Parent.ParentName发生变化时,我都想在Child.ParentName.

够简单吗?如果我更新 中的单行Parent,我可以使用inserteddeleted表很容易地知道要更新ParentChild表中的哪一行。像这样的东西:

UPDATE Parent
SET Parent.ParentName = inserted.ParentName
FROM Parent
    INNER JOIN deleted ON Parent.ParentName = deleted.ParentName
    CROSS JOIN inserted;

UPDATE Child
SET Child.ParentName = inserted.ParentName
FROM Child
    INNER JOIN deleted ON Child.ParentName = deleted.ParentName
    CROSS JOIN inserted;
Run Code Online (Sandbox Code Playgroud)

很明显,如果Parent在一个 …

trigger sql-server referential-integrity

1
推荐指数
1
解决办法
190
查看次数