标签: referential-integrity

外键有什么问题?

我记得听过Joel Spolsky播客014中提到他几乎没用过外键(如果我没记错的话).但是,对我而言,在整个数据库中避免重复和后续数据完整性问题似乎非常重要.

人们有一些坚实的理由为什么(避免与Stack Overflow原则一致的讨论)?

编辑: "我还没有理由创建一个外键,所以这可能是我实际设置一个外键的第一个原因."

database database-design referential-integrity foreign-keys data-integrity

250
推荐指数
12
解决办法
11万
查看次数

使用空列创建唯一约束

我有一个这种布局的表:

CREATE TABLE Favorites
(
  FavoriteId uuid NOT NULL PRIMARY KEY,
  UserId uuid NOT NULL,
  RecipeId uuid NOT NULL,
  MenuId uuid
)
Run Code Online (Sandbox Code Playgroud)

我想创建一个类似于此的唯一约束:

ALTER TABLE Favorites
ADD CONSTRAINT Favorites_UniqueFavorite UNIQUE(UserId, MenuId, RecipeId);
Run Code Online (Sandbox Code Playgroud)

但是,这将允许多行具有相同的(UserId, RecipeId)if MenuId IS NULL.我想允许NULLMenuId存储不具有关联菜单中的最爱,但我只希望每个用户/食谱对这些行中最多只有一个.

我到目前为止的想法是:

  1. 使用一些硬编码的UUID(例如全零)而不是null.
    但是,MenuId每个用户的菜单都有一个FK约束,所以我必须为每个用户创建一个特殊的"空"菜单,这是一个麻烦.

  2. 使用触发器检查是否存在空条目.
    我认为这是一个麻烦,我喜欢尽可能避免触发器.另外,我不相信他们能保证我的数据永远不会处于不良状态.

  3. 只需忘记它并检查中间件或插入函数中是否存在空条目,并且没有此约束.

我正在使用Postgres 9.0.

我有什么方法可以忽略吗?

sql postgresql null database-design referential-integrity

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

MySQL外键允许NULL?

我正拼凑一个图片网站.基本模式非常简单的MySQL,但是我在尝试表示与图像相关的可能管理标志("不合适","受版权保护"等)时遇到了一些麻烦.我目前的想法如下:

tblImages (
    imageID INT UNSIGNED NOT NULL AUTO_INCREMENT,
    ...
);

tblImageFlags (
    imageFlagID INT UNSIGNED NOT NULL AUTO_INCREMENT,
    imageID INT UNSIGNED NOT NULL,
    flagTypeID INT UNSIGNED NOT NULL,
    resolutionTypeID INT UNSIGNED NOT NULL,
    ...
);

luResolutionTypes (
    resolutionTypeID INT UNSIGNED NOT NULL AUTO_INCREMENT,
    resolutionType VARCHAR(63) NOT NULL,
    ...
);
Run Code Online (Sandbox Code Playgroud)

(为了便于阅读而被截断;各种外键和索引都是有序的,我发誓)

tblImageFlags.flagTypeID在标志类型的查找表上是外键的,你可以想象tblImageFlags.resolutionTypeID 应该是外键的luResolutionTypes.resolutionTypeID.手头的问题是,当首次发布一个标志时,没有逻辑解决方案类型(我很好地宣称这个NULL); 但是,如果设置了一个值,它应该是外键键到查找表.

我找不到这种情况的MySQL语法解决方法.它存在吗?最佳参赛者是:

  • 添加"未经调整"的分辨率类型
  • 添加一个NULL条目luResolutionTypes.resolutionTypeID(这甚至可以在AUTO_INCREMENT列中工作吗?)

感谢您的见解!

PS Bonus指向任何人告诉我,在数据库的情况下,它是"索引"还是"索引".


后续行动:感谢Bill Karwin指出了表格结构中出现的语法错误(NOT NULL如果您希望它允许,请不要设置列NULL …

mysql database null referential-integrity foreign-keys

64
推荐指数
1
解决办法
6万
查看次数

在MySQL中,我可以在提交之前推迟参照完整性检查

正如在这个问题中,我一直在阅读PoEAA,并想知道是否可以推迟参考完整性检查,直到在MySQL中提交.

想要在同一次提交中插入一堆产品和相关产品时,我遇到了这个问题.即使在事务中,当我尝试插入related_products连接表时,我也会遇到约束错误.

如果它有帮助,我正在使用PHP PDO进行数据库连接.

我很感激您提供的任何帮助.

mysql referential-integrity

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

如何在Postgres 8.2中禁用参照完整性?

谷歌的这一结果有点薄,但建议不容易实现.

我的具体问题是我需要在两个彼此相关的表中重新编号ID,以便表B中有一个"table_a_id"列.我不能首先对表A重新编号,因为它的B中的子节点指向旧的ID.我不能首先重新编号表B,因为它们会在创建之前指向新的ID.现在重复三到四张桌子.

当我可以"启动事务;禁用ref完整性;对ID排序;重新启用ref完整性;提交事务"时,我真的不想摆弄个人关系.Mysql和MSSQL都提供了这个功能IIRC,所以如果Postgres没有,我会感到惊讶.

谢谢!

postgresql referential-integrity

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

为什么Rails迁移定义应用程序中的外键而不是数据库中的外键?

如果我定义一个CustomerOrder模型,其中Customer"有很多" OrdersOrder"属于" Customer,在Rails中我们谈论Order有一个外键到Customer通过customer_id但我们并不是说这是在数据库中强制执行.

由于Rails没有将其定义为数据库级约束,因此存在数据完整性被违反的风险,可能在应用程序之外(或者如果同时收到请求,则在内部?),除非您手动在数据库中强制执行约束.

为什么Rails没有在数据库级别定义外键,或者有没有办法让Rails这样做?

class Customer < ActiveRecord::Base
  has_many :orders
end

class Order < ActiveRecord::Base
    belongs_to :customer
end

ActiveRecord::Schema.define(:version => 1) do

  create_table "customers", :force => true do |t|
    t.string   "name"
  end

  create_table "orders", :force => true do |t|
    t.string   "item_name"
    t.integer  "customer_id"
  end

end
Run Code Online (Sandbox Code Playgroud)

database referential-integrity ruby-on-rails foreign-keys

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

保持参考完整性 - 好还是坏?

我们计划在数据库中引入简单的Audit Trail,使用触发器和每个需要审计的表的单独历史表.

例如,考虑表StudentScore,它具有很少的外键(例如,StudentID,CourseID)将其链接到相应的父表(学生和课程).

Table StudentScore (
    StudentScoreID, -- PK
    StudentID ref Student(StudentID),  -- FK to Student
    CourseID ref Course(CourseID),   -- FK to Course
)
Run Code Online (Sandbox Code Playgroud)

如果StudentScore需要审核,我们计划创建审核表StudentScoreHistory -

Table StudentScoreHistory (
    StudentScoreHistoryID, -- PK
    StudentScoreID,
    StudentID,
    CourseID,
    AuditActionCode,
    AuditDateTime,
    AuditActionUserID
)
Run Code Online (Sandbox Code Playgroud)

如果StudentScore中的任何行被修改,我们会将旧行移至StudentScoreHistory.

在设计讨论期间提出的一点是在StudentHistory表中将StudentID和CourseID设为FK,以保持参照完整性.支持这一点的论据是因为我们总是主要做一个软(逻辑布尔标志)删除而不是硬删除,它有利于维护引用完整性以确保我们在审计表中没有任何孤立ID.

Table StudentScoreHistory (
    StudentScoreHistoryID, -- PK
    StudentScoreID,
    StudentID ref Student(StudentID), -- FK to Student
    CourseID ref Course(CourseID), -- FK to Course
    AuditActionCode,
    AuditDateTime,
    AuditActionUserID
)
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎有点奇怪.我同意@Jonathan Leffler的评论,即审计记录不应该停止删除父数据.相反,如果需要,则应通过主表中的外键处理,而不是在审计表中处理.我想得到你的意见,以确保我没有错过将外键扩展到审计表的一些价值.

现在我的问题是: 在历史表中使用这些外键是一个好的设计吗?

关键参数的任何细节(性能,最佳实践,设计灵活性等)将受到高度赞赏.

为了寻找特定目的和环境的人的利益:

目的:

  1. 维护关键数据历史记录
  2. 允许审核用户活动并支持重新创建方案
  3. 在有限的范围内允许回滚用户活动 …

sql database-design referential-integrity audit-trail

33
推荐指数
3
解决办法
7155
查看次数

Rails:删除级联vs依赖destroy

假设我有两个表:usersorders.用户有很多订单,所以我的订单表中自然会有一个外键user_id.

rails中的最佳实践(速度,样式和参照完整性)是什么,以确保删除用户时,所有相关订单也会被删除?我正在考虑以下选项:

案例1. :dependent => :destroy在用户模型中使用

案例2.在postgres中定义表顺序并写入

user_id integer REFERENCES users(id) ON DELETE CASCADE
Run Code Online (Sandbox Code Playgroud)

我有什么理由使用案例1吗?似乎案例2正在做我想做的一切吗?执行速度方面有区别吗?

postgresql referential-integrity ruby-on-rails

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

是否应该执行参照完整性?

不应强制执行引用完整性的原因之一是性能.因为Db必须根据关系验证所有更新,它只会使事情变慢,但执行和不执行的其他优缺点是什么?

因为无论如何都要在业务逻辑层中维护关系,所以它只会让db成为冗余.你对此有什么想法?

database database-design referential-integrity

20
推荐指数
5
解决办法
1万
查看次数

CONSTRAINT检查远程相关表中的值(通过连接等)

我想添加一个约束来检查相关表中的值.

我有3张桌子:

CREATE TABLE somethink_usr_rel (
    user_id BIGINT NOT NULL,
    stomethink_id BIGINT NOT NULL
);

CREATE TABLE usr (
    id BIGINT NOT NULL,
    role_id BIGINT NOT NULL
);

CREATE TABLE role (
    id BIGINT NOT NULL,
    type BIGINT NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

(如果你想让我对FK施加约束,请告诉我.)

我想补充一个约束somethink_usr_rel,检查typerole("两个表走"),例如:

ALTER TABLE somethink_usr_rel
    ADD CONSTRAINT CH_sm_usr_type_check 
    CHECK (usr.role.type = 'SOME_ENUM');
Run Code Online (Sandbox Code Playgroud)

我尝试用JOINs 做但没有成功.知道如何实现它吗?

postgresql database-design referential-integrity constraints foreign-keys

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