Ken Sheridan
Active member
- Local time
- Today, 13:10
- Joined
- Jul 10, 2025
- Messages
- 277
If we start with a table Parts with columns for it's attributes, each of which must be functionally determined solely by the key:
Parts
....PartID (PK)
....PartName
....Tag
Parts are combined to make assemblies, which is another entity type modelled by a table:
Assemblies
....AssemblyID
....AssemblyName
In each of the above other columns can be added to represent attributes functionally determined by the key.
Each assembly comprises multiple parts and each part (i.e. the type of part not each physical entity of the type) can be a component of multiple assemblies, so the relationship type is many to many. The relationship type is modelled by a table which resolves it into two one to many relationship types:
AssemblyParts
....AssemblyID (FK)
....PartID
....Quantity
When the three tables are joined in a query, each assembly would return multiple rows, one for each constituent part. You say, however, that you want the tags returned as a single string expression. This can be done by returning distinct assemblies in a query and a string of all tags for each assembly by means of a VBA concatenation function. The following is one of my own which uses the highly efficient GetString property of the ADO recordset object. Other similar functions will use DAO, and iterate through the referencing rows in the Parts table to build a string. You'll easily be able to find such functions online:
The above assumes that for each assembly you want to record a simple parts list. However, assemblies are generally made of sub-assemblies which are themselves made up of other assemblies and/or atomic base parts. The classic model for this comprises two tables:
Parts
....PartID
....PartName
....Tag
This table covers includes all assemblies, sub-assemblies, and atomic base parts. I've added the last column to satisfy your requirements.
PartStructure
....MajorPart (FK)
....MinorPart (FK)
....Quantity
The two foreign key columns each reference the primary key of Parts. The primary key is a composite of the two foreign keys. This very simple model can define any assembly, whatever its complexity, as, in theory, the recursive nature of the joins allows for an infinite number of levels. To generate a bill of materials for an assembly therefore requires recursive querying. Unlike client server database systems like Oracle, SQL Server etc. this is not supported by Access per se. It can be simulated, however, and I long ago created an Access file which does this by progressively writing rows to a table in an external database created at runtime. I won't go down that road at present, however, as I don't think it's what you are looking for. If I'm wrong let me know and I'll attach the file here.
Parts
....PartID (PK)
....PartName
....Tag
Parts are combined to make assemblies, which is another entity type modelled by a table:
Assemblies
....AssemblyID
....AssemblyName
In each of the above other columns can be added to represent attributes functionally determined by the key.
Each assembly comprises multiple parts and each part (i.e. the type of part not each physical entity of the type) can be a component of multiple assemblies, so the relationship type is many to many. The relationship type is modelled by a table which resolves it into two one to many relationship types:
AssemblyParts
....AssemblyID (FK)
....PartID
....Quantity
When the three tables are joined in a query, each assembly would return multiple rows, one for each constituent part. You say, however, that you want the tags returned as a single string expression. This can be done by returning distinct assemblies in a query and a string of all tags for each assembly by means of a VBA concatenation function. The following is one of my own which uses the highly efficient GetString property of the ADO recordset object. Other similar functions will use DAO, and iterate through the referencing rows in the Parts table to build a string. You'll easily be able to find such functions online:
Code:
Public Function GetList(strTable As String, strColumn As String, strSortColumn As String, strDelim As String, Optional strFilter As String = "True") As String
Const NOCURRENTRECORD = 3021
Dim rst As ADODB.Recordset
Dim strSQL As String
Dim strList As String
strSQL = "SELECT " & strColumn & " FROM " & strTable & " WHERE " & strFilter & " ORDER BY " & strSortColumn
Set rst = New ADODB.Recordset
With rst
Set .ActiveConnection = CurrentProject.Connection
.Open _
Source:=strSQL, _
CursorType:=adOpenForwardOnly, _
Options:=adCmdText
On Error Resume Next
strList = .GetString(adClipString, , strDelim, strDelim)
.Close
Select Case Err.Number
Case 0
' no error so remove trailing delimiter
' and return string
GetList = Left(strList, Len(strList) - Len(strDelim))
Case NOCURRENTRECORD
' no rows in table so return
' zero length string
Case Else
' unknown error
GetList = "Error"
End Select
End With
End Function
The above assumes that for each assembly you want to record a simple parts list. However, assemblies are generally made of sub-assemblies which are themselves made up of other assemblies and/or atomic base parts. The classic model for this comprises two tables:
Parts
....PartID
....PartName
....Tag
This table covers includes all assemblies, sub-assemblies, and atomic base parts. I've added the last column to satisfy your requirements.
PartStructure
....MajorPart (FK)
....MinorPart (FK)
....Quantity
The two foreign key columns each reference the primary key of Parts. The primary key is a composite of the two foreign keys. This very simple model can define any assembly, whatever its complexity, as, in theory, the recursive nature of the joins allows for an infinite number of levels. To generate a bill of materials for an assembly therefore requires recursive querying. Unlike client server database systems like Oracle, SQL Server etc. this is not supported by Access per se. It can be simulated, however, and I long ago created an Access file which does this by progressively writing rows to a table in an external database created at runtime. I won't go down that road at present, however, as I don't think it's what you are looking for. If I'm wrong let me know and I'll attach the file here.
Last edited: