MS Access 的多对多关系问题
Posted
技术标签:
【中文标题】MS Access 的多对多关系问题【英文标题】:Many to Many Relationship problem with MS Access 【发布时间】:2020-04-11 01:08:07 【问题描述】:我正在为我大学的一位管理员构建一个 Access 数据库,以跟踪教师信息。有一个部分用于跟踪哪个委员会的教员。这是一种多对多的关系,因为教员可以在多个委员会中任职,而且委员会显然有不止一个教员。这是我与连接表的关系的屏幕截图。我有一个人口统计表(教师),其中有一个委员会表和一个连接表:
我想要的是一个多选列表框,其中包含我可以选择来填充连接表的委员会。如果我将列表框设置为只有一个选择,则此方法有效。如果我将其设置为多项选择,则会收到一条错误消息,提示“您必须在 jctDemographicsCommitteess.committeeID 字段中输入一个值”。
有谁知道如何让它工作?
列表框在一个子窗体中,记录源是连接表。另外,当我设置 ListBox 时,我将“在此字段中存储该值:”设置为 CommitteeID。
如果您需要更多信息,请告诉我!
【问题讨论】:
必须是未绑定的listbox,并使用VBA通过循环listbox选中项将一批记录写入表。 不清楚;联结表中的每个条目都需要一个教师(或其他)和一个委员会成员。因此,例如,您需要一个用于教师的未绑定复选框或列表框,以及一个用于委员会的未绑定列表框。然后使用 vba 从连接表中输入和删除教师委员会组合。没有输入这两个值是错误的可能原因。 你有没有考虑过使用基于联结表的连续子表单,而不是使用列表框?您将在委员会桌子上拥有一个组合框。 我已经考虑过 ComboBox 的想法,但是,我需要能够输入多个值,因为教员可以是多个委员会的成员。我还需要一种将他们从委员会中删除的方法,并使用 ListBox,我可以从中选择和取消选择委员会;这似乎是最用户友好的方式。另外,我不确定什么是连续子表单。 ListBox 子窗体嵌入到一个主窗体中,该主窗体用于查看实际的其他数据(姓名、地址等)。我希望 DemographicID 会来自那里,而 CommitteeID 会来自 Listbox。 @June7 已经告诉您完成此操作需要做什么。编写代码会很烦人(我讨厌循环 htrpough 列表框),但它会得到你所需要的。 【参考方案1】:我认为在连续子窗体上使用一组组合框是这里的方法。
首先创建一个基于联结表的表单 在其属性中,将“默认视图”从“单一表单”更改为“连续表单”。在此表单中添加一个组合框,并将 Control Source 设置为 CommitteeID,RowSource 以 Committee 表为基础,且 CommitteeID 为绑定列。将 Column Count 设置为 2,将列宽设置为“0;6”。
返回基于人口统计表的表单。在工具箱上应该有一个插入子表单/子报表的选项。将其添加到 Demographics 表单的详细信息部分,当向导开始引导您完成时,选择“使用现有表单”,选择您刚刚创建的子表单,当询问要使用哪些字段进行链接时,选择“ DEM_ID”到“DemographicID”。
你应该得到这样的结果:
我在组合框旁边添加了一个“删除”按钮,其中包含以下代码:
CurrentDb.Execute "DELETE * FROM Junction WHERE DemographicID=" & Me.DemographicID & " AND CommitteeID=" & Me.CommitteeID
Me.Requery
问候,
【讨论】:
这是一个很好的选择。感谢您的建议以及您的详细说明!【参考方案2】:我去拿了一些我很久以前写的代码来帮忙。我把它清理了一点,但我把东西留给你自己解决。对不起,我很懒,但你从中得到了免费代码。它通过内联注释/cmets 彻底记录。
编码愉快!
Private Sub SampleListBoxLoop()
On Error GoTo SampleListBoxLoopErr
Dim arr(0 To 4) As String ' you might need to vchange this too
Dim lCol As Long, lRow As Long
Dim vbsql As String
With Me.ListBox
'I wrote this in Access97. Not sure if listbox looping is still backwards or not - find out!
'Looping through multi column list boxes is transposed.
'Which is why we loop through columns first
For lCol = 0 To .ColumnCount + 1 'needs to be plus due to column header
If .Selected(lCol) Then
'You'll need to change the next line based on your scenario.
'Since I gave you free code, you'lll have to figure this one out for yourself :P
For lRow = 0 To 4 'this is to 4 due to Ubound of array and not row count since row count changes with each run
'Assign to the array transposed so that it is filled in normally.
arr(lRow) = Nz(.Column(lRow, lCol))
Next lRow
End If
Next lCol
'needed for deselecting
For lRow = 0 To .ListCount - 1
.Selected(lRow) = False
Next lRow
End With
If arr(0) <> "" Then 'Cannot run this if empty array
'Build your SQL statements herre
CurrentDb.Execute vbsql, dbFailOnError
End If
Me.Requery
Me.ListBox.Requery
Me.Subform.Requery
Exit_Sub:
Exit Sub
SampleListBoxLoopErr:
If DBEngine.Errors.Count > 1 Then
'ODBC Error
For Each errany In DBEngine.Errors
msgbox "ODBCExecute: Err# " & errany.Number & " raised by " _
& errany.Source & ": " & errany.Description, _
vbCritical, "cmdExecuteAttached()"
Next errany
Else 'Access Error
msgbox "ODBCExecute: Err# " & ERR.Number & " raised by " _
& ERR.Source & ": " & ERR.Description, _
vbCritical, "cmdExecuteAttached()"
End If
GoTo Exit_Sub
Resume
End Sub
【讨论】:
以上是关于MS Access 的多对多关系问题的主要内容,如果未能解决你的问题,请参考以下文章
在 MS Access 中,如何以多对多关系列出记录,以使所列出的表中的记录不重复?