5

Related question: Multivalued Fields a Good Idea?

I know that multi-valued fields are similar to many-to-many relationship. What is the best way to replace multi-valued fields in an MS Access application? I have an application that has multi-valued fields. I am not sure how exactly to do away with those and implement exactly same logic in the form of fields that are single-valued?

What would be the implementation in terms of table-relationships when I want to move a multi-valued relationship to single-valued one.

Thank you.

Community
  • 1
  • 1
Jay
  • 1,210
  • 9
  • 28
  • 48
  • I wouldn't say that they are similar to many-to-many relationships, I haven't read them in detail but don't imagine you could use multi-valued fields for the PK's & FK's. Are you able to tell us more about how extensively they are used in your database, how many tables, fields, values etc. It appears you will need to write some VBA logic to strip them out but first we need more structure details. – Matt Donnan Nov 22 '12 at 08:38
  • 1
    Multi-valued fields are indeed like many-to-many relationships, contrary to Matt Donnan's assumption. Multi-valued fields cannot themselves be the PK's & FK's, but they are *implemented* by Access "behind the scenes" by using separate system value and junction tables. – C Perkins Jul 07 '16 at 20:48

3 Answers3

4

The following is probably far more detailed than you need, but it is intended for a beginner. Let us say you have a table, MainTable:

ID -> Numeric, primary key
Title -> Text
Surname -> Text
Address -> Text
Country -> Numeric

You will probably want a list of titles and countries from which to select.

In the case of Title, it would not be the worst thing to store the information in a field in a table, because you have a single column and the data is unlikely to change, and you probably will not be creating a query using the data.

Country is a different story, conventionally you would store a number and have a look-up table. It is the kind of situation where people are tempted to use a multi-value field.

However, convention is a lot easier. Add another table for country:

ID -> Numeric, primary key
Country -> Text

You might like to call the related field in the main table CountryID. You can now create a relationship in the relationship window showing how Country relates to MainTable:

relationship

You can see that Enforce Referential Integrity is selected, which means that you must have null or a country from the countries table in the CountryID field.

To view the data, you can create a query:

SELECT 
    MainTable.ID, 
    MainTable.Title, 
    MainTable.Surname, 
    MainTable.Address, 
    Country.Country
FROM Country 
INNER JOIN MainTable 
ON Country.ID = MainTable.CountryID;

query

But the main point is to have a form that allows data entry. You can create a form using the wizards, but after that, you either need to right-click CountryID and change it to a combobox or add a combobox or listbox using the wizard. Option 2 is probably the easiest. Here are most of the steps from the wizard:

combo1 combo2 combo3 combo4 combo5

You now have a dropdown list of countries on your form.

form

See also: create form to add records in multiple tables

In Access 2010, there are new ways of adding values to combos when the user enters data that does not exist in the table of possible values. In previous versions (although I am not sure about 2007), you would use the Not In List event to add items to a look-up table, in 2010, you have a choice of adding a List Items Edit form to the property sheet.

add item to lookup table1 add item to lookup table2

Community
  • 1
  • 1
Fionnuala
  • 90,370
  • 7
  • 114
  • 152
  • 1
    Thanks Remou for the answer. Lets say for the table that you have shown, I want to have a record as follows. ID: 1 Title: Mr. Surname: Watson As far as the country is concerned, I want to relate 2 countries with this record (In case of multi-valued country field, I would have got an option to store name of both the countries in the same Country field.). How can we avoid using multi-valued fields; still get the same behaviour from the database. Is there a way to achieve such behaviour? – Jay Nov 23 '12 at 08:54
  • 1
    Yes, you will need a junction table. This will contain PersonID and CountryID with a unique index on the combined fields. For example: http://stackoverflow.com/questions/1356492/populate-a-many-to-many-table-with-access/1356740#1356740 – Fionnuala Nov 23 '12 at 10:09
  • 3
    This is NOT an answer and does not allow the user to select more then one value for the choice, and thus is NOT multi-value. – Albert D. Kallal Apr 09 '16 at 23:03
1

The question is rather odd since it asks about a single-value field, but also asks about table-relationships. In a very strict interpretation, a multi-value field (MVF) could be replaced with a single TextBox filled with comma-separated items... no table-relationships required. Instead, I assume by "single-value" field that the question means standard fields in a multi-table relationship, in which each field of each related row has a single value. But each primary record can still be related to multiple rows in the related value table, which preserves the whole purpose of the MVF.

Consider the database outline below to illustrate a possible replacement for the MVF. I'm not including every possible property or how to create basic object, just what's necessary for creating desired behavior--assuming enough knowledge of Access to "fill in the blanks" and no fear of basic code or SQL.

The basic structure consists of three tables: 1) Primary table, 2) "value list" table, 3) junction table used to define many-to-many relationship.

  • Customer Table
    CustomerID: autonumber, primary
    CustomerName: short text
  • Codes Table
    Code: short text, length 5, primary key
    Description: short text
  • [Customer Codes] Table
    CustomerID: long
    Code: short text

Create relationships between the tables. This will require appropriate indexes defined on the tables (not detailed here).

  • Customer Table to [Customer Codes] Table
    CustomerID -> CustomerID fields (with enforce integrity enabled)
  • Code Table to [Customer Codes] Table
    Code -> Code fields (with enforce integrity enabled)

(A separate ID field could also be created for the values table [e.g. Codes Table] table, but that just complicates later queries and controls, etc. In such a case, the junction table would contain another ID field and not the value directly.)

In a standard VBA module, create a function like

Public Function GetCodeList(ByVal CustomerID As Integer) As String
   Dim sSQL As String
   Dim qry As QueryDef
   Dim rs As Recordset2

   sSQL = "PARAMETERS [CustID] LONG;" & _
       " SELECT * FROM [Customer Codes] WHERE [CustomerID] = [CustID]"
   Set qry = CurrentDb.CreateQueryDef("", sSQL)
   qry.Parameters("CustID") = CustomerID
   Set rs = qry.OpenRecordset(dbOpenForwardOnly, dbReadOnly)

   Dim sCodes As String
   sCodes = ""
   Dim bFirst As Boolean
   bFirst = True

   Do Until rs.EOF
      sCodes = sCodes & IIf(bFirst, "", ",") & rs("Code")
      bFirst = False
      rs.MoveNext
   Loop

   rs.Close
   qry.Close

   GetCodeList = sCodes
End Function

Useful queries of the primary table without duplicate rows will require creating some sort of aggregate queries (i.e. Group By, Count, etc.). Simple selection could be done in a single query, for example

SELECT Customer.CustomerID, Customer.[CustomerName], GetCodeList([CustomerID]) AS Codes, Count(Customer.CustomerID) AS CountOfID
FROM Customer LEFT JOIN [Customer Codes] ON Customer.ID = [Customer Codes].CustomerID
WHERE ((([Customer Codes].Code)="Current" Or ([Customer Codes].Code)="Free"))
GROUP BY Customer.ID, Customer.[CustomerName], GetCodeList([ID]);

More complicated selection may require multiple queries, one to first select the proper records, then another to join the primary table to the first query. But honestly, these types of queries are no more complicated than what can be required to select on Multi-Valued Fields. In fact, the query syntax for MVF is non-standard and can get rather complicated and confusing, even more than having a junction table and many-to-many relationships. Behind the scenes, Access is essentially doing the same thing as I've outlined, but because it hides so much detail it make some queries even more difficult.

Regarding multi-value presentation and selection on a form, mimicking the multi-valued ComboBox exactly is not possible--mainly because the basic Access Combobox does not have a multi-selection option with the ability to show checkboxes. However, one can populate a non-bound ListBox with property [Multi Select] = Simple. On the Form_Load event, add available values (e.g. Code from the example table) to the listbox using ListBox.AddItem method. Then in the Form_Current, Form_AfterUpdate, Form_Undo events, one can add code to show and/or save the selected values. This requires more code which is probably beyond the scope here.

Technically the question asked about "moving" a MVF to another implementation. The gist is to populate the values table (e.g. Code table in the example) with the same values in the MVF list. This could be a manual process, but depends on how the MVF's ComboBox is populated. Then write a query which copies each MFV into the junction table (e.g. [Customer Code]) for the same primary record, something like

INSERT INTO [Customer Codes] ( CustomerID, Code )
SELECT Customer.CustomerID, Customer.TestMVF.Value
FROM Customers
WHERE (((Customers.TestMVF.Value) Is Not Null));

A full implementation is definitely not a simple task overall, but if you find too many problems with MVFs or if you are wanting to migrate to another database, this kind of change will be necessary to understand.

C Perkins
  • 3,733
  • 4
  • 23
  • 37
0

There is no replacement for MVFs in an Access database. Some query techniques can mimic MVFs but you may find MVF functionality to be superior. 1. It is fast and very easy to implement. No code and no SQL. 2. It is visual and therefore it is intuitive for the user. There are some things that you cannot do with an MVF so you really need to decide what is more important.

Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
  • 2
    "No code and no SQL" is not useful, since the amount of code and SQL in any Access database depends on the ultimate desired/required behavior. Much can be done without code, but many things require code and/or working with SQL--a very general statement not limited to MVF's. Stating that "there are some things that you cannot do" is also rather useless, because finding out precisely what the limitations are is not trivial. Lastly, it is indeed possible to duplicate much of the behavior of multi-valued fields with a junction table and custom functions to facilitate queries, etc. – C Perkins Jul 07 '16 at 19:19
  • 2
    The MVF control allows one to add a multiple choice UI to a form and do so without code. There are few if any systems I know that are code free like Access for this ability. This feature allows non developers to create applications that typical require a expensive developer. The idea that everyone has to learn to use a standard transmission to drive a car is silly, and in this context is also silly. It is a feature that allows people to build systems without code or SQL. What's next, suggesting that everyone learn assembler to use a computer? What's next, forcing code to layout a form? – Albert D. Kallal Jul 09 '16 at 04:06
  • 1
    The replacement is a many-to-many relation with a junction table, known from standard RDB design, as they are indeed functionally equivalent. Access implements MVFs with an internal junction table, simply hiding the added complexity from the user. I believe the only limitations of MVFs are related to integration with, or porting to, other DBMS, as the junction tables need to be rebuilt first. Maybe future versions of Access will offer to do this automatically, but at the moment, the additional programming effort if the data is ever to be used outside of Access should definitely be considered. – Daniel Saner Nov 21 '16 at 09:39
  • 1
    @Albert I was emphasizing that MVFs should not be over simplified, that's all. Unless it’s an extremely simple database, it is likely that someone will want to go beyond the no-code “multiple choice UI”. I have now spent a year developing and updating a database with MVF. Otherwise simple queries which could normally be done with the Access designers (i.e. "no SQL") are not always possible with MVFs, in particular update queries and insert queries esp. with joins. Even if the MVF isn't the field being updated... often it can't even be referenced at all in the query without causing problems. – C Perkins Mar 06 '17 at 07:16