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

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.

Related

DAO passthrough query using VBA: "Error 3131 Syntax error in from clause"

I copied a solution found in Stack Overflow, adapted it to my needs.
Public Function getAssortmentTypes(Optional personId As Variant) As DAO.Recordset 'personId is integer
Dim strQuery As String
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(" & personId & ")"
End If
Set qdf = CurrentDb.CreateQueryDef("")
With qdf
.SQL = strQuery
.Connect = getDBConnectionString
.ReturnsRecords = True
End With
Set rst = qdf.OpenRecordset
Debug.Print rst!qryTest
Set getAssortmentTypes = rst
End Function
In my postgresql db I do have a working function and appropriate tables. I've tested sql queries with DBEaver and they work.
I'm receiving just one row (should be about 30) when I call the function without a parameter.
With a parameter I expect filtered resultset but receive
"Error 3131 Syntax error in from clause".
Always set the connection string before setting the SQL.
When you set the SQL, DAO doesn't have a clue this will later become a passthrough query, so it tries to parse it as Access SQL, and obviously fails, since it's not valid Access SQL.
Simply change the order:
With qdf
.Connect = getDBConnectionString
.ReturnsRecords = True
.SQL = strQuery
End With
Do note that you should be using parameters, and generally, use ADO instead of DAO when working with external data sources. DAO is great with Access, but offers less features with external data sources. ADO won't try parsing the SQL string before it actually needs to, for example.
Forgo the need for DAO and QueryDefs and use ADO with command parameterization which can then be binded to a recordset:
' SET REFERENCE TO Microsoft ActiveX Data Object #.# Library
Public Function getAssortmentTypes(Optional personId As Variant) As ADODB.Recordset
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim cmd As ADODB.Command
Set conn As New ADODB.Connection
conn.Open getDBConnectionString
' PREPARED STATEMENT WITH QMARKS ?
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(?)"
End If
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = strQuery
.CommandType = adCmdText
' BIND PARAMETER
.Parameters.Append .CreateParameter("user_param", adInteger, adParamInput, , personId)
' EXECUTE QUERY AND BIND INTO RECORDSET
Set rst = .Execute
End With
Set cmd = Nothing
Set getAssortmentTypes = rst
End Function
I don't recommend the introduction of ADO.
The issue looks to be that your first SQL query would (and does) work as a linked table, and thus works because it not a pass-through query.
The 2nd sql fails, since it still try to use "access" sql, and not postgresSQL syntax.
I recommend that you create a PT query (using Access UI). In the designer, make sure you select pass-though:
So, like linked tables - put the connection string in that PT query.
Do not put or attempt to place connection strings in the code. Your re-link routines can thus also include to re-link PT queries.
You can now use this code:
Public Function getAssortmentTypes(Optional personId As Variant) As DAO.Recordset 'personId is integer
Dim rst As DAO.Recordset
Dim strQuery As String
If IsMissing(personId) Then
strQuery = "SELECT assortment_type.type_id, assortment_type.type_name AS qryTest FROM assortment_type"
Else
strQuery = "SELECT * FROM get_non_deleted_assortment_types_by_user(" & personId & ")"
End If
With CurrentDb.QueryDefs("qryPT")
.SQL = strQuery
Set rst = .OpenRecordset
End With
Debug.Print rst!qryTest
Set getAssortmentTypes = rst
End Function
So, create a PT query called (for this example) qryPT
Try omitting the “DAO.” Prefix in your Recordset and dimension statements. Later versions of Access understand what you want.

How can I set an Excel Cell Value as the criteria for Access Query?

I am creating a new query in MS Access that updates an existing record based on the "Branch" and "Employee" fields. How can I set the criteria to reference cell values? Say A2 holds the "Branch" ID for Access and B2 holds the value for the "Employee" ID in Access.I want to update my Access "Notes" Field. My query works when running in Excel, but only because I have specified what the "Employee" & "Branch" ID's are. Nothing updates when i run my code below:
Code
Sub modify_record()
Dim ac As Object
Dim branchid As String
Dim employeeid As String
Dim notesF As String
Set ac = CreateObject("Access.Application")
branchid = Sheets("Sheet4").Range("A2")
employeeid = Sheets("Sheet4").Range("B2")
notesF = Sheets("Sheet4").Range("C2")
Dim strDatabasePath As String
strDatabasePath = "C:\Users\johnsmith\OneDrive\pbsbackup.mdb"
With ac
.OpenCurrentDatabase (strDatabasePath)
Dim db As Object
Set db = .CurrentDb
db.Execute "Update_Records"
End With
End Sub
Query in MS Access. Saved as Update_Records
UPDATE pbsmaster SET pbsmaster.notes = "notesF" WHERE
(((pbsmaster.branch)="branchid") AND((pbsmaster.employee)="employeeid"));
Your variables don't magically transfer into the query, just because they have the same name.
You need to specify the parameters in the Access query, and pass them via a DAO.QueryDef object in the Excel VBA code.
Here is an example: https://stackoverflow.com/a/2317225/3820271
Dim qd As Object ' DAO.QueryDef
Set qd = db.QueryDefs("Update_Records")
qd.Parameters("branchid") = branchid
' etc.
qd.Execute
Here is my solution from what I learned from #Andre. I am able to execute my code, I noticed working with Parameters is much quicker than opening a recordset with DAO.
Sub foo()
Dim db As Database
Dim qdf As QueryDef
Set db = OpenDatabase("C:\Users\employee\OneDrive\samplefile.mdb")
Set qdf = db.CreateQueryDef("", _
"PARAMETERS pbsbranch text , pbsnotes text; " & _
"UPDATE pbsmaster SET pbsmaster.notes=[pbsnotes] " & _
"WHERE pbsmaster.branch=[pbsbranch] " & _
"")
qdf!pbsbranch = Sheets("Sheet4").Range("A2")
qdf!pbsnotes = Sheets("Sheet4").Range("C2")
qdf.Execute dbFailOnError
Set qdf = Nothing
Set cdb = Nothing
End Sub

VBA OpenRecordset Producing Too few parameters. Expected 2. Error

I have a query called qryAlloc_Source that has two paramaters under one criteria:
>=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd])
A have a separate query that ultimately references qryAlloc_Source (there are a couple queries in between), and that query runs fine when I double click it in the UI, but if I try to open it in VBA, I get an error. My code is:
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("qryAlloc_Debits")
I am getting run-time error 3061, Too few parameters. Expected 2. I've read that I may need to build out the SQL in VBA using the form parameters, but it would be pretty complex SQL given that there are a few queries in the chain.
Any suggestions as to a workaround? I considered using VBA to create a table from the query and then just referencing that table--I hate to make extra steps though.
The reason you get the error when you just try to open the recordset is that your form is not open and when you try to access [forms]![frmReportingMain] it's null then you try to get a property on that null reference and things blow up. The OpenRecordset function has no way of poping up a dialog box to prompt for user inputs like the UI does if it gets this error.
You can change your query to use parameters that are not bound to a form
yourTableAllocStart >= pAllocStart
and yourTableAllocEnd <= pAllocEnd
Then you can use this function to get the recordset of that query.
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim db As DAO.Database
Dim qdef As DAO.QueryDef
Set db = CurrentDb
Set qdef = db.QueryDefs("qryAlloc_Debits")
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
The disadvantage to this is that when you call this now on a form that is bound to it it doesn't dynamically 'fill in the blanks' for you.
In that case you can bind forms qryAlloc_debts and have no where clause on the saved query, then use the forms Filter to make your where clause. In that instance you can use your where clause exactly how you have it written.
Then if you want to still open a recordset you can do it like this
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim qdef As DAO.QueryDef
Set qdef = New DAO.QueryDef
qdef.SQL = "Select * from qryAlloc_Debits where AllocStart >= pAllocStart and pAllocEnd <= pAllocEnd"
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
While a [Forms]!... reference does default to a form reference when a QueryDef is run from the GUI, it is actually just another Parameter in the query in VBA. The upshot is you don't have to recode your query/create a new one at all. Also, as #Brad mentioned, whether a parameter is in the final query of a chain of queries or not, you are able to refer to the parameter as if it is in the collection of the final query. That being the case, you should be able to use code similar to this:
Sub GetQryAllocDebits(dteAllocStart As Date, dteAllocEnd as Date)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Set db = CurrentDb()
Set qdf = db.QueryDefs("qryAlloc_Debit")
If CurrentProject.AllForms("frmReportingMain").IsLoaded Then
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = [forms]![frmReportingMain]![txtAllocStart]
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = [forms]![frmReportingMain]![txtAllocEnd]
Else
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = CStr(dteAllocStart)
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = CStr(dteAllocEnd)
End If
Set rst = qdf.OpenRecordset
Do Until rst.EOF
'...do stuff here.
Loop
Set rst = Nothing
Set qdf = Nothing
Set db = Nothing
End Function
If the referenced form is open, the code is smart enough to use the referenced controls on the form. If not, it will use the dates supplied to the subroutine as parameters. A gotcha here is that the parameters did not like when I set them as date types (#xx/xx/xx#), even if the field were dates. It only seemed to work properly if I set the params as strings. It didn't seem to be an issue when pulling the values straight out of the controls on the forms, though.
I know it's been a while since this was posted, but I'd like to throw in my tuppence worth as I'm always searching this problem:
A stored query can be resolved:
Set db = CurrentDb
Set qdf = db.QueryDefs(sQueryName)
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
For SQL:
Set db = CurrentDb
Set qdf = db.CreateQueryDef("", "SELECT * FROM MyTable " & _
"WHERE ID = " & Me.lstID & _
" AND dWeekCommencing = " & CDbl(Me.frm_SomeForm.Controls("txtWkCommencing")) & _
" AND DB_Status = 'Used'")
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
This assumes that all parameter values are accessible - i.e. forms are open and controls have values.
'I have two parameters in my recordset and I was getting the "Too few parameters. Expected 2" 'error when using an OpenRecordset in MS Access vba, and this is how I got around it and IT WORKS! see the below sub routine:
'Private Sub DisplayID_Click()
'1. I created variables for my two parameter fields xEventID and xExID as seen below:
Dim db As Database
Dim rst As Recordset
Dim xEventID As Integer
Dim xExId As Integer
'2. Sets the variables to the parameter fields as seen below:
Set db = CurrentDb
xEventID = Forms!frmExhibitorEntry!txtEventID
xExId = Forms!frmExhibitorEntry!subExhibitors!ExID
'3. Set the rst to OpenRecordSet and assign the Set the variables to the WHERE clause. Be sure to include all quotations, ampersand, and spaces exactly the way it is displayed. Otherwise the code will break!exactly as it is seen below:
Set rst = db.OpenRecordset("SELECT tblInfo_Exhibitor.EventID,tblInfo_Display.ExID, tblMstr_DisplayItems.Display " _
& "FROM tblInfo_Exhibitor INNER JOIN (tblMstr_DisplayItems INNER JOIN tblInfo_Display ON tblMstr_DisplayItems.DisplayID = tblInfo_Display.DisplayID) ON tblInfo_Exhibitor.ExID = tblInfo_Display.ExID " _
& "WHERE (((tblInfo_Exhibitor.EventID) =" & xEventID & " ) and ((tblInfo_Exhibitor.ExID) =" & xExId & " ));")
rst.Close
Set rst = Nothing
db.Close
'End Sub

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.

Errors with linked tables and Ms Access ( Run-time error '3622' : dbSeeChanges/Identity column )

I am trying to output the name of all linked tables, including their fields which are Date/Time, and that fields values.
The following code can output the first table, field name and their first value, not all values, although when it gets to the next linked table, I get this error
Run-time Error '3622'
You must use the dbSeeChanges option with OpenRecordSet when accessing a SQL Server table that has an IDENTITY column.
Here is my code
Private Sub btnGetFields_Click()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim f As Field
Dim rst As DAO.Recordset
Dim numField As Integer
Set db = CurrentDb
For Each tdf In db.TableDefs
If Left$(tdf.Connect, 9) = "ODBC;DSN=" Then
Set rst = CurrentDb.OpenRecordset(tdf.Name)
numField = rst.Fields.Count
Debug.Print "Table: " & tdf.Name
For index = 0 To numField - 1
If rst.Fields(index).Type = dbDate Then
Debug.Print "Field: " & rst.Fields(index).Name; " Value : "; rst.Fields(index).Value
End If
Next
End If
Next
Set tdf = Nothing
Set db = Nothing
End Sub
I read something that if I'm using sql tables I should use ADO?
Any ideas?
You can continue to use your existing DAO code, just change
Set rst = CurrentDb.OpenRecordset(tdf.Name)
to
Set rst = CurrentDb.OpenRecordset(tdf.Name, dbOpenSnapshot)
That opens a static read-only Recordset, so dbSeeChanges is not required.