【问题标题】:Query regarding SQLite and Cascading foreign keys关于 SQLite 和级联外键的查询
【发布时间】:2018-09-11 17:40:10
【问题描述】:

我目前正在用 C# 编写一个应用程序,它使用 SQLite 数据库来存储用户将输入的信息。该应用程序基本上是一个管理系统,用于在应用程序中被称为“学生”的用户。这是我的数据库中最重要的表,其他所有表都与该表链接。我想要做的是当一个学生被移除时——他们离开学院/被踢出等等——是从所有其他表中移除他们的数据,这样数据就不再存在了,因为它不需要了。我编写的一些创建表语句的示例是:

CREATE TABLE student(studentID int(5) PRIMARY KEY NOT NULL, name string(16),...,DOB string(8) );

CREATE TABLE emergencyContact(emergencyID int(5) PRIMARY KEY NOT NULL, name string(16),..., contactNumber int(16));

CREATE TABLE emergencyContactOf(studentID int(5) FOREIGN KEY REFERENCES student('studentID'), emergencyID int(5) FOREIGN KEY REFERENCES emergencyContact('emergencyID');

我已阅读此内容,我的理解是,如果我包含“ON DELETE CASCADE”语句,则会删除 EmergencyContactOf 表中的数据,因为 StudentID 键将不再存在于 Parent 表中。

但是,我的理解是,EmergencyContact 表中针对该特定学生的数据不会被删除,因为没有引用 StudentID。

我的问题是,有没有办法从该表中删除与该学生相关的数据?例如,如果我要在 EmergencyContact 表中包含一个列,它将引用 StudentID 作为外键,然后如果从父表中删除了 StudentID,则删除该行?这是解决这个特定问题的好方法吗?

我拥有的所有其他表也是这样设计的,其中数据位于不同的表中,然后通过关系表链接回 Student 表,因此这也适用于我拥有的所有其他表。

谢谢。

【问题讨论】:

  • 没有回答您的问题,但您确实希望使用INTEGER PRIMARY KEY,而不是int(5) PRIMARY KEY 来提高您的表格效率...

标签: sql database sqlite c#-4.0 cascade


【解决方案1】:

我的问题是,有没有办法从该表中删除与该学生相关的数据?例如,如果我要在 EmergencyContact 表中包含一个列,它将引用 StudentID 作为外键,然后如果从父表中删除了 StudentID,则删除该行?这是解决这个特定问题的好方法吗?

如果多个学生有相同的紧急联系人会怎样?如果没有必要,您不想复制数据——这就是emergencyContactOf 表的重点,可以有效地在学生和紧急联系人之间建立多对多关系。所以你不想做你描述的事情。

您可以定期(每月、每年,在清除学生名册后,等等)运行删除,如果它们没有出现在紧急联系人中,则从紧急联系人中删除它们:

DELETE FROM emergencyContact
WHERE emergencyID NOT IN (SELECT emergencyID FROM emergencyContactOf)

或类似的。

【讨论】:

  • 谢谢Shawn - 没有考虑过这种情况,但肯定会在所有表中发生 - 多个父级等 - 所以将使用您建议的第二个 SQL 命令。非常感谢您的帮助
【解决方案2】:

嗯,我在这里看到了两种情况。如果两个学生有相同的紧急联系人怎么办?比如说两个麻烦,他们的父亲是紧急联系人?

  1. 如果在这种情况下,您在紧急联系人表中只存储了一条记录(父亲),如果只有其中一个人离开,您不想删除该紧急联系人。你会删除另一个人的紧急联系人。所以你需要额外的逻辑,什么时候删除紧急联系人。你可以把它放在一个触发器中。
  2. 您使用一种不太复杂的方法,紧急联系人表中的多行可以映射到现实生活中的一个人。在这种情况下,您可以将对学生的引用直接拉到紧急联系人表中,并在那里使用ON DELETE CASCADE

    CREATE TABLE student
                 (studentid int(5),
                  name string(16),
                  ...
                  PRIMARY KEY (studentid),
                  ...);
    ...
    CREATE TABLE emergencycontact
                 (emergencycontactid int(5),
                  studentid int(5),
                  name string(16),
                  ...
                  PRIMARY KEY (emergencycontactid),
                  FOREIGN KEY (studentid)
                              REFERENCES student
                                         (studentid),
                  ...);
    

第二个可能很诱人,但“干净的方式”是第一个,因为第二个允许矛盾的数据。从您发布的内容来看,您已经走上了“干净的道路”。但是提到需要触发器。

【讨论】:

  • 谢谢 - 没有考虑或想过多个学生有相同的紧急联系人,但我现在肯定会考虑一个。也发生在多个表中 - 许多学生的家长等 - 因此将使用 SQL 命令或其变体,如上面 Shawn 所建议的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
  • 2012-12-25
  • 1970-01-01
  • 2011-05-22
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多