I have many Access database files that contain linked tables to a SQLServer database. Now the database server has changed and I have to edit the links, possibly without recreating them.
it's possible to do it? I use Access 2013.
Yes it is possible to do with VBA but the way you'll do it really depends on how you linked the tables.
Here are 2 example of connection strings I use for SQL server tables
Direct connection:
Driver=SQL Server Native Client 10.0;Server=server_name;Address=server_address,1433;Network=network_name;Database=database_name;Trusted_Connection=Yes
DSN connection (with an entry in the ODBC control panel)
ODBC;Provider=SQLNCLI10;Server=server_name;DSN=name_of_DSN_entry_in_ODBC_control_panel;Database=database_name;Trusted_Connection=Yes
So the first thing to do is to determine how your tables are linked.
You can use this code (pay attention to the comments):
Public Sub Check_ODBC_tables()
Dim tdef As TableDef
' First loop on all tables to determine the connection strings
For Each tdef In CurrentDb.TableDefs
' only print the constring if the database name is your old database (adapt accordingly)
If InStr(tdef.Connect, "Database=old_database_name") Then
Debug.Print tdef.Connect
End If
Next
End Sub
Run this code (F5) and check the output in the immediate window. You'll find how the table are linked and what are the connection strings.
You should prepare a connection string based on that, and adapt in them the database name to use your new DB.
Once you are ready, you can adapt and run the following code that will delete the old table and recreate them with the new database names (some tweaks might be necessary), so go thought it in debug mode !
Public Sub Change_ODBC_tables()
Dim tDef As TableDef
Dim tDefNew As TableDef
Dim strTable As String
Dim strCOnString As String
' examples of constrings - ADAPT!!!!
strCOnString = "Driver=SQL Server Native Client 10.0;Server=server_name;Address=server_address,1433;Network=network_name;Database=database_name;Trusted_Connection=Yes"
strCOnString = "ODBC;Provider=SQLNCLI10;Server=server_name;DSN=name_of_DSN_entry_in_ODBC_control_panel;Database=database_name;Trusted_Connection=Yes"
For Each tDef In CurrentDb.TableDefs
If InStr(tDef.Connect, "Database=old_database_name") Then
' We find a match, store the table name
strTable = tDef.Name
' delete the linked table
DoCmd.DeleteObject acTable, strTable
' recreate the linked table with new DB name
Set tDef2 = CurrentDB.CreateTableDef(strTable)
tDef2.Connect = strCOnString
tDef2.SourceTableName = strTable
tDef2.Name = strTable
CurrentDb.TableDefs.Append tDef2
End If
Next
End Sub
If you don't fully understand the second piece of code I posted, I urge you to backup your mdb prior to run it because it will delete objects which can cause serious issues.
Related
I don't have much experience with SQL Server, I use it currently to run some simple queries, and I link to SQL tables from Access where I have all my heavy queries. My goal is to run all of my queries in Access daily and then at the end write the finished tables up to SQL where my Access front end will read them (versus keeping them in my Access backend).
I've tried messing around with the code below to try and figure out how to do this, but I'm stuck at the driver and I can't find any references on how to do this with just a single table. Let's call it "PO_STATUS_TBL"
Public Sub ADOtest()
Dim ADOConn As New ADODB.Connection
Dim ADOCom As New ADODB.Command
On Error Resume Next
ADOConn.ConnectionString = "Driver =(SQL Server);DRIVER=SQL Server;SERVER=BUSINESS_BWP;Trusted_Connection=Yes"
ADOConn.Open
Debug.Print ADOConn.State
Dim db As Database
Set db = CurrentDb
'db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;ENCSQL28\BUSINESS_BWP;DATABASE=CurrentDb].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"
End Sub
I went through this process lately.
For migration you can use this tool by Microsoft. With this tool you can either migrate a table or a query to MS-SQL - or even both. Even with relations.
Simple export with this wizard and add your one table through ODBC Connector in Access. Important is to have the correct ODBC Driver.
If you are interested I resolved this issue with Parfait's advise. By using a simple INSERT statement.
INSERT INTO Dbo_PO_STATUS_ALL_TBL Select * FROM PO_STATUS_ALL_TBL
Over the last few days, I was asked to move a company program over from an Access back-end, to SQL Server.
There are 2 copies of the program, the live data version, on the server, and the local version on my PCs C: Drive, to ensure if I make a mistake, it doesn't affect the live data.
So, I managed to migrate the Access database, tables and data over to SQL Server 2008, and the local version of the program now works.
The easiest way, or so I'm informed, to now do the same to the live version of the program, is to write an imports program, which wipes all of the data from each table in the SQL Server database, and then copies over the data from the live Access database. However, I've never done this before, so I'm not really even sure where to begin.
Could anybody point me in the right direction on how to begin or do this, so that I only have to change the connection path in the program, rather than go through the whole process again?
PS, I work in vb.net, so that's the language I would need any responses in!
Thanks.
Usually one uses the SQL Server Import and Export Wizard for this.
It's a separate tool that is installed with SQL Server Management Studio (SSMS).
ANSWER
Step 1;
I added a new path to the ini file for the database to read. This connected to the live database. Once this connection is open in the project, proceed to step 2.
Step 2;
Create a new class, where the imports and exports will happen.
Step 3;
Put a button, or some sort of control in the program to initiate the import/export. For example, I had a button which, when clicked, asked the user to confirm that they wanted to import a new database and overwrite the existing one. If yes, call the function which does this, in the newly made imports class.
Step 4;
Now that you know how to get this set up, the code would be something like
Public Function importdatabase(/connections go in here/)
Declare transaction
Create sql variable
Try
Begin the transaction here
sql to delete the data from one table
sql to select all data from database that is being imported
For loop to iterate over each record in the database table
Declare a variable for each field in the database
variable1 = ("fieldname1")
variable2 = ("fieldname2")
sql statement to insert the new values
call to the function which runs the sql query
Next
commit transaction
Catch ex As Exception
Throw
End Try
Step 5; Repeat the delete/insert process for each database table
Below this, I have other functions.
One function created a new datatable, this is referenced as
For each dr as datarow in /functionname(parameters).Rows
Next one is to execute the sql statement (not required, any command to execute it will do)
Next one is used for parameterising my SQL query
The rest are to replace null values in the database with empty strings, set dates, etc
You can use the following class to import table(s) in access to sql server.
You need:
- The connection string of the source (including access file name) and the target one.
- The Source Table ,target tatble (if null it is the same as the source table)
Class ImportHelper
'modify connectionstring as needed
Public Property SourceConnectionString() As String
Get
Return m_SourceConnectionString
End Get
Set
m_SourceConnectionString = Value
End Set
End Property
Private m_SourceConnectionString As String
Public Property DestinationConnectionString() As String
Get
Return m_DestinationConnectionString
End Get
Set
m_DestinationConnectionString = Value
End Set
End Property
Private m_DestinationConnectionString As String
Public Sub New(sourceConnectionString__1 As String, destinationConnectionString__2 As String)
SourceConnectionString = sourceConnectionString__1
DestinationConnectionString = destinationConnectionString__2
End Sub
Public Sub Import(sourceTable As String, Optional targetTable As String = Nothing)
Using sourceConnection = New OleDbConnection(SourceConnectionString)
If String.IsNullOrEmpty(targetTable) Then
targetTable = sourceTable
End If
sourceConnection.Open()
' Perform an initial count on the destination table.
Dim commandRowCount = New OleDbCommand(Convert.ToString("SELECT COUNT(*) FROM ") & sourceTable, sourceConnection)
Dim countStart As Long = Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Source Table [{0}] has {1} rows", sourceTable, countStart)
' Get data from the source table
Dim commandSourceData = New OleDbCommand(Convert.ToString("SELECT * FROM ") & sourceTable, sourceConnection)
Dim reader = commandSourceData.ExecuteReader()
'---------------
Using destinationConnection As New SqlConnection(DestinationConnectionString)
destinationConnection.Open()
Using bulkCopy As New SqlBulkCopy(destinationConnection)
bulkCopy.DestinationTableName = targetTable
Try
' Write from the source to the destination.
bulkCopy.WriteToServer(reader)
Console.WriteLine(Convert.ToString("Sucess Importing ") & sourceTable)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
reader.Close()
End Try
'using
End Using
'using
End Using
End Using
'using
End Sub
End Class
How to use:
Private Sub Test()
'modify connectionstring as needed
'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\mydatabase.mdb;User Id=admin;Password=; //access 97..2000
Dim SourceConnectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\temp\database1.accdb;Persist Security Info=False;"
Dim DestinationConnectionString As String = "Data Source=xxxx;Initial Catalog=test;user=xxx;password=xxx;"
New ImportHelper(SourceConnectionString, DestinationConnectionString).Import("table1", "test1")
End Sub
Yesterday I had to run a query in MS Access 2010. One field I needed was not in the tables I usually use (already linked through the ODBC Database) and I didn't know what table it was a part (there are several hundred tables in the Machine Data Sources). Aside from manually importing all the tables and looking in each one for this field is there a way I can search for a field without knowing the table either 1. without importing any tables from the ODBC Databases, or if not 2. importing a handful of possible tables and searching once those tables have been linked into my active MS Access 2010 session?
Install Access Dependency Checker, link all tables and search for column name (enable checkbox for search in linked tables)
You could do this in a Function using ADO schema's.
Try this function in a standard module:
Function ListTablesContainingField(SelectFieldName) As String
Dim cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim strTempList As String
Set cn = CurrentProject.Connection
'Get names of all tables that have a column called <SelectFieldName>
Set rs = cn.OpenSchema(adSchemaColumns, _
Array(Empty, Empty, Empty, SelectFieldName))
'List the tables that have been selected
While Not rs.EOF
'Exclude MS system tables
If Left(rs!Table_Name, 4) <> "MSys" Then
strTempList = strTempList & "," & rs!Table_Name
End If
rs.MoveNext
Wend
ListTablesContainingField = Mid(strTempList, 2)
rs.Close
Set cn = Nothing
End Function
I have created a table in my Access front end application, and try to connect it to the back end database with the following subroutine:
Sub createFlowTable()
Dim db As Database
Dim tblDef As TableDef
Set db = CurrentDb
Set tblDef = db.CreateTableDef("myTable")
tblDef.Connect = "ODBC;DRIVER=SQL Server;SERVER=myServer; Trusted_Connection=No;UID=<myUID>;PWD=<myPWD>;APP=2007 Microsoft Office system;DATABASE=myDataBase;Network=DBMSSOCN;TABLE=dbo.myTable"
tblDef.SourceTableName = "mySourceTableName"
db.TableDefs.Append tblDef
End Sub
After I close the front end Access database, and upon reopening it, the table fails to open. Even though I have set the Trusted_Connection to "No" in my string, the table still tries to use the Windows Authentication. Also, when I open the table on design view, I see in front of "Description":
ODBC;DRIVER=SQL Server;Server=myServer;APP=2007 Microsoft Office System;DATABASE=myDatabase;Network=DBMSSOCN;Table=dbo.myTable
So obviously Access has not saved the UID and PWD, nor has it saved the instruction on setting the Trusted_Connection to "No".
I insist to get this done with the connection string, and using DSN will not work for the purpose of my application. Help would be greatly appreciated.
You need to add the dbAttachSavePWD-Attribute to the created table to store your credentials with the linked table in Access.
Before appending the tabledef you should put this line of code:
tblDef.Attributes = (tblDef.Attributes Or dbAttachSavePWD)
I have just learned about the pass through queries in MS-ACCESS.
I have a SQL SERVER backend and
if I'm right, for a query access loads all records before to do the where clause... so what would be the point of having a SQL SERVER backend?
That's why I want to try using pass through queries as much as possible but is there a way I can get the connection string from my linked tables for my pass through queries?
I tried CurrentDb.TableDefs("One of my table name").Connect in the ODBC Connect Str property but I got the error saying it's an invalid connection string.
It would be nice because I know I will have to change the connection soon so I wouldn't have to edit the connection string at many places.
Thank you.
I'm not sure what you meant here: "for a query access loads all records before to do the where clause"
If the WHERE clause can be applied at the server, ODBC will translate it to the server's language, and only the matching rows will be sent back to Access:
WHERE date_field >= #2011-01-01# AND date_field < #2012-01-01#
That WHERE clause would limit the rows sent to Access to only those whose date_field values are from 2011.
However, if a WHERE clause includes functions which must be evaluated by Access, ODBC must retrieve all candidate rows and hand them over to the Access db engine so it can perform the evaluation.
WHERE Format(date_field, 'yyyy') = '2011'
But for your actual question ... connection string for pass through queries ... consider the following code example. I have an ODBC link named dbo_foo whose source table in SQL Server is [dbo].[foo]. So I can grab the .Connect property from dbo_foo and use it for the .Connect property of a pass through query based on the same server table.
Public Sub CreatePassThruQuery()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim strConnect As String
Set db = CurrentDb
strConnect = db.TableDefs("dbo_foo").Connect
Set qdf = db.CreateQueryDef("qryDbo_Foo")
qdf.Connect = strConnect
qdf.SQL = "SELECT * FROM [dbo].[foo];"
qdf.Close
Set qdf = Nothing
Set db = Nothing
End Sub
Still when you change the .Connect property of the table, you will also need to do it for the query. If you have many of them and/or change the connections frequently, it may be worth the effort to create a VBA procedure to update them. Alternatively, you might use a DSN for the .Connect property of the table and matching query. Then revise the DSN as needed. A pitfall with that approach is that, if other people will be using your application, you would need to manage the DSNs on multiple machines.