Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The MS Access Jet/ACE db engine does not support UPDATEs via subqueries (<a href="http://allenbrowne.com/ser-61.html" rel="nofollow" title="Why is my query read-only?">among other limitations</a>).</p> <p>You have three primary options:</p> <h2>Option 1: Temporary Table</h2> <p>Run your subquery as a "Make Table" query first:</p> <pre><code>SELECT Call.MachineId, Visit.PersonId AS Person INTO temp_T FROM Call INNER JOIN Visit ON Call.CallId = Visit.CallId ORDER BY Visit.Date DESC </code></pre> <p>Then use the resulting temporary table to do your update:</p> <pre><code>UPDATE Details SET Details.PersonId = t.Person FROM Details INNER JOIN temp_T AS t ON Details.MachineId = t.MachineId </code></pre> <h2>Option 2: Select Query and Domain Aggregate Function</h2> <p>Create and save a select query and then use a DLookup when setting the value in your UPDATE query. You need to save the select query because the stock DLookup function does not allow you to specify a sort order.</p> <pre><code>SELECT Call.MachineId, Visit.PersonId FROM Call INNER JOIN Visit ON Call.CallId = Visit.CallId ORDER BY Visit.Date DESC </code></pre> <p>Save the above to a query named LastCalledTech. Then change your UPDATE query to:</p> <pre><code>UPDATE Details SET Details.PersonId = DLookup("PersonID", "LastCalledTech", "MachineID=" &amp; Details.MachineID) </code></pre> <h2>Option 3: Modified DLookup() Custom Function</h2> <p>Allen Browne wrote an <a href="http://allenbrowne.com/ser-42.html" rel="nofollow" title="Extended DLookup&#40;&#41;">"extended" DLookup function</a> that allows you to specify a sort order. I further modified the function slightly to allow passing in an arbitrary SELECT statement (not just a table or query name). We don't actually need the sort parameter in this case because it is more efficient to simply include it in the SELECT SQL string. Using this function (which I've posted below), you would execute the following UPDATE query:</p> <pre><code>UPDATE Details SET Details.PersonId = ELookup("PersonID", "SELECT Call.MachineId, Visit.PersonId FROM Call INNER JOIN Visit ON Call.CallId = Visit.CallId ORDER BY Visit.Date DESC", "MachineID=" &amp; Details.MachineID) </code></pre> <p>And here is the modified function:</p> <pre><code>Public Function ELookup(Expr As String, Domain As String, Optional Criteria As Variant, _ Optional OrderClause As Variant) As Variant On Error GoTo Err_ELookup 'Purpose: Faster and more flexible replacement for DLookup() 'Arguments: Same as DLookup, with additional Order By option. 'Return: Value of the Expr if found, else Null. ' Delimited list for multi-value field. 'Author: Allen Browne. allen@allenbrowne.com 'Updated: December 2006, to handle multi-value fields (Access 2007 and later.) ' {by mwolfe02} Add parentheses to allow passing arbitrary SELECT statements 'Examples: ' 1. To find the last value, include DESC in the OrderClause, e.g.: ' ELookup("[Surname] &amp; [FirstName]", "tblClient", , "ClientID DESC") ' 2. To find the lowest non-null value of a field, use the Criteria, e.g.: ' ELookup("ClientID", "tblClient", "Surname Is Not Null" , "Surname") 'Note: Requires a reference to the DAO library. Dim db As DAO.Database 'This database. Dim rs As DAO.Recordset 'To retrieve the value to find. Dim rsMVF As DAO.Recordset 'Child recordset to use for multi-value fields. Dim varResult As Variant 'Return value for function. Dim strSql As String 'SQL statement. Dim strOut As String 'Output string to build up (multi-value field.) Dim lngLen As Long 'Length of string. Const strcSep = "," 'Separator between items in multi-value list. 'Initialize to null. varResult = Null 'Build the SQL string. strSql = "SELECT TOP 1 " &amp; Expr &amp; " FROM (" &amp; Domain &amp; ")" If Not IsMissing(Criteria) Then strSql = strSql &amp; " WHERE " &amp; Criteria End If If Not IsMissing(OrderClause) Then strSql = strSql &amp; " ORDER BY " &amp; OrderClause End If strSql = strSql &amp; ";" 'Lookup the value. Set db = DBEngine(0)(0) Set rs = db.OpenRecordset(strSql, dbOpenForwardOnly) If rs.RecordCount &gt; 0 Then 'Will be an object if multi-value field. If VarType(rs(0)) = vbObject Then Set rsMVF = rs(0).Value Do While Not rsMVF.EOF If rs(0).Type = 101 Then 'dbAttachment strOut = strOut &amp; rsMVF!FileName &amp; strcSep Else strOut = strOut &amp; rsMVF![Value].Value &amp; strcSep End If rsMVF.MoveNext Loop 'Remove trailing separator. lngLen = Len(strOut) - Len(strcSep) If lngLen &gt; 0&amp; Then varResult = Left(strOut, lngLen) End If Set rsMVF = Nothing Else 'Not a multi-value field: just return the value. varResult = rs(0) End If End If rs.Close 'Assign the return value. ELookup = varResult Exit_ELookup: Set rs = Nothing Set db = Nothing Exit Function Err_ELookup: MsgBox Err.Description, vbExclamation, "ELookup Error " &amp; Err.number Resume Exit_ELookup End Function </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload