【问题标题】:When deleting a record that is referenced in another table, how do I know when to stop?删除在另一个表中引用的记录时,我如何知道何时停止?
【发布时间】:2011-03-19 07:12:51
【问题描述】:

我的数据库中有以下表结构:

create table Encargado(
ID int primary key,
Nombre varchar(300),
)

create table Area(
ID int primary key,
Nombre varchar(300),
Jefe int foreign key references Encargado(ID)
)

create table Carrera(
ID int primary key,
Nombre varchar(300),
Area int foreign key references Area(ID)
)

create table Formacion(
ID int primary key,
Grado varchar(300),
Lugar varchar(300)
)

create table Docente(
ID int primary key,
Nombre varchar(300),
Carrera int foreign key references Carrera(ID),
Formacion int foreign key references Formacion(ID),
Horario varchar(300)
)

create table Evaluacion(
ID int primary key,
Docente int foreign key references Docente(ID),
Evaluador varchar(300),
Secuencia int,
Pizarra int,
Audiovisual int,
Letra int,
Voz int,
GestosVocabulario int,
Ejemplificacion int,
Respuestas int,
DominioEscenico int,
Participacion int,
Observacion varchar(4000),
Materias varchar(3000),
Valido bit
)

create table Seguimiento(
ID int primary key,
Docente int foreign key references Docente(ID),
Modulo int,
Semestre int,
Ano int,
Fecha datetime,
Hora datetime,
OrdenSecuencia bit,
OrdenSecuenciaObservacion varchar(200),
PortafolioAlumno bit,
PortalofioAlumnoObservacion varchar(200),
AspectosParaEntrevista varchar(3000),
Conclusiones varchar(3000),
Evaluador varchar(300),
DirectorDeArea int foreign key references Encargado(ID),
EncargadoControl int foreign key references Encargado(ID),
)

假设我想删除一个区域,我该怎么做?我还需要删除所有 Carreras 和所有 Docentes。

public void Delete(Area area)
        {
            db.Carreras.DeleteAllOnSubmit(area.Carreras);
            //I'm stuck here. Is this what I should be doing?
        }

有人可以建议如何处理吗?

我正在使用 C# 和 Linq-to-SQL。我觉得我可能通过使用这种表结构将自己挖了一个洞,或者这可能是关系数据库的失败之一? :\

【问题讨论】:

    标签: c# sql linq-to-sql database-design


    【解决方案1】:

    我不会在 Linq-to-SQL 端处理这个问题,如果你真的想删除所有子记录,我会在数据库端使用级联删除。

    例如,对于 Oracle,您可以在创建表语句中添加“ON DELETE CASCADE”子句,请参阅 this 链接。

    级联删除将处理从子表中删除所有记录,所有这些都通过一个删除操作完成。这种方法的美妙之处在于,无论您在何处执行操作,尽管是通过 Linq-To-SQL、JAVA、ROR、PHP 等,逻辑都集中在数据库中,因此无论谁执行删除操作都一样.

    【讨论】:

    • 级联删除的一个注意事项是,它也很容易意外删除大量数据。我个人的偏好是将所有删除都封装在一个存储过程调用中,这样如果有东西试图删除该调用之外的行,它将阻塞任何子行。
    【解决方案2】:

    这应该取决于你想如何处理你的外键关系。即删除外部引用或留下它们以防它们有其他依赖于它们的条目等。

    请参阅参考完整性http://msdn.microsoft.com/en-us/library/ms186973.aspx

    所以,最后你可能应该让数据库来处理它。

    【讨论】:

      【解决方案3】:

      假设我要删除一个区域,如何 我会这样做吗?我还需要 删除所有 Carreras 以及所有 讲解员。

      从表面上看,您似乎想将 ON DELETE 的声明性引用完整性 (DRI) 操作从默认的 NO ACTION(即防止删除引用的行)更改为 CASCADE(即删除引用表中的行)。

      请注意,这种逻辑通常表明引用列(例如Carrera.Area)应定义为NOT NULL

      例如:

      CREATE TABLE Carrera
      (
      ...
      Area INTEGER NOT NULL
         REFERENCES Area (ID) 
         ON DELETE CASCADE
      );
      
      CREATE TABLE Docente
      (
      ...
      Carrera INTEGER NOT NULL
         REFERENCES Carrera (ID)
         ON DELETE CASCADE, 
      ...
      );
      

      然而,深入研究我们会发现

      Evaluacion REFERENCES Docente
      Seguimiento REFERENCES Docente
      

      您需要考虑这些是否也需要ON DELETE CASCADE DRI 操作。

      此外:

      Seguimiento REFERENCES Encargado -- twice
      Area REFERENCES Encargado
      

      换句话说,这里有一个潜在的循环。即使您的 DBMS 允许 ON DELETE CASCADE DRI 对所有这些操作(例如 SQL Server 不允许),您也应该考虑通过“手动”删除行来管理逻辑。

      还有其他需要考虑的事情,看到所有那些看似可以为空的列(但主键列怎么可以为空...?)您可以考虑ON DELETE SET NULL DRI 操作。就个人而言,我会通过删除 NULLable 列来澄清设计,这会创建新的关系表,但这可能涉及大量工作:)

      【讨论】:

        【解决方案4】:

        您是否考虑过“逻辑删除”而不是物理删除?

        当您希望保留对数据(用于报告或查询)的历史访问权限时,即使它们已经过时,逻辑删除也很有意义。

        示例:您的学校曾经教拉丁语,并且有许多教授教授拉丁语,并且招收了许多学生。 明年,拉丁语将从可用课程中删除。其中一位教授退休,其他人继续学习其他课程。学生仍然需要证明他们获得了拉丁语投票,即使这不会成为未来课程的一部分。

        解决方案:在 Course 表中添加一个布尔标志 (Active=Y/N) 并调整您的程序,使其从必须返回什么内容的查询中排除具有“Active=N”的课程(或教授或其他任何内容) “活”,并将它们保存在历史报告中。

        【讨论】:

          猜你喜欢
          • 2011-07-27
          • 2019-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-21
          • 2010-09-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多