如何处理Access中插入的参照完整性

时间:2011-09-13 06:58:37

标签: ms-access vba ms-access-2007

我正在研究一个我从同事手中接过的Access项目。存在三个表:rulesoverviewrelationshiprelationship表有两个字段,每个字段都是一个外键,链接到另外两个表中的主键。我有一个表格中rules表的数据表视图,我可以删除没有问题的记录。但是,当我尝试将记录插入rules表时,记录将插入rules表,但没有匹配的记录插入relationship表。我检查了“强制参照完整性”,以及“级联更新相关字段”和“级联删除相关记录”。我做了一个天真的假设,这会处理插入,但显然我错了。所以我现在想知道处理这个问题的最佳方法 - 我是否为表单的After Insert事件编写了一些VBA,将事件相应地插入到relationship表中?

2 个答案:

答案 0 :(得分:2)

通常的方法是使用表单将记录插入到基于包含关系表的查询的规则中,例如,允许用户选择相关概述的组合,或表单/子表单集具有合适的主/子字段的特写。在NorthWind示例数据库中,Order Detail表是Relationship表的一个示例,它使用了厌恶的查找表反特征,但您可能会获得一些进一步研究的想法。

选项1的更详细说明

<强>表格

概述
ID
概述

规则
ID
规则

关系
RulesID)PK由两个FK组成 OverviewID)

<强>关系

Relations

数据

Data

建议1查询设计

请注意,Relationship中的两个字段都包含在查询中。没有必要显示规则中的ID,因为它是一个自动编号字段,但为简单起见,它包含在此处。

如果删除了一行,则会删除两个表中的记录。

Query Design

您不能违反参照完整性。在此之前,您需要创建所有概视图,或者提供添加概视图的其他方法。

Violate Integrity

如果更新RulesIDOverviewID,记录将添加到关系表中,但不会添加到规则中。

New Relationship record

如果您更新OverviewIDRule,记录将添加到关系和规则中。

New Rule and Relationship records

如果您创建了一个连续的表单,那么您可以通过更加用户友好的方式获得更多控制权。您可以使用组合框来允许用户选择更友好的概述描述,而不是ID,您可以利用NotInList事件添加新的概视图。

continuous Form

请注意,到目前为止,这不需要一行代码。这就是Access的力量。

答案 1 :(得分:0)

如果有问题的密钥是自动编号(IDENTITY)并且一个表引用另一个(通过外键),那么您可以创建一个VIEW连接两个表,插入到视图中,以及自动编号值自动复制到引用表。这是一个快速演示:

Sub RulesOverview()
  On Error Resume Next
  Kill Environ$("temp") & "\DropMe.mdb"
  On Error GoTo 0

  Dim cat
  Set cat = CreateObject("ADOX.Catalog")

  With cat
    .Create _
    "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source=" & _
    Environ$("temp") & "\DropMe.mdb"

    With .ActiveConnection

      Dim Sql As String

      Sql = _
      "CREATE TABLE Rules ( " & _
      " ID INTEGER IDENTITY NOT NULL UNIQUE,  " & _
      " Rule VARCHAR(30) NOT NULL UNIQUE " & _
      ")"

      .Execute Sql

      Sql = _
      "CREATE TABLE Overview ( " & _
      " OverviewID INTEGER IDENTITY NOT NULL UNIQUE, " & _
      " Overview VARCHAR(30) NOT NULL UNIQUE " & _
      ")"

      .Execute Sql

      Sql = _
      "CREATE TABLE Relationship ( " & _
      " RuleID INTEGER NOT NULL " & _
      "    REFERENCES Rules (ID) " & _
      "    ON DELETE CASCADE, " & _
      " OverviewID INTEGER " & _
      "    REFERENCES Overview (OverviewID) " & _
      "    ON DELETE SET NULL, " & _
      " Name VARCHAR(20) NOT NULL, " & _
      " UNIQUE (RuleID, OverviewID) " & _
      ")"

      .Execute Sql

      Sql = _
      "CREATE VIEW RulesRelationship AS " & _
      "SELECT Rules.ID, " & _
      "       Rules.Rule, " & _
      "       Relationship.RuleID, " & _
      "       Relationship.Name " & _
      "  FROM Rules INNER JOIN Relationship " & _
      "          ON Rules.ID = Relationship.RuleID;"

      .Execute Sql

      Sql = _
      "INSERT INTO RulesRelationship (Rule, Name) " & _
      "   VALUES ('Don''t run with scissors', " & _
      "           'Initial scissors');"

      .Execute Sql

      Sql = _
      "SELECT * FROM RulesRelationship;"

      Dim rs
      Set rs = .Execute(Sql)
      MsgBox rs.GetString

    End With
    Set .ActiveConnection = Nothing
  End With
End Sub