MS Access lié aux vues serveur SQL
-
10-07-2019 - |
Question
nous avons un problème avec une base de données d'accès que nous mettons à niveau pour utiliser SQL Server en tant que magasin de données.
Cette base de données particulière est liée à 2 bases de données SQL. J'ai donc pensé simplifier les choses. Nous avons une vue dans la base de données principale qui est liée à chaque table de la base de données secondaire. De cette façon, l'accès n'aurait besoin que de parler directement avec une base de données SQL.
Lorsque nous avons lié l'accès aux vues de la base de données, nous avons choisi les champs qui constituaient la clé primaire. Ainsi, les vues n'étaient pas en lecture seule. Nous avons un code standard qui actualise tous les liens lorsqu'une base de données s'ouvre pour prendre en compte les modifications et les vues liées deviennent en lecture seule car les informations de la clé primaire sont perdues.
Existe-t-il un moyen d'actualiser les liens vers les vues tout en conservant les informations de clé primaire?
John
La solution
J'ai inclus toute ma fonction de reconnexion ODBC ci-dessous. Cette fonction est basée sur l’idée que j’ai une table appelée rtblODBC qui stocke toutes les informations nécessaires à la reconnexion. Si vous implémentez cette fonction, vous n'aurez plus à vous soucier de la connexion à plusieurs bases de données SQL, celle-ci étant gérée de manière fluide, chaque table à reconnecter ayant sa propre chaîne de connexion.
Lorsque vous arriverez à la fin, vous verrez que j'utilise DAO pour recréer les clés primaires avec db.Execute "CREATE INDEX". & amp; sPrimaryKeyName & amp; " ON " & amp; sLocalTableName & amp; "(" & spprimaryKeyField & ") WITH PRIMARY;"
Si vous avez des questions, n'hésitez pas à demander.
Public Function fnReconnectODBC( _
Optional bForceReconnect As Boolean _
) As Boolean
' Comments :
' Parameters: bForceReconnect -
' Returns : Boolean -
' Modified :
' --------------------------------------------------'
On Error GoTo Err_fnReconnectODBC
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim tdf As DAO.TableDef
Dim sPrimaryKeyName As String
Dim sPrimaryKeyField As String
Dim sLocalTableName As String
Dim strConnect As String
Dim varRet As Variant
Dim con As ADODB.Connection
Dim rst As ADODB.Recordset
Dim sSQL As String
If IsMissing(bForceReconnect) Then
bForceReconnect = False
End If
sSQL = "SELECT rtblODBC.LocalTableName, MSysObjects.Name, MSysObjects.ForeignName, rtblODBC.SourceTableName, MSysObjects.Connect, rtblODBC.ConnectString " _
& "FROM MSysObjects RIGHT JOIN rtblODBC ON MSysObjects.Name = rtblODBC.LocalTableName " _
& "WHERE (((rtblODBC.ConnectString)<>'ODBC;' & [Connect]));"
Set con = Access.CurrentProject.Connection
Set rst = New ADODB.Recordset
rst.Open sSQL, con, adOpenDynamic, adLockOptimistic
'Test the recordset to see if any tables in rtblODBC (needed tables) are missing from the MSysObjects (actual tables)
If rst.BOF And rst.EOF And bForceReconnect = False Then
'No missing tables identified
fnReconnectODBC = True
Else
'Table returned information, we don't have a perfect match, time to relink
Set db = CurrentDb
Set rs = db.OpenRecordset("rtblODBC", dbOpenSnapshot)
'For each table definition in the database collection of tables
For Each tdf In db.TableDefs
'Set strConnect variable to table connection string
strConnect = tdf.Connect
If Len(strConnect) > 0 And Left(tdf.Name, 1) <> "~" Then
If Left(strConnect, 4) = "ODBC" Then
'If there is a connection string, and it's not a temp table, and it IS an odbc table
'Delete the table
DoCmd.DeleteObject acTable, tdf.Name
End If
End If
Next
'Relink tables from rtblODBC
With rs
.MoveFirst
Do While Not .EOF
Set tdf = db.CreateTableDef(!localtablename, dbAttachSavePWD, !SourceTableName, !ConnectString)
varRet = SysCmd(acSysCmdSetStatus, "Relinking '" & !SourceTableName & "'")
db.TableDefs.Append tdf
db.TableDefs.Refresh
If Len(!PrimaryKeyName & "") > 0 And Len(!PrimaryKeyField & "") > 0 Then
sPrimaryKeyName = !PrimaryKeyName
sPrimaryKeyField = !PrimaryKeyField
sLocalTableName = !localtablename
db.Execute "CREATE INDEX " & sPrimaryKeyName & " ON " & sLocalTableName & "(" & sPrimaryKeyField & ")WITH PRIMARY;"
End If
db.TableDefs.Refresh
.MoveNext
Loop
End With
subTurnOffSubDataSheets
fnReconnectODBC = True
End If
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
Exit_fnReconnectODBC:
Set tdf = Nothing
Set rs = Nothing
Set db = Nothing
varRet = SysCmd(acSysCmdClearStatus)
Exit Function
Err_fnReconnectODBC:
fnReconnectODBC = False
sPrompt = "Press OK to continue."
vbMsg = MsgBox(sPrompt, vbOKOnly, "Error Reconnecting")
If vbMsg = vbOK Then
Resume Exit_fnReconnectODBC
End If
End Function
Autres conseils
Une bonne partie du code DSN moins qui lie de nouveau les tables d’accès au serveur SQL supprime souvent les liens en premier lieu, puis les recrée. Le code configure ensuite la chaîne de connexion. Ainsi, c’est la suppression qui vous fait perdre ce que la clé primaire était / est.
Je vous recommande en fait de modifier votre code de ré-association afin de ne pas supprimer les liens de la table.
Essayez quelque chose comme:
For Each tdfCurrent In dbCurrent.TableDefs
If Len(tdfCurrent.Connect) > 0 Then
If Left$(tdfCurrent.Connect, 5) = "ODBC;" Then
strCon = "ODBC;DRIVER={sql server};" & _
"SERVER=" & ServerName & ";" & _
"DATABASE=" & DatabaseName & ";" & _
"UID=" & UserID & ";" & _
"PWD=" & USERpw & ";" & _
"APP=Microsoft Office 2003;" & _
"WSID=" & WSID & ";"
End If
End If
tdfCurrent.Connect = strCon
tdfCurrent.RefreshLink
End If
Next tdfCurrent
Cela fonctionne un peu mieux pour moi (notez la fin déplacée):
Dim dbCurrent As Database
Set dbCurrent = CurrentDb()
StatusList.SetFocus
StatusList.AddItem ("starting... ")
I = DoEvents()
Dim tdfCurrent As DAO.TableDef
For Each tdfCurrent In dbCurrent.TableDefs
If Len(tdfCurrent.Connect) > 0 Then
If Left$(tdfCurrent.Connect, 5) = "ODBC;" Then
strCon = "ODBC;DRIVER={sql server};" & _
"SERVER=" & ServerName & ";" & _
"DATABASE=" & DatabaseName & ";" & _
"UID=" & UserID & ";" & _
"PWD=" & USERpw & ";" & _
"APP=Microsoft Office 2003;" & _
"WSID=" & WSID & ";"
StatusList.AddItem ("fixing " & tdfCurrent.Name)
tdfCurrent.Connect = strCon
tdfCurrent.RefreshLink
End If
End If
I = DoEvents()
Next tdfCurrent
StatusList.AddItem ("----Done.")
La vérification ODBC est correcte, même si la commande "ODBC;" la partie ne s'affiche pas dans la vue MSysObjects.