06. juni 2002 - 13:29Der er
34 kommentarer og 1 løsning
Access med ODBC til SQL70 Base i flere miljøer
Hej..
Jeg har følgende opsætning:
1 stk SQL7.0 Base 1 stk Access Base på en anden maskine. 1 stk ODBC-forbindelse mellem de 2 ovenstående.
I Access basen har jeg 3 linkede tabeller via ODBC til 3 tabeller på SQL7.0 Basen.
Mit problem ligger nu i, at hvis jeg kopierer Access basen over i et identisk miljø (miljø2), hvor kun maskin-navnene er forskellige, så forsøger den stadig at trække på den oprindelige server(i miljø1),selvom ODBC'en peger på den nye server (i miljø2).
Jeg bruger NT4.0 (med Sixpacken på) og Access 97.
Jeg kan godt gå ind og genoprette de 3 tabeller manuelt, men basen skal bruges i en "unattended" installation, og genoprettelsen skal derfor ske automatisk.
It would also be an idea to refresh the links each time you open the database, this way its easy to chnage between a test SQL database and a production database
Sub RefreshLinkX()
Dim dbsCurrent As Database Dim tdfLinked As TableDef
' Open a database to which a linked table can be ' appended. Set dbsCurrent = OpenDatabase("DB1.mdb")
' Create a linked table that points to a Microsoft ' SQL Server database. Set tdfLinked = _ dbsCurrent.CreateTableDef("AuthorsTable") tdfLinked.Connect = _ "ODBC;DATABASE=pubs;UID=sa;PWD=;DSN=Publishers" tdfLinked.SourceTableName = "authors" dbsCurrent.TableDefs.Append tdfLinked
' Display contents of linked table. Debug.Print _ "Data from linked table connected to first source:" RefreshLinkOutput dbsCurrent
' Change connection information for linked table and ' refresh the connection in order to make the new data ' available. tdfLinked.Connect = _ "ODBC;DATABASE=pubs;UID=sa;PWD=;DSN=NewPublishers" tdfLinked.RefreshLink
' Display contents of linked table. Debug.Print _ "Data from linked table connected to second source:"
RefreshLinkOutput dbsCurrent
' Delete linked table because this is a demonstration. dbsCurrent.TableDefs.Delete tdfLinked.Name
dbsCurrent.Close
End Sub
Sub RefreshLinkOutput(dbsTemp As Database)
Dim rstRemote As Recordset Dim intCount As Integer
' Open linked table. Set rstRemote = _ dbsTemp.OpenRecordset("AuthorsTable")
intCount = 0
' Enumerate Recordset object, but stop at 50 records. With rstRemote Do While Not .EOF And intCount < 50
Debug.Print , .Fields(0), .Fields(1) intCount = intCount + 1 .MoveNext Loop If Not .EOF Then Debug.Print , "[more records]" .Close End With
Den kaldes således: call Sammenkæd_Tabeller("Navn på en af dine tabeller")
Her er koden: Public Function Sammenkæd_Tabeller(Tbl As String) As Boolean On Error GoTo Err_reattach Dim db As Database Dim tdef As TableDef, qdef As QueryDef Dim ConStr As String, OldConStr As String Dim ConnectString As String, tblSourceName As String, tblName As String, n As Integer Set db = CurrentDb Set tdef = db.TableDefs(Tbl) tblSourceName = tdef.SourceTableName ConStr = tdef.Connect
If ConStr = "" Then Sammenkæd_Tabeller = False Exit Function End If DoCmd.Hourglass True For Each tdef In db.TableDefs '<<----Hvis tabellen er tilknyttet---->> If Left(tdef.Connect, 5) = "ODBC;" Then tblName = tdef.Name tdef.Connect = ConStr tdef.RefreshLink End If Next tdef
DoCmd.Hourglass False Sammenkæd_Tabeller = True Exit Function Err_reattach: DoCmd.Hourglass False Select Case Err Case 3011: If MsgBox("Table " & tblName & " wasn't reattached@@Do you wish to continue reattaching tables?", vbQuestion + vbYesNo, "Continue?") = vbNo Then Sammenkæd_Tabeller = False Exit Function End If Case Else If MsgBox(Err.Description & vbNewLine & tblName & vbNewLine & tblSourceName & "@@Do you wish to continue reattaching tables?", vbQuestion + vbYesNo, "Continue?") = vbNo Then Sammenkæd_Tabeller = False Exit Function End If End Select DoCmd.Hourglass True Resume Next End Function
Lad os lige få noget på det rene: Du har 2 maskiner, som skal trække på 2 forskellige SQL servere? Du siger at ODBC peger på den aktuelle server? Med ODBC, mener du da din Datakilde i ODBC-indstillinger i kontrolpanelet? Den har nemlig ikke direkte noget at gøre med hvor tabellerne peger hen. Access bruger kun ODBC datakilderne til at guide sig vej. Herefter gemmer den selv en connectstreng.
You can also open the table in design view then right click and choose properties from the menu. If you now look at the description you will see the connection string Access is using to try and attach to the dB. This will show the string used from "miljø 1", and this is why you need to refresh the connection string.
Public Sub Attach(ConStr As String) On Error GoTo Err_reattach Dim db As Database, tblName As String Dim tdef As TableDef, qdef As QueryDef Set db = CurrentDb
If ConStr = "" Then Exit Sub End If DoCmd.Hourglass True
For Each tdef In db.TableDefs '<<----Hvis tabellen er tilknyttet---->> If Left(tdef.Connect, 5) = "ODBC;" Then tblName = tdef.Name tdef.Connect = ConStr tdef.RefreshLink End If Next tdef For Each qdef In db.QueryDefs If qdef.Connect <> "" Then qdef.Connect = ConStr End If Next qdef DoCmd.Hourglass False Exit Sub Err_reattach: DoCmd.Hourglass False Select Case Err Case 3011: If MsgBox("Table " & tblName & " wasn't reattached@@Do you wish to continue reattaching tables?", vbQuestion + vbYesNo, "Continue?") = vbNo Then Exit Sub End If Case Else If MsgBox(Err.Description & vbNewLine & tblName & "@@Do you wish to continue reattaching tables?", vbQuestion + vbYesNo, "Continue?") = vbNo Then Exit Sub End If End Select DoCmd.Hourglass True Resume Next End Sub
Du skal således have fat i de 2 connect-strenge.
På hver maskine kalder du så f.eks. denne: Attach "ODBC;DRIVER=SQL Server;SERVER=SQLservery;APP=Microsoft® Access;DATABASE=VKD;LANGUAGE=Dansk"
Da jeg ikke på forhånd har Miljø 2 fast defineret, det hele skal gøres med en unattended installation. ALT skal findes automatisk og ALT skal rettes automatisk.. DVS lægges ind i AUTOEXEC og startes hver gang basen røres...
Du kan jo ikke connecte hvis du slet ikke ved hvad serveren eller databasen hedder!?
Du kan heller ikke stille dig tilfreds med at brugeren skal indtaste bare Server-navnet? For så kan du jo selv sammensætte connectstrengen, hvis alt det andet er fastdefineret.
Men...ODBC-forbindelsen er jo netop den streng, som jeg har refereret til flere gange ("ODBC;DRIVER=SQL Server;SERVER=SQLservery;APP=Microsoft® Access;DATABASE=VKD;LANGUAGE=Dansk")
Du kan definere en ODBC datakilde, som peger på databasen, men så kræver det jo at brugeren har lavet denne datakilde (DSN). Og for at kunne oprette den DSN, så skal man angive servernavn, database samt brugernavn/passwrd.
Jeg mener, for at skære det ud i pap, at man har på forhånd været indi i kontrol-panelet under ODBC-forbindelser og oprette den pågældende forbindelse.
wizax>This example will also create the ODBC data source if it doesnt already exist.
Create a new database called TestODBC.mdb.
Create the following table to store SQL Server ODBC data source information. You can modify the fields in this table to store the DSN information for any ODBC driver:
Table: tblODBCDataSources Field Name Data Type Field Size
DataBase Text 50 UID Text 50 PWD Text 50 Server Text 50 ODBCTableName Text 50 LocalTableName Text 50 DSN Text 50
Make the LocalTableName field the primary key, and save the table as tblODBCDataSources.
Create a record in the tblODBCDataSources table with information about your ODBC databases. This example uses a SQL Server connection to the Authors table in the Pubs database; substitute the correct information for your environment, and add a record for each linked table in your database:
Field Name Value Database Pubs UID sa PWD <blank> Server SQLPUBS ODBCTableName dbo.authors LocalTableName Authors DSN Pubs
Create a module and type the following line in the Declarations section if it is not already there:
Option Explicit Type the following procedures:
NOTE: The sample code in this article uses Microsoft Data Access Objects. For this code to run properly, you must reference the Microsoft DAO 3.6 Object Library. To do so, click References on the Tools menu in the Visual Basic Editor, and ensure that the Microsoft DAO 3.6 Object Library check box is selected.
'*************************************************************** 'The DoesTblExist function validates the existence of a TableDef 'object in the current database. The result determines if an 'object should be appended or its Connect property refreshed. '*************************************************************** Function DoesTblExist(strTblName As String) As Boolean On Error Resume Next Dim db As DAO.Database, tbl As DAO.TableDef Set db = CurrentDb Set tbl = db.TableDefs(strTblName) If Err.Number = 3265 Then ' Item not found. DoesTblExist = False Exit Function End If DoesTblExist = True End Function
Function CreateODBCLinkedTables() As Boolean On Error GoTo CreateODBCLinkedTables_Err Dim strTblName As String, strConn As String Dim db As DAO.Database, rs As DAO.Recordset, tbl As DAO.TableDef ' --------------------------------------------- ' Register ODBC database(s). ' --------------------------------------------- Set db = CurrentDb Set rs = db.OpenRecordset("tblODBCDataSources") With rs While Not .EOF DBEngine.RegisterDatabase rs("DSN"), _ "SQL Server", _ True, _ "Description=VSS - " & rs("DataBase") & _ Chr(13) & "Server=" & rs("Server") & _ Chr(13) & "Database=" & rs("DataBase") ' --------------------------------------------- ' Link table. ' --------------------------------------------- strTblName = rs("LocalTableName") strConn = "ODBC;" strConn = strConn & "DSN=" & rs("DSN") & ";" strConn = strConn & "APP=Microsoft Access;" strConn = strConn & "DATABASE=" & rs("DataBase") & ";" strConn = strConn & "UID=" & rs("UID") & ";" strConn = strConn & "PWD=" & rs("PWD") & ";" strConn = strConn & "TABLE=" & rs("ODBCTableName") If (DoesTblExist(strTblName) = False) Then Set tbl = db.CreateTableDef(strTblName, _ dbAttachSavePWD, rs("ODBCTableName"), _ strConn) db.TableDefs.Append tbl Else Set tbl = db.TableDefs(strTblName) tbl.Connect = strConn tbl.RefreshLink End If
rs.MoveNext Wend End With CreateODBCLinkedTables = True MsgBox "Refreshed ODBC Data Sources", vbInformation CreateODBCLinkedTables_End: Exit Function CreateODBCLinkedTables_Err: MsgBox Err.Description, vbCritical, "MyApp" Resume CreateODBCLinkedTables_End End Function
To test this function, type the following line in the Immediate window, and then press ENTER:
?CreateODBCLinkedTables()
Note that you receive the message "Refreshed ODBC Data Sources." Also note that a new linked table called Authors exists in your database, and a new User DSN called Pubs exists in the ODBC Administrator in Control Panel.
Hi Terry... Thanks for the attempts of heling me, but I feel like you and Thomas do not understand my problem completely....
1) The links must be reconnected in AUTOEXEC. 2) NO POPUPS/MESSAGES/TEXT may be shown, and NO user intervention. 3) The ODBC-links are defined in NT, and SOULD NOT BE CREATED. 4) The solution MUST be generic, so It will reconnect ALL links. If possible search for the tables itself.
Sorry if I sound demanding or rude, but point 1-3 has already been pointed out (several times), and they are _essential_ for the implementation of this fix.
remark: I have NO knowledge of code in Access, and therefore I cannot make adjustments to the code delivered by you....
Wizax>This DOES work with an existing ODBC data source and NO PROMPTS.
If you are using NT logins then you should remove the two lines which look like this strConn = strConn & "UID=" & gsUserName & ";" strConn = strConn & "PWD=" & gsPassword & ";" Then you can make a call to the function MyRefreshLinks() from autoexec.
If you are need to enter a user name and password then you need to make a login form. Then set the two variables gsUserName and gsPassword and then call the function MyRefreshLinks()
In BOTH cases you need to enter the DSN and table names in the table tblODBCDataSources.
Copy the following into a Module
Global gsUserName As String Global gsPassword As String
'*************************************************************** 'The DoesTblExist function validates the existence of a TableDef 'object in the current database. The result determines if an 'object should be appended or its Connect property refreshed. '*************************************************************** Function DoesTblExist(strTblName As String) As Boolean On Error Resume Next Dim db As DAO.Database, tbl As DAO.TableDef Set db = CurrentDb Set tbl = db.TableDefs(strTblName) If Err.Number = 3265 Then ' Item not found. DoesTblExist = False Exit Function End If DoesTblExist = True End Function
Function MyRefreshLinks() As Boolean On Error GoTo MyRefreshLinks_Err Dim strTblName As String, strConn As String Dim db As DAO.Database, rs As DAO.Recordset, tbl As DAO.TableDef ' --------------------------------------------- ' Register ODBC database(s). ' --------------------------------------------- Set db = CurrentDb Set rs = db.OpenRecordset("tblODBCDataSources") With rs While Not .EOF strTblName = rs("LocalTableName") strConn = "ODBC;" strConn = strConn & "DSN=" & rs("DSN") & ";" strConn = strConn & "APP=Microsoft Access;"
Then you make a macro named autoexec and in the Action field you choose RunCode and in the Function Name field you enter =MyRefreshLinks()
Then copy the following into a new Module WITHOUT any changes.
'*************************************************************** 'The DoesTblExist function validates the existence of a TableDef 'object in the current database. The result determines if an 'object should be appended or its Connect property refreshed. '*************************************************************** Function DoesTblExist(strTblName As String) As Boolean On Error Resume Next Dim db As DAO.Database, tbl As DAO.TableDef Set db = CurrentDb Set tbl = db.TableDefs(strTblName) If Err.Number = 3265 Then ' Item not found. DoesTblExist = False Exit Function End If DoesTblExist = True End Function
Function MyRefreshLinks() As Boolean On Error GoTo MyRefreshLinks_Err Dim strTblName As String, strConn As String Dim db As DAO.Database, rs As DAO.Recordset, tbl As DAO.TableDef ' --------------------------------------------- ' Register ODBC database(s). ' --------------------------------------------- Set db = CurrentDb Set rs = db.OpenRecordset("tblODBCDataSources") With rs While Not .EOF strTblName = rs("LocalTableName") strConn = "ODBC;" strConn = strConn & "DSN=" & rs("DSN") & ";" strConn = strConn & "APP=Microsoft Access;" strConn = strConn & "TABLE=" & rs("ODBCTableName") If (DoesTblExist(strTblName) = False) Then Set tbl = db.CreateTableDef(strTblName, _ dbAttachSavePWD, rs("ODBCTableName"), _ strConn) db.TableDefs.Append tbl Else Set tbl = db.TableDefs(strTblName) tbl.CONNECT = strConn tbl.RefreshLink End If
rs.MoveNext Wend End With MyRefreshLinks = True
MyRefreshLinks_End: Exit Function MyRefreshLinks_Err: msgBox Err.Description, vbCritical, "MyApp" Resume MyRefreshLinks_End End Function
wizax>hows it going, have you got it to work yet? If you are having problems implementing this then if you give me th einformation of which tables you have in the dB AND the DSN name then I will implement it for you íf you send me your database terry@santhell.dk
Hope it does, if not then let me know, and thanks :o)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.