Ms-access – How to refresh linked tables in an Access mdb when ODBC changes


I can create an Access mdb and add a linked table to an Sql Server database via ODBC. If I change the Sql Server that the ODBC is connecting to with the ODBC control panel applet the mdb still connects to the original Sql Server until Access is restarted.

Is there a way to relink these linked server tables without restarting Access?

EDIT: I would like to do this in code

Best Solution

You can use the code below to refresh all ODBC tables in your Access project to a given DSN.

How to use it

Just copy the code in a new or existing VBA module and, where you want to refresh the links, call it with the proper DSN for the new ODBC connection:

RefreshODBCLinks "ODBC;DRIVER=SQL Server Native Client 10.0;" & _"
                 "SERVER=SQLSERVER;UID=Administrator;" & _
                 "Trusted_Connection=Yes;" & _
                 "APP=2007 Microsoft Office system;DATABASE=OrderSystem;"

Also, have a look at the Access help for the TableDef.RefreshLink method.

Code version 1

Classic way of relinking but Access may keep connection information in memory if the tables have been used before RefreshODBCLinks is called.

Public Sub RefreshODBCLinks(newConnectionString As String)
    Dim db As DAO.Database
    Dim tb As DAO.TableDef
    Set db = CurrentDb
    For Each tb In db.TableDefs
        If Left(tb.Connect, 4) = "ODBC" Then
            tb.Connect = newConnectionString
            Debug.Print "Refreshed ODBC table " & tb.Name
        End If
    Next tb
    Set db = Nothing
End Sub

Code version 2

This will completely re-create the ODBC linked tables: the old ones will be renamed, then new tables using the given DSN will be created before deleting the old linked version.
Please make sure you test this and maybe add some code to better handle errors as necessary.

Note also that the parameter dbAttachSavePWD passed during creation of the ODBC table will save the ODBC password (if any) in Access. Just remove it if that's not what you need.

Public Sub RefreshODBCLinks(newConnectionString As String)
    Dim db As DAO.Database
    Dim tb As DAO.TableDef
    Dim originalname As String
    Dim tempname As String
    Dim sourcename As String
    Dim i As Integer

    Set db = CurrentDb
    ' Get a list of all ODBC tables '
    Dim tables As New Collection
    For Each tb In db.TableDefs
        If (Left(tb.Connect, 4) = "ODBC") Then
            tables.Add Item:=tb.Name, key:=tb.Name
        End If
    Next tb

    ' Create new tables using the given DSN after moving the old ones '
    For i = tables.count To 1 Step -1
            originalname = tables(i)
            tempname = "~" & originalname & "~"
            sourcename = db.TableDefs(originalname).SourceTableName
            ' Create the replacement table '
            db.TableDefs(originalname).Name = tempname
            Set tb = db.CreateTableDef(originalname, dbAttachSavePWD, _
                                        sourcename, newConnectionString)
            db.TableDefs.Append tb
            ' delete the old table '
            DoCmd.DeleteObject acTable, tempname
            tables.Remove originalname
            Debug.Print "Refreshed ODBC table " & originalname
    Next i
    Set db = Nothing
End Sub

One last thing: if you're still getting issues that require that you restart Access for the changes to be visible, then have a look at my code in Restarting and compacting the database programmatically on my site.

Note: Code Version 2 was inspired in part from this Access Web article.