First Published 18 Jan 2025                                                Difficulty level :   Moderate


Section Links:
          Introduction
          Complex Data Fields
          Matching Complex Fields to the Attached Tables
          MSysComplexType Tables
          Feedback



Introduction                                                                                                                   Return To Top

This is the fifth in a series of articles about the complex datatypes that were first introduced in Access 2007.

This article discusses the 9 complex datatypes available in more detail and explains how these are managed by Access.

The four previous articles were:
•   multivalued fields (MVFs)               - see Multivalued Fields . . . and why you shouldn't use them
•   column history memo fields            - see Use Column History in Memo fields
•   attachment fields                            - see Attachment Field Issues
•   deep hidden attached tables           - see Attached, associated, detached . . .



Complex Data Fields                                                                                                       Return To Top

Access allows a wide variety of datatypes to be used in tables. All those shown in RED are complex datatypes which allow multiple values to be stored in the same field

Datatype Enums

NOTE: Datatype information taken from the Microsoft article: DataTypeEnum enumeration (DAO)

The table used below includes all 9 complex datatypes:

Complex Datatypes Table Design
Seven of these are number datatypes - Byte/Integer/Long Integer/Single/Double/Decimal/GUID (Replication ID). The other two are short text and attachment

To create a number or short text complex field in table design, click the Lookup tab, select combo box or list box as display control then set allow multiple values = Yes.
Next set the field row source based on a value list or a table/query:

Complex Datatypes Number Field Design

Complex Datatypes Text Field Design
In the table or a query, the complex field(s) will be shown as comma separated lists:

Complex Datatypes Data
In a form, the specified display control will be used. In this example, all the controls are set as listboxes:

Complex Datatypes Form
The query design has been expanded to show the multi-valued fields from the various attached tables used to store the multi-valued data

Complex Datatypes Design
Perhaps surprisingly, it is possible to create an aggregate (totals) query on the multi-valued field data

Totals Complex Datatypes
However, action queries on complex data fields can be complicated to do



Matching Complex Fields to the Attached Tables                                                       Return To Top

If you have many complex field types, it can be difficult to keep track of which hidden attached tables are matched to each field

In this example, 16 attached tables are needed for the 4 tables with complex fields:

Complex Attached Tables
Aceess uses a system table, MSysComplexColumns to keep a track of each complex table/field and attached table.

MSysComplexColumns Table
The ColumnName references the complex field names in the various tables.
The number values in the ComplexTypeObjectID field specify the complex datatype used.
All values are between 21 and 39 with the exception of the ColumnHistory data which works in a different way:

Complex Datatypes Lookup
Unlike the other complex datatypes, the ID value for ColumnHistory varies for each table/field and is negative for linked tables.

The ConceptualTableID and FlatTableID fields are used to link to the MSysObjects system table.

Using a query joining the MSysComplexColumns and MSysObjects system tables gives the attached table name for each complex datatype.

Attached Tables
The query design is:

Attached Tables Design
The query SQL used is:

SELECT DISTINCT MSysObjects.Name AS ComplexTable, MSysComplexColumns.ColumnName AS ComplexField, qryComplexDatatypesLookup.ComplexDatatype,
      MSysComplexColumns.ComplexTypeObjectID, MSysObjects_1.Name AS AttachedTableName, MSysObjects_1.Flags
FROM ((MSysObjects INNER JOIN MSysComplexColumns ON MSysObjects.Id = MSysComplexColumns.ConceptualTableID)
      INNER JOIN MSysObjects AS MSysObjects_1 ON MSysComplexColumns.FlatTableID = MSysObjects_1.Id)
      INNER JOIN qryComplexDatatypesLookup ON MSysComplexColumns.ComplexTypeObjectID = qryComplexDatatypesLookup.ComplexTypeObjectID
ORDER BY MSysObjects.Name;


The above query fails to match the additional column history system table(s) MSysComplexTypeVH_*

To do so, we need another query linking the FlatTableID field in MSysComplexColumns to the Id field in MSysObjects:

Column History Associated Table
The query design is:

Column History Query Design
The query SQL is:

SELECT DISTINCT MSysObjects.Name AS ComplexTable, MSysComplexColumns.ColumnName AS ComplexField, qryComplexDatatypesLookup.ComplexDatatype,
      MSysComplexColumns.ComplexTypeObjectID, MSysObjects_1.Name AS AttachedTableName, MSysObjects_1.Flags
FROM (MSysObjects INNER JOIN (MSysObjects AS MSysObjects_1 INNER JOIN
      MSysComplexColumns ON MSysObjects_1.Id = MSysComplexColumns.ComplexTypeObjectID) ON MSysObjects.Id = MSysComplexColumns.ConceptualTableID)
      INNER JOIN qryComplexDatatypesLookup ON MSysComplexColumns.ComplexTypeObjectID = qryComplexDatatypesLookup.ComplexTypeObjectID
WHERE MSysComplexColumns.ComplexTypeObjectID < 0 Or MSysComplexColumns.ComplexTypeObjectID > 39;


Combining the two queries as a UNION query gives a list of ALL attached tables:

ALL Attached Tables
The query SQL is:

SELECT MSysObjects.Name AS ComplexTable, MSysComplexColumns.ColumnName AS ComplexField, qryComplexDatatypesLookup.ComplexDatatype,
      MSysComplexColumns.ComplexTypeObjectID, MSysObjects_1.Name AS AttachedTableName, MSysObjects_1.Flags
FROM ((MSysObjects INNER JOIN MSysComplexColumns ON MSysObjects.Id = MSysComplexColumns.ConceptualTableID)
      INNER JOIN MSysObjects AS MSysObjects_1 ON MSysComplexColumns.FlatTableID = MSysObjects_1.Id)
      INNER JOIN qryComplexDatatypesLookup ON MSysComplexColumns.ComplexTypeObjectID = qryComplexDatatypesLookup.ComplexTypeObjectID
UNION SELECT MSysObjects.Name AS ComplexTable, MSysComplexColumns.ColumnName AS ComplexField, qryComplexDatatypesLookup.ComplexDatatype,
      MSysComplexColumns.ComplexTypeObjectID, MSysObjects_1.Name AS AttachedTableName, MSysObjects_1.Flags
FROM (MSysObjects INNER JOIN (MSysObjects AS MSysObjects_1
      INNER JOIN MSysComplexColumns ON MSysObjects_1.Id = MSysComplexColumns.ComplexTypeObjectID)
      ON MSysObjects.Id = MSysComplexColumns.ConceptualTableID)
      INNER JOIN qryComplexDatatypesLookup ON MSysComplexColumns.ComplexTypeObjectID = qryComplexDatatypesLookup.ComplexTypeObjectID
WHERE MSysComplexColumns.ComplexTypeObjectID <0 Or MSysComplexColumns.ComplexTypeObjectID > 39;


As explained in the earlier articles, the attached tables are all deep hidden and their contents cannot be viewed by standard methods.

In order to do so, I use an obscure method which is not widely known about and which I do not intend to explain here:

These tables contain the normalized data for each complex field. The screenshot below shows the data for 5 of the tables attached to complex fields in the tblTestComplexDatatypes table

Complex Data Attached Tables
All these attached tables work in the same way.



MSysComplexType Tables                                                                                               Return To Top

To add a further level of complexity, Access has another deep hidden system table for each of the 9 complex datatypes.
Column History fields also create their own MSysComplexTypeVH tables - one for each column history field

MSysComplexType Tables
I have viewed the contents of each of these tables for local and linked complex data together with linked complex data in SharePoint lists.

In my tests, the peculiar thing about each of these tables is that they ALWAYS empty:

MSysComplexType Tables
Clearly the tables are required in some way, but I have absolutely no idea what their purpose is!



Feedback                                                                                                                         Return To Top

Please use the contact form below to let me know whether you found this article interesting/useful or if you have any questions/comments.

Please also consider making a donation towards the costs of maintaining this website. Thank you



Colin Riddington           Mendip Data Systems                 Last Updated 18 Jan 2025



Return to Access Articles Page




Return to Top