How to connect/link SQL db to Access database using SSIS? - sql-server

I have a SQL database that centralizes all data within our agency; however, we also receive data from outside sources that needs to be parsed into our db structure. One of our partners maintains an Access 2016 database that they provide to us weekly to perform various analyses. My goal is to build an SSIS (2017) package that will move data from the Access db to SQL tables; replacing the Access db w/ an updated version and re-running the SSIS package on a scheduled basis.
I am trying to set up a connection manager for the Access database, but I cannot find a driver option in the provided DSN list for .accdb files, only .mdb files types, when I try to build the connection string. How do I create the connection for an Access 2016 database (i.e., .accdb)???

You don't need SSIS for something like this. You can simply export data from MS Access to SQL Server, without replying on another app.
This VBA sample will export data from a table in Access to SQL Server.
Option Compare Database
Private Sub Command0_Click()
Dim sTblNm As String
Dim sTypExprt As String
Dim sCnxnStr As String, vStTime As Variant
Dim db As Database, tbldef As DAO.TableDef
On Error GoTo ExportTbls_Error
sTypExprt = "ODBC Database" 'Export Type
sCnxnStr = "ODBC;DRIVER=SQL Server;SERVER=your_sever_name" & stServer & ";DATABASE=your_database_name" & stDatabase & ";Trusted_Connection=Yes"
vStTime = Timer
Application.Echo False, "Visual Basic code is executing."
Set db = CurrentDb()
'need a reference to Microsoft DAO 3.x library
For Each tbldef In db.TableDefs
'Don’t export System and temporary tables
Debug.Print tbldef.Name
If tbldef.Name Like "*Table1*" Then
sTblNm = tbldef.Name
DoCmd.TransferDatabase acExport, sTypExprt, sCnxnStr, acTable, sTblNm, sTblNm
End If
Next tbldef
MsgBox "Done! Time taken=" & (Timer - vStTime)
On Error GoTo 0
SmoothExit_ExportTbls:
Set db = Nothing
Application.Echo True
Exit Sub
ExportTbls_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure ExportTblsODST"
Resume SmoothExit_ExportTbls
End Sub
See the link below for more info.
https://www.mssqltips.com/sqlservertip/2484/import-data-from-microsoft-access-to-sql-server/

Related

Run Stored Procedure in SQL database from Access VBA without windows authentication

I am trying to run a stored procedure (using Access VBA) in the SQL database. I can find a few examples of this on SO and on other sites but what I am unable to find is connection string where I can provide my login details as windows authentication won't work because I have to use a different user to connect to SQL database
Here is what I have tried so far (got this from one of the post in SO, unfortunately, I can't find the post anymore):
Sub RunSQLProc()
Dim cdb As DAO.Database, qdf As DAO.QueryDef
Set cdb = CurrentDb
Set qdf = cdb.CreateQueryDef("")
qdf.Connect = "ODBC;" & _
"Driver=SQL Server;" & _
"Server=myServer;" & _
"Database=myDatabase;" & _
"UID=myUsername;" & _
"PWD=myPassword;" & _
"Trusted_Connection=yes;"
' "Driver={SQL Server Native Client 11.0};" & _
' "MARS Connection=True;"
qdf.SQL = "SQLStroedProcedure;"
qdf.ReturnsRecords = False
qdf.Execute dbFailOnError '<-- this line throws the error
Set qdf = Nothing
Set cdb = Nothing
End Sub
On qdf.Execute dbFailOnError line, I get the following error:
Run-time error '3151':
ODBC--connection to 'SQL ServermyServer'failed.
I have managed to connect to the SQL database and run the stored procedure through SQL Server Management Studio. This tells me that the details in my connection string are correct (although I haven't provided the actual details here) but I suspect there is an issue with my connection string.
Happy to provide more details. Any help is much appreciated, thanks
P.S. Apologies for my lack of knowledge in Access. I just don't use it very often
to use SQL Server security remove Trusted_Connection=yes.
https://www.connectionstrings.com/microsoft-sql-server-odbc-driver/

Set commandtimeout for linked SQL Tables/Views in Access front end

We have moved some back-end data tables over from a network drive (mbd file) to being on an SQL Server database. Things mostly work great, but if staff are accessing things through a VPN (which slows things down a lot), then we get connection errors when we run reports that retrieve a lot of data. My guess is that I need to set a timeout to a larger value, and I did some research and it seems that I need to set the commandtimeout (or maybe query timeout?).
Below is the VBA code we use to connect the SQL Server tables/views to our Access front end from the SQL Server back end. Am I right that I likely need to specify a commandtimeout? Where in this would we add the commandtimeout (or other timeout) value?
Public Sub CreateSQLLinkedTable(strSourceTableName As String, strNewTableName As String)
'************************************************************************************
'* Create a linked table in the current database from a table in a different SQL Server file.
'* In: *
'* strNewTableName - name of linked table to create *
'* strSourceTableName - name of table in database *
'************************************************************************************
Setup:
Dim tdf As TableDef
Dim strConnect As String, strMsg As String
Dim myDB As Database
' set database vars
Set myDB = CurrentDb
Set tdf = myDB.CreateTableDef(strNewTableName)
MakeConnections:
On Error GoTo OnError
' turn system warnings off
DoCmd.SetWarnings False
' define connect string and source table
' We do not need to specify the username (Uid) and password (Pwd) in this connection
' string, because that information is already cached from the connection to the SQL
' Projects database that we created in CheckSQLConnection() that was run to check connection
' to the database. So here we can have a connection string without the Uid and Pwd.
With tdf
.Connect = "ODBC;Driver={SQL Server};" & _
"server=" & myServer & ";" & _
"database=" & mySQLDB & ";"
.SourceTableName = strSourceTableName
End With
' execute appending the table
myDB.TableDefs.Append tdf
' turn system warnings back on
DoCmd.SetWarnings True
ExitProgram:
' this block of code will run if there are no errors
Exit Sub
OnError:
' this block of code runs if there is an error, per On Error assignment above
' display error message with details
MsgBox "There was an error connecting to the SQL Server data source Projects. Error = " & err & ", Description: " & err.Description
'exit Projects
Call CloseFormsAndQuit
End Sub
There is an ODBC timeout property. Open the query in design view, and go to properties to see it. There is also an (ODBC) query timeout on the current database properties page. You can set it programmatically as well:
Dim objDB As DAO.Database
Set objDB = CurrentDb()
objDB.QueryTimeout = 120
http://www.geeksengine.com/article/how-to-change-timeout-value-for-access-sql.html
Also check the server configuration. There is a query timeout on server side.

Access Excel workbook through ADODB - Mutiple users at same time

I am trying to access Excel workbook placed in a share path through ADODB connection in different remote machines. But when multiple remote machines trying to access the same Excel sheet, it thows the following error:
The Microsoft Office Access database engine cannot open or write to the file ''. It is already opened exclusively by another user, or you need permission to view and write its data.
Connection String used:
strConnection_Write = "Provider=Microsoft.jet.OLEDB.4.0;Data Source=" & _
Runmanager_path & ";Mode= Share Deny None" & _
";Extended Properties=""Excel 8.0;HDR=Yes;"";"
Please suggest me a solution.
I ran into the same issue a while back with OLEDB, got past it by using DAO...
Dim DBworkbook As DAO.Database
Dim DBSheet As DAO.Recordset
Set DBworkbook = OpenDatabase("C:\File.xls", False, False, "Excel 8.0;HDR=Yes;")
Set DBSheet = DBworkbook.OpenRecordset("SELECT * FROM [Sheet1$]")
DBSheet.MoveFirst
Do Until DBSheet.EOF
If DBSheet!Name = "Bob" Then
DBSheet.Edit
DBSheet!Addeess = "5 Something Street"
DBSheet.Update
End If
DBSheet.MoveNext
Loop

Installable ISAM Error when trying to use DoCmd.TransferDatabase to link a table

I am trying to use DoCmd.TransferDatabase to link a SQL Server Express table to an Access 2013 table. I have no problems with other program code that accesses table data in SQL Server and Access.
The error message that I am getting is: "could not find installable ISAM".
I have had no success in running Microsoft's DoCmd.TransferDatabase sample programs or in finding an answer on the Web to the ISAM problem.
The code is as follows:
Set AccessConn = CreateObject("ADODB.Connection")
With AccessConn
.Provider = "Microsoft.Access.OLEDB.10.0"
'.Provider = "Microsoft.ACE.OLEDB.12.0"
.Properties("Data Provider").Value = "SQLOLEDB"
.Properties("Data Source").Value = TempVars!GlobalServerName
.Properties("User ID").Value = "sa"
.Properties("Password").Value = "xxxxxx"
.Properties("Initial Catalog").Value = TempVars!GlobalDatabaseName
.Open
End With
DoCmd.TransferDatabase acLink, "ODBC Database", _
"[ODBC;DSN={SQL Server Native Client 11.0};Server=XXXS1\SQLExpress;Database=ADatabaseName;Trusted_Connection=yes;]" _
& "DATABASE=D:\DatabaseDirectory\DatabaseTables.accdb", acTable, "Table1", "Table1;"
I had this problem, play with connection string, this worked for me.
"ODBC;Driver={ODBC Driver 17 for SQL Server};SERVER=MyServerName;DATABASE=MyDbName;Trusted_Connection=Yes;"
Private Sub PrintFormPB_Click()
'The purpose of this code is to be able to print Access Reports when the data are stored in
'a SQL Server database. One way to do this is to link all the SQL Tables to all the Access
'tables, but this has multiple disadvantages including the fact that the linker duplicates
'all of the SQL Table data in Access.
'This program only transfers Table data when it is required by Access Reports. The table
'data can then be deleted.
'There are several Report options. You can print the current Form page or all of the pages
'using a Report template. It is also possible to set a variety of printer options.
'This code links a SQL Server Table to an Access Table. The link command creates a new table
'that is named by appending a suffix the Table name. For example, Table allergies is linked
'as Allergies1. It is preferable to link to the original Table name, but the linker
'apparently cannot do this.
'This is part of an Open Source personal "MedicalRecords" program.
Dim strSQL As String
Dim database_path As String
Dim oRpt As Report
Dim AccessConn As New ADODB.Connection
Dim MsgBoxResponse As Integer
Dim ret As Integer
On Error GoTo ErrorHandler
'Setup the Access database connections
Set AccessConn = CreateObject("ADODB.Connection")
With AccessConn
.Provider = "Microsoft.Access.OLEDB.10.0"
'.Provider = "Microsoft.ACE.OLEDB.12.0"
.Properties("Data Source").Value = "D:\MedicalRecordsSQL\MedicalRecordTables.accdb"
.Open
End With
'The following links a SQL Server Table called Allergies to an Access Table called Allergies1.
'The Access table Allergies is then deleted and Allergies1 is renamed to Allergies.
'These are undesirable steps, but no alternative is known at this time.
'Note the formats of the SQL Server statements.
DoCmd.TransferDatabase acLink, "ODBC Database", _
"ODBC;Driver={SQL Server Native Client 11.0};SERVER=RERS1\SQLExpress;UID=sa;PWD=<your Password>;DATABASE=MedicalRecordsSQL;;Table=dbo.Allergies;" _
& "DATABASE=|D:\MedicalRecordsSQL\|MedicalRecordTables.accdb", acTable, "dbo.Allergies", "Allergies"
Set AccessConn = Nothing
DoCmd.DeleteObject acTable, "Allergies"
DoCmd.Rename "Allergies", acTable, "Allergies1"
'Setup Report
DoCmd.OpenReport "Allergies", acViewDesign, Null, Null, acHidden
Set oRpt = Reports(0)
oRpt.UseDefaultPrinter = True
'oRpt.Printer = Application.Printers("printer name")
'Set printer options
With oRpt.Printer
.PaperBin = acPRBNAuto
.PaperSize = acPRPSLetter
.Copies = 1
.PrintQuality = acPRPQMedium
.Orientation = acPRORLandscape
End With
'Print the report
DoCmd.Close acReport, "Allergies", acSaveYes
DoCmd.OpenReport "Allergies", acViewNormal, , "[ID] = " & Me.ID
Set oRpt = Nothing
Exit Sub
ErrorHandler:
MsgBoxReturn = MsgBox("Error Source: Allergies_Form" & vbCrLf & "Error Line: " & Erl & vbCrLf & "Error Number: " & Err.Number & vbCrLf & Err.Description, vbCritical, "")
End Sub

Keeping UID and PWD out of an ADO connection string in an ODBC DSN-less Database and a DAO cached connection?

I have used Ben Clothier's suggestion from his Office Blog Power Tip (http://blogs.office.com/2011/04/08/power-tip-improve-the-security-of-database-connections/) to create a DSN-less connection with cached credentials so that users' UID and PWD aren't saved, or required multiple times, when working in the Access interface. Have others done this? If so, what has been your approach when you need to use an ADO connection instead of DOA to reach SQL from Access via VBA? How do you open a adodb connection without having to provide the User ID and Password again, or having to put it in the code?
(I'm using Access 2013 frontend, SQL 2008 R2 backend, SQL Server Security)
Thanks in advance!
My Cached Connection code works like this:
Public Function InitConnect(strUserName As String, strPassword As String) As Boolean
' Description: Is called in the application’s startup
' to ensure that Access has a cached connection
' for all other ODBC objects’ use.
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Dim strConnection As String
strConnection = "ODBC;DRIVER=sql server;" & _
"SERVER=******;" & _
"APP=Microsoft Office 2010;" & _
"DATABASE=******;" & _
"Network=DBMSSOCN;"
Set dbs = DBEngine(0)(0)
Set qdf = dbs.CreateQueryDef("")
With qdf
.Connect = strConnection & _
"UID=" & strUserName & ";" & _
"PWD=" & strPassword & ";"
.SQL = "Select Current_User;"
Set rst = qdf.OpenRecordset(dbOpenSnapshot, dbSQLPassThrough)
End With
InitConnect = True
ExitProcedure:
On Error Resume Next
Set rst = Nothing
Set qdf = Nothing
Set dbs = Nothing
Exit Function
End Function
Then when I need to access data I can do this (Note the UID and PWD are not required):
Dim dbs As DAO.Database
Set dbs = OpenDatabase("", False, False, "ODBC;DRIVER=sql server;SERVER=*****;APP=Microsoft Office 2010;DATABASE=*****;Network=DBMSSOCN")
I can also set the ODBC connection to pass-through queries as well in Access or VBA. But these connections work only when the connection string is IDENTICAL to what was originally used in my Cached Connection code. So, when I need an ADODB connection (as it seems sometimes ADO is needed?), the string obviously isn't going to be identical.
For Example:
Dim cn As New ADODB.Connection
cn.Open "Provider = sqloledb;Data Source=*same as "SERVER"*;Initial Catalog=*same as "DATABASE"*;User Id=****;Password=****"
This type of connection only works if I supply a User Id and Password. How can I write it so that I don't need them? ~Thanks!
Although ACCESS has some weak points regarding security, you can do few things to minimize the risks. One of them would be compile the DB to ACCDE. This way VBA is compiled and not visible.
You can create a public function that returns a string
Public Function GET_CONNECTION_STRING() as STRING
' construct your connection string here with server name and password
GET_CONNECTION_STRING = "DRIVER={" & Driver & "};PORT=" & mPort & ";DATABASE=" & mDatabase & ";SERVER={" & mServer & "};UID=" & mUser & ";PWD={" & mPassword & "};"
End Function
then create an AutoExe macro that runs when the application is opened.
in your AutoExe perform refreshing links to your linked tables. something similar to what you have.
For Each tdf In db.TableDefs
If tdf.connect <> vbNullString Then
tdf.connect = GET_CONNECTION_STRING & ";TABLE=" & tdf.name
tdf.RefreshLink
End If
Next tdf
you can do the same for existing pass through queries:
For Each myQuerydef In MyDB.QueryDefs
If Left(myQuerydef.connect, 4) = "ODBC" Then
myQuerydef.connect = "ODBC;" & GET_CONNECTION_STRING
myQuerydef.Close
End If
Next
in addition you can have some other public functions to get current logged in username.
something like
public function getCrruserID() as int
'check your public variable crr_user_id if its empty redirect to login
if nz(crr_user_id,0) = 0 then
'go to login and save the user id after successful login
else
getCrruserID = crr_user_id
end if
end function
use simple DAO to execute sql code like
dim db as DAO.Database
set db = currentdb
dim rs as Dao.Recordset
set rs = db.openrecordset("select something from your linked table")
or
db.execute "update command", dbfailonerror
to your last question. if you save something in memory it will be destroyed once your application is closed.
EDIT:
if you have more than 50 linked tables it might be not a good idea to refresh them at every startup. Instead you can create a Local table containing your [local_Appversion, isFreshInstall] and some other variables as per your need. Every time your user receives an update the freshInstall will be true and code your App to connect and refresh all tables. (just to make sure client will get uninterrupted connection)
so in your autoExe code: if its freshInstall then
connect and refreshlinks if not just set the connectionString. (usually a splash screen after login to perform this action)
After successful connection just update the local isFreshInstall value to false for a quicker start next time.
you can also have a dedicated menu where user can click and refresh links manually.(in case if the connection get dropped)
something like
if your organisation has a domain you can allow trusted connection using windows login name
good luck.

Resources