MS Access collegato alle viste del server SQL
-
10-07-2019 - |
Domanda
abbiamo un problema con un database di accesso che stiamo aggiornando per utilizzare SQL Server come archivio dati.
Questo particolare database si collega a 2 database sql, quindi ho pensato di semplificare le cose, abbiamo una vista nel database principale che si collega a ciascuna tabella nel database secondario. In questo modo l'accesso dovrebbe solo parlare direttamente con un database SQL.
Quando abbiamo collegato l'accesso alle viste del database scegliamo quali campi erano le chiavi primarie, quindi le viste non erano di sola lettura. Abbiamo un codice standard che aggiorna tutti i collegamenti quando si apre un database per rilevare eventuali modifiche e le viste collegate diventano di sola lettura perché le informazioni sulla chiave primaria vengono perse.
Esiste un modo per aggiornare i collegamenti alle viste mantenendo le informazioni sulla chiave primaria?
Giovanni
Soluzione
Ho incluso la mia intera funzione di riconnessione ODBC di seguito. Questa funzione è basata sull'idea che ho una tabella chiamata rtblODBC che memorizza tutte le informazioni di cui ho bisogno per riconnettermi. Se si implementa questa funzione, NON sarà necessario preoccuparsi di connettersi a più database SQL, poiché viene gestito senza problemi con ogni tabella da ricollegare con la propria stringa di connessione.
Quando arriverai alla fine vedrai che uso DAO per ricreare le chiavi primarie con db.Execute " CREATE INDEX " & Amp; sPrimaryKeyName & amp; & Quot; ON " & Amp; sLocalTableName & amp; " (" & amp; sPrimaryKeyField & amp; ") CON PRIMARIO; "
In caso di domande, si prega di chiedere.
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
Altri suggerimenti
Una buona parte del codice DSN in meno che ricollega le tabelle di accesso al server SQL spesso elimina prima i collegamenti, quindi ricrea il collegamento. Il codice quindi imposta la stringa di connessione. Pertanto, è l'eliminazione che ti fa perdere quella che era / è la chiave primaria.
In realtà, ti consiglio di modificare il codice di ricollegamento in modo da non eliminare i collegamenti della tabella.
Prova qualcosa del tipo:
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
Questo funziona meglio per me (nota la fine spostata se è):
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.")
Il controllo ODBC è corretto, anche se " ODBC; " la parte non viene visualizzata nella vista MSysObjects.