与MySQL外键中的RESTRICT相反删除?

时间:2013-01-28 21:07:42

标签: mysql database-design foreign-keys

我正在重新设计一些应用程序安全日志表(例如用户登录,访问不同文件等等)以满足一些不断变化的需求。它们最初是用MyISAM创建的,但实际上并没有真正被访问,并且切换到InnoDB并且为数据完整性添加一堆外键真的会更有益。因为无论如何我必须重新制作表格,我觉得这是一个很好的时间来进行切换。

在大多数情况下,一切都是简单的外键,并按预期工作。我正在尝试一些奇怪的问题和遇到问题的唯一部分是user_ids。这些日志表中的每条记录都与user_id相关联,我想确保在插入记录时存在给定的user_id。添加引用用户表的外键可以解决这个问题 - 简单的东西。以下是一些简洁,有代表性的表格:

用户表

CREATE TABLE tbl_user (
  id INT(10) NOT NULL AUTO_INCREMENT,
  first_name VARCHAR(50),
  PRIMARY KEY(id)
) ENGINE=InnoDB; 

示例日志表

CREATE TABLE tbl_login_time (
  id INT(10) NOT NULL AUTO_INCREMENT,
  user_id INT(10) NOT NULL,
  login_at TIMESTAMP NOT NULL,
  PRIMARY KEY(id),
  CONSTRAINT 'tbl_login_time_fk_1` FOREIGN KEY (user_id) REFERENCES tbl_user
      ON UPDATE CASCADE ON DELETE ???
) ENGINE=InnoDB; 

我的问题是我希望对插入强制执行外键,更新级联,但删除tbl_user中的记录根本不影响tbl_login_time。通常,用户被标记为非活动状态,但每隔一段时间用户就会被完全删除,但需要维护日志。

MySQL docs列出ON DELETE的6个选项,但这些选项听起来都不合适:

  1. RESTRICT :会阻止tbl_user中的删除。
  2. NO ACTION :获得评估,就像RESTRICT一样。
  3. CASCADE :会在我想要的tbl_user中删除,但也会在tbl_login_time中删除。
  4. SET NULL :将在tbl_user中删除,并将该行保留在tbl_login_time中,但会使数据无效。关闭但没有雪茄。
  5. SET DEFAULT :MySQL识别它,但拒绝它。
  6. 忽略ON DELETE :相当于RESTRICT。
  7. 我之前从未使用过这样的外键(强制执行INSERTUPDATE而不是DELETE),并且在阅读了很多其他问题之后看起来并不像其他人都做了。这应该告诉我这是错误的方法,但它可以以某种方式工作吗?

1 个答案:

答案 0 :(得分:2)

  

我的问题是我想要对插入强制执行外键,   更新要级联,但删除tbl_user中的记录不会影响   tbl_login_time。

使用外键约束无法实现这一点。

在某些应用程序中,ON DELETE SET NULL是有意义的。但是您的应用程序本质上是存储在SQL数据库中的日志文件。您有一个重要问题,即您要删除标识信息(用户),但在某些情况下会保留其ID号。坦率地说,我不明白为什么你愿意保留用户23332今天18:40登录的事实,而不关心你是否可以识别用户23332

您有几个选择。

  • 删除日志文件表,并将日志文件数据存储在文件系统中的文件中,而不是存储在数据库中。如果我在你的鞋子里,我会先考虑这个。如果我们谈论的是通过Web以某种方式访问​​的数据库,请确保日志文件存储在Web根目录之外。 (我将它与/ var / log一起存储在所有其他日志文件中。)
  • 使用外键约束,永不删除用户。
  • 使用外键约束,并使用ON DELETE SET NULL或ON DELETE SET DEFAULT的效果。在此特定应用程序中,ON DELETE SET NULL和ON DELETE SET DEFAULT在语义上是等效的。两者都将数据替换为不识别用户的数据。如果你无法识别用户23332,谁在乎你是否知道她今天18:40登录了?
  • 删除外键约束,并使用触发器执行任何您喜欢的操作。

我很确定我们同意最明显的选择 - 使用ON DELETE CASCADE的外键 - 对你的应用来说是错误的。