Execute a SQL Server stored procedure from MS Access - sql

I use MS Access 2013 and SQL Server 2012. I have connected my SQL Server database to MS Access. I connect to SQL Server via SQL Server Authentication. I want to execute a stored procedure with a value entered into a textbox in one of my forms. I have been trying to do it for ages now but nothing that I found on this website works for me. Can anyone please help me and give me some tips as to how to write a basic VBA code to execute the procedure? Please help!!!

Probably the most straightforward way is to create a temporary pass-through query using a DAO.QueryDef object. If you have an existing linked table in Access then you can use its .Connect property (ODBC connection information). All you need to do is set the .SQL property of the QueryDef to call (EXEC) the stored procedure, like this:
Option Compare Database
Option Explicit
Private Sub Command2_Click()
Dim cdb As DAO.Database, qdf As DAO.QueryDef
Set cdb = CurrentDb
Set qdf = cdb.CreateQueryDef("")
' get .Connect property from existing ODBC linked table
qdf.Connect = cdb.TableDefs("dbo_myContacts").Connect
qdf.sql = "EXEC dbo.addContact N'" & Replace(Me.Text0.Value, "'", "''") & "'"
qdf.ReturnsRecords = False
qdf.Execute dbFailOnError
Set qdf = Nothing
Set cdb = Nothing
End Sub
So, for example, if the Text0 text box contains Thompson then the QueryDef will execute
EXEC dbo.addContact N'Thompson'
and if the text box contains O'Rourke then the QueryDef will execute
EXEC dbo.addContact N'O''Rourke'

After Trial and error this one worked for me
> Private Sub UpdateItems_Click()
> Dim cdb As DAO.Database, qdf As DAO.QueryDef
> Set cdb = CurrentDb
> Set qdf = cdb.CreateQueryDef("")
> ' get .Connect property from existing ODBC linked table
> qdf.Connect = cdb.TableDefs("dbo_AccesLinkedTable").Connect
> qdf.SQL = "EXEC dbo.YourStoreProcedure"
> qdf.ReturnsRecords = False
> qdf.Execute dbFailOnError
> Set qdf = Nothing
> Set cdb = Nothing
>
> MsgBox "Records Updated!"
>
> End Sub

Related

Why does an ms-access sql Pass Through not work in VBA

I am currently trying to write a select pass through query using VBA in Access 2016. If I use the manual option via the button Pass-Through and assign manually the dsn the following statement works.
SELECT top 1 dat_Kunden.Kunden_Status FROM dat_Kunden
The sql I want to pass through is changing so I want to create a VBA Function to execute it.
This is my current Function to execute a given sql statement
Function CreateSPT(strSQL As String)
Dim qdf As DAO.QueryDef, rs As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("")
qdf.Connect = "ODBC;Driver=SQL Server;SERVER=xxx;DATABASE=yyy;UID=zzz" 'in the code this is the real data
qdf.SQL = strSQL
qdf.ReturnsRecords = True
Set rs = qdf.OpenRecordset()
If Not (rs.BOF And rs.EOF) Then rs.MoveFirst
Do Until rs.EOF
Debug.Print rs.Fields(0)
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set qdf = Nothing
End Function
This does work.
Sub test_sql()
SQL = "SELECT CONVERT( date, GETDATE() ) AS qryTest"
CreateSPT (SQL)
End Sub
This statement which works via the manual pass through does not work
Sub test_sql2()
SQL = "SELECT top 1 dat_Kunden.Kunden_Status FROM dat_Kunden AS qryTest"
CreateSPT (SQL)
End Sub
The Error code is Run-time error '3146': ODBC -- call failed at this line:
Set rs = qdf.OpenRecordset()
I hope you have an idea where my mistake is... Thanks to all of you, learned a lot from you!
If you provide an alias, use it:
SQL = "SELECT Top 1 qryTest.Kunden_Status FROM dat_Kunden AS qryTest"
or ignore it:
SQL = "SELECT Top 1 Kunden_Status FROM dat_Kunden AS qryTest"

MS Access VBA Pass Through Query Connection String Error (ODBC)

I am currently trying to write a pass through query using VBA that connects to an oracle database. Using the answer provided from SQL Server Passthrough query as basis for a DAO recordset in Access as a starting poing, I have the following VBA code.
Option Compare Database
Sub Test_PassThroughQuery()
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("")
qdf.Connect = "ODBC;DSN=database_name;UID=username;PWD=password;DBQ=ADPR;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;"
qdf.SQL = "SELECT * FROM DATE_TABLE"
qdf.ReturnsRecords = True
Set rst = qdf.OpenRecordset
Debug.Print rst
rst.Close
Set rst = Nothing
Set qdf = Nothing
End Sub
However, this prompts an error Type mismatch on the Debug.Print rst.
For the connection string I am using the ODBC connection string from the Property tab.
EDIT Am I calling the Debug.print rst line incorrectly?
There are many ways to create pass-through queries. If you want to save a pass-through query in Access, you can set the first parameter of CreateQueryDef:
Sub Test_PassThroughQuery()
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("MyPassthroughQuery")
qdf.Connect = "ODBC;DSN=database_name;UID=username;PWD=password;DBQ=ADPR;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;"
qdf.SQL = "SELECT * FROM DATE_TABLE"
qdf.ReturnsRecords = True
DoCmd.OpenQuery "MyPassthroughQuery"
End Sub
This creates a saved query, and opens it.
You could also query an external data source in Access, which allows you to use the query designer, and use local tables and external data in a single query:
SELECT *
FROM [ODBC;DSN=database_name;UID=username;PWD=password;DBQ=ADPR;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;].DATE_TABLE

Using a Stored Procedure as a MS Access form Recordsource

Right now, I have a database, with a SQL Server backend, and a MS Access frontend. On one form, my users are experiencing slow load times for it to display. The form essentially looks up to see who the user is (based on their login ID, this part works), sees their access rights (readonly, v. update, etc.; this also works), and then pulls the projects they are allowed to see based on their access rights (this is the part I believe is running slow).
To make this form load faster, I feel that moving the last part, the part that pulls the projects they are allowed to see, to an SSMS Stored Procedure should make the form faster to load.
I have the stored procedure written, in SSMS, and I have the code on the 'Form Load' event that calls the stored procedure. The issue I am facing is having the results of the stored procedure become the Recordsource of the form. I've tried Me.RecordSource, but that doesn't seem to be working. Below is a copy of the code that calls the Stored Procedure:
This is different than having code to call an SP, because I already have the code to call it, however, I need the results of the SP to be the recordsource of an MS Access form.
Any help, or ideas will be appreciated! (e.g. I thought of trying to use a temp table to serve as the recordsource...)
Dim rs1 As ADODB.Recordset
Dim cmd As ADODB.Command
Dim prm As ADODB.Parameter
cn.ConnectionString = "DRIVER=SQL Server;SERVER=SERVERNAME;APP=Microsoft Office XP;WSID=MYCOMPUTER;DATABASE=dbname;Trusted_Connection=Yes;"
cn.Open
Set cmd = New ADODB.Command
Set rs1 = New ADODB.Recordset
With cmd
.ActiveConnection = cn
.CommandType = adCmdStoredProc
.CommandText = "dbo.ProcProjectSelection"
Set prm = .CreateParameter("#xID", adVarChar, adParamInput, 10, Me.txtNetworkID)
.Parameters.Append prm
End With
If I put:
Set Me.RecordSource = rs1
Before the "end with", I get an Error Message saying "Invalid Use of Property"
Solution:
Use a Pass through Query to get data from your Stored Procedure into a SubForm
Add the following code to your SubForm RecordSource field
Select * from YourPassThruQueryName
In your Form_Load()
Dim qdf as DAO.QueryDef
Set qdf = CurrentDb.QueryDefs("YourPassThruQueryName") ' If it exist
Set qdf = CurrentDb.CreateQueryDef("YourPassThruQueryName") ' If you have to create one
You must have a default Select statement so use something like:
qdf.sql = "Select * from anyTable where 0=1"
Set qdf = Nothing
Important!
You must use the following code to refresh your subform, as requery will not work:
Me.frm_Your_Sub_Form_Name.SourceObject = "frm_Your_Actual_Sub_Form_Name"
Final!
Use the the following to update the subform when you make your selection that's needed for your Stored Procedure in your Submit button:
Private Sub btn_Submit_Click()
Dim rs_tmp as DAO.Recordset
Dim qdf as DAO.QueryDef
Dim sp as String
sp = "EXEC DBO.USP_Your_SQL_Server_Stored_Procedure_Name '" & prevdate & "','" & currdate & "'"
Set qdf = CurrentDb.QueryDefs("YourPassThruQueryName")
qdf.Connect = adoConnectionString ' This is your Connection string for SQL Server
qdf.sql = sp
qdf.ReturnsRecords = True
Set rs_tmp = qdf.OpenRecordset
If Not rs_tmp.EOF Then
Me.frm_Your_Sub_Form_Name.SourceObject = "frm_Your_Actual_Sub_Form_Name"
rs_tmp.Close
End If
Set rs_tmp = Nothing
Set qdf = Nothing
End Sub
Solution 1:
Assign the Recordset returned from stored procedure to Form.Recordset Object
add this line at the end of your code
Set Me.Recordset = cmd.Execute
Solution 2:
You can create pass-through query based on ODBC data source, and use it as record source
Then, in the property sheet of the form , set the properties:
record source = your_pass_through_query
recordset type = dynamic
Edit:
My advice use solution 2 to avoid many setting for ado and runtime errors
Example: Pass through using northwind , and stored procedure
Bind your controls in the form with the field name of result set of the query
Private Sub Form_Open(Cancel As Integer)
test
End Sub
Sub test()
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("")
qdf.Connect = "ODBC;Driver=SQL Server;Server=xxxx;database=northwind;Trusted_Connection=Yes;"
' stored procedure with paramete
qdf.SQL = "exec [CustOrderHist] 'ALFKI'"
qdf.ReturnsRecords = True
Set rst = qdf.OpenRecordset
Set Me.Recordset = rst
End Sub

Run-time error '3049' when qdf.Execute dbFailOnError in Access

I am trying to commit new data into the various databases and when I keep committing data after a while, it shows me this error:
The commit statment looks like this:
sql "INSERT INTO Bond Values("","HK0000122334","CNH",8447.5357732363,8447.5357732400,0.0000000037,109913,"01Jun15")".
The database reaches 2.09Gb as well. My code looks this:
Sub commit(dbName As String, tableName As String, commitString As String, reportDate As String)
Dim ws As DAO.Workspace
Dim db As DAO.Database
Dim sSQL As String
Dim qdf As QueryDef
sDb = dbName & ".accdb"
Set ws = DBEngine.Workspaces(0)
Set db = ws.OpenDatabase(sDb)
sqlStatementList = Split(commitString, ";")
For Each sqlStatement In sqlStatementList
sqlStatement = Replace(sqlStatement, ")" & vbLf, reportDate)
If InStr(tableName, "EIS") <> 0 Then
sqlStatement = Replace(sqlStatement, "EIS", tableName)
End If
sSQL = sqlStatement
Set qdf = db.CreateQueryDef("", sSQL)
qdf.Execute dbFailOnError
Next sqlStatement
End Sub
What I have tried so far:
1)
Set qdf = Nothing
Set db = Nothing
This did not help. Still the same issue.
2) Tried to delete that particular database and proceeded with committing to the rest of databases but still had the same issue.
Need some guidance on solving this.
The maximum size of an Access database is 2GB (Link is for 2010, but 2013 appears to be the same). So yes your insert will fail when the database gets that large. Your options are to break the data into another database file or switch to SQL Server or some other database type.

Terminating Query If Not Connection

I have a code that uploads data to a SQL server database, I am trying to add in an IF line of code saying if there is a connection then to continue, but if there is not a connection then to END. I am having a difficult time figuring out the wording and placement though. The beginning of the code that connects is:
Public Function Update()
Dim cdb As DAO.Database, qdf As DAO.QueryDef
Dim rs As DAO.Recordset
Dim err As DAO.Error
Const ConnectionString = _
"ODBC;" & _
"Driver={SQL Server Native Client 10.0};" & _
"Server=SERV;" & _
"Database=DB;" & _
"UID=ID;" & _
"PWD=PWD;"
Set cdb = CurrentDb
Set qdf = cdb.CreateQueryDef("")
Set rs = CurrentDb.OpenRecordset("CDData", dbOpenTable)
qdf.Connect = ConnectionString
Do While Not rs.EOF
While one can simple attempt to execute any query or command, the “time out” and delay to test for an active connection can result in a VERY LONG delay. As a result a wonderful trick exists that uses a DIFFERENT connection mechanism in Access and thus “reduces” the potential VERY long delay when attempting to use a saved query that is based on linked tables. (that "different" connection system occurs when you create a queryDef as opposed to a linked table or a query based on a linked table to sql server)
The follow code will return true or false if you have a working SQL connection:
Function TestLogin(strcon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.Connect = strcon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
qdf.SQL = "SELECT 1 as test"
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
So in code you now with your connection string code go:
If TestLogIn(strConn) = false then
msgbox "no connection or logon invalid"
exit sub
End If
' record processing code goes here for successful logon/connection.