3

I've got a mission-critical Access 2003 database that changed from a local MDB, to an MDB frontend with the backend on MS SQL Server 2005, using the Microsoft SQL Server Database Migration Assistant (SSMA) software.

Now, I need to permanently change the server that the tables are linked to from an IP address (which is changing soon) to a hostname pointing to the same server. The server itself is not changing, just the connection string.

It's a DSN-less connection, so the ODBC info is contained within the Access MDB file. If I try to refresh the table links within Access, it prompts me for a DSN (which I don't want to use).

I've done some Googling, and I've found several scraps of code to have it update itself each time the program launches. But, I'm worried that that could potentially introduce problems or delays for the users. Is that my best option, or is there some trick to permanently change the connection string stored within the MDB?

sentinel23
  • 51
  • 3
  • 6

2 Answers2

1

You can use VBA to alter the .Connect properties for your linked TableDef s.

See this sample from the Immediate window. (I used Replace() simply to split up that long line.)

? Replace(CurrentDb.TableDefs("remote_table").Connect, ";", ";" & vbCrLf)
ODBC;
DRIVER=SQL Server Native Client 10.0;
SERVER=HP64\SQLEXPRESS;
Trusted_Connection=Yes;
APP=Microsoft Office 2003;
WSID=WIN732B;
DATABASE=testbed;

So I could build a new string with a different SERVER, and assign the new string to the TableDef .Connect property.

If this is intended to be a permanent change you should only need to do it one time, not every time you open the database.

When I've done similar connection changes, it has been between different servers. So I deleted the TableDef and re-created it anew, to make sure Access didn't keep any cached meta information about that connection which would now be out of date. However, in your case, you're dealing with the same physical server, just referencing it by name instead of IP. I doubt the cached information would be a concern for you.

HansUp
  • 95,961
  • 11
  • 77
  • 135
1

The following code has served me well for years:

Function LinkTable(DbName As String, SrcTblName As String, _
                   Optional TblName As String = "", _
                   Optional ServerName As String = DEFAULT_SERVER_NAME, _
                   Optional DbFormat As String = "ODBC") As Boolean
Dim db As dao.Database
Dim TName As String, td As TableDef

    On Error GoTo Err_LinkTable

    If Len(TblName) = 0 Then
        TName = SrcTblName
    Else
        TName = TblName
    End If

    'Do not overwrite local tables.'
    If DCount("*", "msysObjects", "Type=1 AND Name=" & Qt(TName)) > 0 Then
        MsgBox "There is already a local table named " & TName
        Exit Function
    End If

    Set db = CurrentDb
    'Drop any linked tables with this name'
    If DCount("*", "msysObjects", "Type In (4,6,8) AND Name=" & Qt(TName)) > 0 Then
        db.TableDefs.Delete TName
    End If

    With db
        Set td = .CreateTableDef(TName)
        td.Connect = BuildConnectString(DbFormat, ServerName, DbName)
        td.SourceTableName = SrcTblName
        .TableDefs.Append td
        .TableDefs.Refresh
        LinkTable = True
    End With

Exit_LinkTable:
    Exit Function
Err_LinkTable:
    'Replace following line with call to error logging function'
    MsgBox Err.Description
    Resume Exit_LinkTable
End Function



Private Function BuildConnectString(DbFormat As String, _
                                    ServerName As String, _
                                    DbName As String, _
                                    Optional SQLServerLogin As String = "", _
                                    Optional SQLServerPassword As String = "") As String
    Select Case DbFormat
    Case "NativeClient10"
        BuildConnectString = "ODBC;" & _
                             "Driver={SQL Server Native Client 10.0};" & _
                             "Server=" & ServerName & ";" & _
                             "Database=" & DbName & ";"
        If Len(SQLServerLogin) > 0 Then
            BuildConnectString = BuildConnectString & _
                                 "Uid=" & SQLServerLogin & ";" & _
                                 "Pwd=" & SQLServerPassword & ";"
        Else
            BuildConnectString = BuildConnectString & _
                                 "Trusted_Connection=Yes;"
        End If

    Case "ADO"
        If Len(ServerName) = 0 Then
            BuildConnectString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                                 "Data Source=" & DbName & ";"
        Else
            BuildConnectString = "Provider=sqloledb;" & _
                                 "Server=" & ServerName & ";" & _
                                 "Database=" & DbName & ";"
            If Len(SQLServerLogin) > 0 Then
                BuildConnectString = BuildConnectString & _
                                     "UserID=" & SQLServerLogin & ";" & _
                                     "Password=" & SQLServerPassword & ";"
            Else
                BuildConnectString = BuildConnectString & _
                                     "Integrated Security=SSPI;"
            End If
        End If
    Case "ODBC"
        BuildConnectString = "ODBC;" & _
                             "Driver={SQL Server};" & _
                             "Server=" & ServerName & ";" & _
                             "Database=" & DbName & ";"
        If Len(SQLServerLogin) > 0 Then
            BuildConnectString = BuildConnectString & _
                                 "Uid=" & SQLServerLogin & ";" & _
                                 "Pwd=" & SQLServerPassword & ";"
        Else
            BuildConnectString = BuildConnectString & _
                                 "Trusted_Connection=Yes;"
        End If
    Case "MDB"
        BuildConnectString = ";Database=" & DbName
    End Select
End Function


Function Qt(Text As Variant) As String
Const QtMark As String = """"
    If IsNull(Text) Or IsEmpty(Text) Then
        Qt = "Null"
    Else
        Qt = QtMark & Replace(Text, QtMark, """""") & QtMark
    End If
End Function
mwolfe02
  • 23,787
  • 9
  • 91
  • 161
  • Seems like it would work... how would I go about calling this function? – sentinel23 Apr 24 '12 at 22:21
  • `LinkTable "MyDatabase", "Employees", , "HostName"` – mwolfe02 Apr 24 '12 at 23:41
  • You'll have to do that for each table you want to relink. You can iterate through the `TableDefs` connection to automate the process if you'd like. – mwolfe02 Apr 24 '12 at 23:42
  • K, I got it to work with a bit of tweaking, but I can't get it to save the username and password as it did before. Even if I hard-code the connect string, the UID and PWD get ignored. Any ideas? `ODBC;DRIVER=SQL Server;SERVER=odbcmssql;UID=database_login;PWD=database_password;APP=SSMA;WSID=odbcmssql;DATABASE=database_name;` – sentinel23 Apr 25 '12 at 17:32
  • I normally use Windows Authentication with SQL Server, so I can't really offer you any advice on that. Maybe something here would help: http://support.microsoft.com/kb/207823? – mwolfe02 Apr 25 '12 at 18:19
  • OK, I'll take a look and keep googling. Thanks for the reply. :) – sentinel23 Apr 25 '12 at 18:30
  • @sentinel23, here's what I'm using for connection string (SQL Server 2008 Express). `ODBC;DRIVER={SQL Server Native Client 10.0};Server=ServerName;Database=DatabaseName;Uid=MySQLServerUserName;Pwd=MySQLServerPassword;` My username and password are not saved when Access closes either. I run the routines to link/relink my ODBC tables every time that the MS Access database/GUI is opened. It's the first thing that runs. – HK1 Apr 25 '12 at 20:26
  • I found what I needed -- I added this line in the `With db` section: `td.Attributes = dbAttachSavePWD` Then the username and password show up in the stored connection string when I run @HansUp's code, and I don't get prompted. Thanks to everyone for your help! :) – sentinel23 Apr 25 '12 at 22:13