Setting two rowsources in same procedure is terrible slow - Access 2010 - sql

I have two Listboxes which are filled via vba on a click event. The table 'Project' is a odbc datasource with 250 records.
List1.RowSource = "SELECT Name FROM Project WHERE ProjectID = " & ProjectID.Caption & " AND Year = " & ActualYear.Caption & " ORDER BY Name"
List2.RowSource = "SELECT ProjectShare FROM Project WHERE ProjectID = " & ProjectID.Caption & " AND Year = " & ActualYear.Caption & " ORDER BY Name"
So far so good. But when I run this code, it takes everytime up to 30sec to complete. I thought, okay it's because of odbc and so on. But when I run only one line of this code (no matter which), it is fast as lightning (0,1sec).
How can it be, that one query takes 0,1sec and two querys 30sec? May I could make a break between these two lines? Btw. without odbc everything works like a charm, no matter how many lines

You can bind both listboxes to the same recordset by manually creating the recordset. This allows Access to only query the table once instead of twice at the same time, avoiding any locking conflicts, and tends to avoid other problems as well.
This also allows you to use parameters, fixing any errors introduced by string concatenation.
Dim rs As DAO.Recordset
With CurrentDb.CreateQueryDef("", "SELECT Name, ProjectShare FROM Project WHERE ProjectID = p1 AND Year = p2 ORDER BY Name")
.Parameters(0).Value= ProjectID.Caption
.Parameters(1).Value = ActualYear.Caption
Set rs = .OpenRecordset(dbOpenSnapshot) 'Snapshot because it won't be updated
End With
Set list1.Recordset = rs
Set list2.Recordset = rs
Note that I have had errors occur when an object bound to a recordset with parameters was requeried, so you might want to use string concatenation if that's happening.

Related

Why does MS Access prompt to enter parameter in update query which already has values?

I am making a database where the user can change the name of a company in a table. However , whenever I use the update query, it asks for a parameter which is already supplied. The old company name is in the variable new_comp and then the new one is in the Me.comp1_box.Value.
Funny enough the query runs excellently whenever I hit ok and enter nothing inside the "Enter Parameter" setting
Dim record_changer As String
record_changer = "UPDATE " & "[" & new_comp & "]" & " SET " & "[" & new_comp & "]" & ".Company_Name =" & """" & Me.comp1_box.Value & """" & ";"
MsgBox (record_changer)
DoCmd.RunSQL (record_changer)
This is the final value of the record_changer.
UPDATE [EREDEON TECHNOLOGIES] SET [EREDEON TECHNOLOGIES].Company_Name="EREDEON TECH";
This is how it is when the code runs.
This is the query that it is supposed to run
It gives this prompt meaning it's supposed to run perfectly, meaning there is nothing wrong with the Query
This what pops up
Can anyone please help me out?
I am genuinely lost.The name of the Old Company name is EREDEON TECHNOLOGIES and the new name is EREDEON TECH
But funny enough when I just hit Okay without entering a value into the parameter dialogue box, it actually makes the changes.-_- weird
This happens, then I press "OK"
THEN THIS HAPPENS, Then I hit Okay
This is the table before.
It updates the table the new value which is EREDEON TECH. When I just hit OK, without typing anything into Parameter Dialogue.
Try changing your SQL string to the following. Note the single quotes change around Me.comp1_box.Value.
record_changer = "UPDATE " & "[" & new_comp & "]" & " SET " & "[" & new_comp & "]" & ".Company_Name ='" & Me.comp1_box.Value & "';"
Misused quote marks is the most common cause for the Parameter Value prompt. If that doesn't work, use this article to perform step-by-step trouble shooting on all of the other usual causes, Why does Access want me to enter a parameter value?
You can also reference the following articles:
MS Docs, Quotation marks in string expressions
Bytes, (') and (") - Where and When to use them
Fundamentally, the issue is due to the use of double quotes in VBA which works in Access SQL by itself but not via VBA using DoCmd.RunSQL. You could have used single quotes to enclose company name value.
However, avoid concatenating VBA literals to SQL queries with quotes in the first place. Instead, use the industry best practice of parameterization which is available in MS Access using QueryDefs in VBA and PARAMETERS clause in SQL:
Dim record_changer As String
Dim qdef As QueryDef
sql = "PARAMETERS new_name_param TEXT; " _
& "UPDATE [" & new_comp & "] " _
& "SET Company_Name = new_name_param;"
' SET UP QUERYDEF
Set qdef = CurrentDb.CreateQueryDef("", sql)
' BIND PARAMS
qdef!new_name_param = Me.comp1_box.Value
' RUN ACTION
qdef.Execute
' RELEASE RESOURCE
Set qdef = Nothing
Nonetheless, the need to concatenate table name, new_comp, in query is questionable database design. Proper names (EREDEON TECHNOLOGIES, GAME DISCOUNT STORE, SHOPRITE, etc.) should never be names of tables. Avoid maintaining a separate table for every company. Instead, normalize data for a single table of all companies, then run UPDATE with WHERE adding a second parameter.
' PREPARED STATEMENT, NO VARIABLE CONCATENATION
sql = "PARAMETERS new_name_param TEXT, old_name_param TEXT; " _
& " UPDATE Companies " _
& " SET Company_Name = new_name_param" _
& " WHERE Company_Name = old_name_param;"
Set qdef = CurrentDb.CreateQueryDef("", sql)
qdef!new_name_param = Me.comp1_box.Value
qdef!old_name_param = new_comp
qdef.Execute
In fact, since above SQL is now separated from VBA, save the query without VBA punctuation (&, ", or _) as a separate object and call it in QueryDefs by name:
Set qdef = CurrentDb.QueryDefs("mySavedQuery")
qdef!new_name_param = Me.comp1_box.Value
qdef!old_name_param = new_comp
qdef.Execute
Even better, if your parameters derive from controls on open forms, include them directly in query for a single line VBA call. Below runs the normalized version of single Companies table:
SQL (save as query object, adjust names to actuals)
UPDATE Companies
SET Company_Name = Forms!myForm!comp1_box
WHERE Company_Name = Forms!myForm!new_comp
VBA (no need to close action queries)
DoCmd.OpenQuery "mySavedQuery"

Pass Through Query Won't Run From Command Line

I created a pass through query in Access.
All it says is .
sp_Submit ''
If I click on it directly it runs the SSMS stored procedure which just changes some test tables.
However if I run it in VBA it does not work. It doesn't error out or anything, it just does not work.
I have tried
sSQL = "sp_Submit '" & Me.cboNumber & "'"
and
sSQL = "sp_Submit '"
Please not the stored procedure isn't doing anything much at this point. I have it testing some stuff. It just deletes everything in one table and inserts it in another.
What am I doing wrong? I've used this in the past and it has worked so I'm not sure why it doesn't work this time. The stored procedure itself is set up to accept one variable but it doesn't actually do anything with it (yet.).
Thank you.
Given what you have to far, then you should be able to edit the saved pass though query with
Sp_Submit 'test'
Assuming the 1 paramter is text. If the parameter is to be a number, then
Sp_Submit 123
At this point, you have to save that query. Now click on it, does it run correctly?
And in place of clicking on the query, you can certainly do
CurrentDB.execute "name of saved query goes here"
However, keep in mind that a PT query is raw T-SQL. What executes runs 100% on the server. This means that such query(s) cannot contain references to any form, or anything else. So you have to “pre-process” or create the value you wish to pass and modify the PT query. So your code of creating the SQL you have looks correct, but you then have to take that sql string and "set" the PT query.
The most easy way to do this is with code like this:
With CurrentDb.QueryDefs("MyPass")
.SQL = "sp_Submit '" & Me.cboNumber & "'"
.Execute
End With
Of course if the PT query returns records, then you would go:
Dim rstRecords As DAO.Recordset
With CurrentDb.QueryDefs("MyPass")
.SQL = "sp_Submit '" & Me.cboNumber & "'"
.ReturnsRecords = True
Set rstRecords = .OpenRecordset
End With
And to be fair, you likely should set “returns” records = false in the first example. You can do this in the property sheet of the save query, or in code like this:
With CurrentDb.QueryDefs("MyPass")
.SQL = "sp_Submit '" & Me.cboNumber & "'"
.ReturnsRecords = False
.Execute
End With
Note that you can use the one PT query over and over in your code. So once you ceated that one PT query, then you can use it to pass any new sql you wish, such as:
Dim rstRecords As DAO.Recordset
With CurrentDb.QueryDefs("MyPass")
.SQL = "select * from tblHotels"
.ReturnsRecords = True
Set rstRecords = .OpenRecordset
End With
So you can "stuff" in any sql you want for that one PT query - and use it throughout your application.

Referencing Variable for Functions

Every two weeks there will be a new table with new data coming in to me, I need to update that onto a master table. I want to automate this process.
I would like to declare a variable that a user can input the date the data is from, and based on that date update to the appropriate field on the master table. I have no clue how to make SQL functions use variables to locate tables with the syntax, not even sure if this can be done. Any help would be appreciated.
As I am inexperienced, I am making a VBA Macro and embedding the SQL code from the access query I made.
Sub UpdateFieldX()
Dim SQL As String
SQL = "UPDATE [15-Jun-16] " & _
"RIGHT JOIN MasterSPI " & _
"ON [15-Jun-16].[SR#] = MasterSPI.[SR#] " & _
"SET MasterSPI.[30-Jun-16] = [15-Jun-16].[SPI]; " _
DoCmd.RunSQL SQL
End Sub
I've done something similar to this and used an Update Query and Insert Query.
It sounds like you're trying to just update any existing records that may need updating and then adding new records into the table.
For an update, I'd try creating a query in SQL view and type something like:
UPDATE MasterSPI SET MasterSPI.SRnumber = [newtablename]![SRnumber] etc.
and do that for each field in your table.
For inserting you could do something like:
INSERT INTO MasterSPI SELECT * FROM newtablename
That may help you get started.
I know many of you are advanced users but I found an answer that fit my quick needs. As a notice and disclaimer for other people, it will be in no way secure, it is more for personal use such that I do not need to spend an hour doing append and updates to several master tables repetitively.
To do this, I made a global string variable called name, then I made another variable called strung that translated it into a readable string for referencing. I then made an SQL string that references that strung variable. This allows the user to submit an input for the global variable, which translates into a readable string for the RunSQL method.
Here's a snippet of the parts that were most relevant, I hope it helps whoever comes next with the same scenario.
**
Public name As String 'global variable declared so that the new field to be created can be used elsewhere
name = InputBox("Name of Month", "InputBox") 'variable that takes user input and it will be name for new fields to be added
Dim SQLa As String 'creates a string variable such that it will be read as an SQL line by the RunSQL method
strung = "[" & name & "]" 'sets strung as global varible name, which is user input on the specific table being used to update
'the following lines runs a query such that it updates the master table with new data and does the grouping by SR number
SQLa = "UPDATE " & strung & " " & _
"RIGHT JOIN MasterSPI " & _
"ON " & strung & "." & "[SR#] = MasterSPI.[SR#] " & _
"SET MasterSPI." & strung & " = " & strung & "." & "[SPI]; " _
DoCmd.RunSQL SQLa 'executes the SQL code in VBA **

MS Access: Use variables instead of text.SetFocus method to query

I have two parameters form a FROM and THRU textbox. The code object is txtFROM and txtTHRU. Now I tried to open the query and reports with a txtFROM.SetFocus and txtTHRU.SetFocus and used in the query criteria: Between [FORMS]![ReportName]![txtFROM].[Text] and [FORMS]![ReportName]![txtTHRU].[Text]. However nothing turns up when I link a button to the query and report to show the data with those two parameters. I think it may be due to the fact that the .SetFocus method will only work on one parameter, so I think writing VBA variables to pass into a query might work if possible. The thing is I do not know if it is possible to call a VBA variable while running to a query as it were an object. The variables would otherwise read .SetFocus to ready the parameter to be passed to the Access query.
DoCmd.SetWarnings False
If IsNull(txtFROM.Value) = False And IsNull(txtTHRU.Value) = False Then
dataFROM = CDate(txtFROM.Value)
dataTHRU = CDate(txtTHRU.Value)
End If
DoCmd.OpenQuery ("Expiring")
DoCmd.OpenReport ("Expirees"), acViewPreview
DoCmd.SetWarnings True
The above variables dataFROM and dataTHRU would be what I would like to fit in the query criteria to reference the Form which displays reports.
You might need to script the query "on the fly" by using CreateQueryDef. Sort of like:
Dim db as Database
Dim qdf as QueryDef
Set db = CurrentDB
Set qdf = db.CreateQueryDef("Expiring", "SELECT * FROM MyTable WHERE " &_
"MyDate >= #" & CDate(txtFROM.Value) & "# and MyDate =< #" CDate(txtTHRU.Value) & "#")
DoCmd.OpenReport "Expirees", acViewPreview
Of course, you'll probably need to add some code at the beginning to delete that query if it already exists. Definitely inside an If/Then because if the code happens to burp and doesn't create the query one time, it'll crash the next time you run it.
Edit
As suggested by HansUp, another option is simply to alter the query's SQL statement, which you can do in code.
Set myquery = db.OpenQueryDef("Expiring")
strsql = "SELECT * FROM MyTable WHERE " &_
"MyDate >= #" & CDate(txtFROM.Value) & "# and MyDate =< #" CDate(txtTHRU.Value) & "#"
myquery.SQL = strsql
myquery.Close
It looks like there was a mixup in my query code, the FROM was duplicated, FROM FROM, not FROM THRU. The code works as it should have with the reference to the Reports and Form which the text controls. Keep with the usual method then.

Access 2007 VBA Query Shows Data in Query Analyzer But Not in VBA Coded Recordset

I have a function I've written that was initially supposed to take a string field and populate an excel spreadsheet with the values. Those values continually came up null. I started tracking it back to the recordset and found that despite the query being valid and running properly through the Access query analyzer the recordset was empty or had missing fields.
To test the problem, I created a sub in which I created a query, opened a recordset, and then paged through the values (outputting them to a messagebox). The most perplexing part of the problem seems to revolve around the "WHERE" clause of the query. If I don't put a "WHERE" clause on the query, the recordset always has data and the values for "DESCRIPTION" are normal.
If I put anything in for the WHERE clause the recordset comes back either totally empty (rs.EOF = true) or the Description field is totally blank where the other fields have values. I want to stress again that if I debug.print the query, I can copy/paste it into the query analyzer and get a valid and returned values that I expect.
I'd sure appreciate some help with this. Thank you!
Private Sub NewTest()
' Dimension Variables
'----------------------------------------------------------
Dim rsNewTest As ADODB.Recordset
Dim sqlNewTest As String
Dim Counter As Integer
' Set variables
'----------------------------------------------------------
Set rsNewTest = New ADODB.Recordset
sqlNewTest = "SELECT dbo_partmtl.partnum as [Job/Sub], dbo_partmtl.revisionnum as Rev, " & _
"dbo_part.partdescription as Description, dbo_partmtl.qtyper as [Qty Per] " & _
"FROM dbo_partmtl " & _
"LEFT JOIN dbo_part ON dbo_partmtl.partnum = dbo_part.partnum " & _
"WHERE dbo_partmtl.mtlpartnum=" & Chr(34) & "3C16470" & Chr(34)
' Open recordset
rsNewTest.Open sqlNewTest, CurrentProject.Connection, adOpenDynamic, adLockOptimistic
Do Until rsNewTest.EOF
For Counter = 0 To rsNewTest.Fields.Count - 1
MsgBox rsNewTest.Fields(Counter).Name
Next
MsgBox rsNewTest.Fields("Description")
rsNewTest.MoveNext
Loop
' close the recordset
rsNewTest.Close
Set rsNewTest = Nothing
End Sub
EDIT: Someone requested that I post the DEBUG.PRINT of the query. Here it is:
SELECT dbo_partmtl.partnum as [Job/Sub], dbo_partmtl.revisionnum as Rev, dbo_part.partdescription as [Description], dbo_partmtl.qtyper as [Qty Per] FROM dbo_partmtl LEFT JOIN dbo_part ON dbo_partmtl.partnum = dbo_part.partnum WHERE dbo_partmtl.mtlpartnum='3C16470'
I have tried double and single quotes using ASCII characters and implicitly.
For example:
"WHERE dbo_partmtl.mtlpartnum='3C16470'"
I even tried your suggestion with chr(39):
"WHERE dbo_partmtl.mtlpartnum=" & Chr(39) & "3C16470" & Chr(39)
Both return a null value for description. However, if I debug.print the query and paste it into the Access query analyzer, it displays just fine. Again (as a side note), if I do a LIKE statement in the WHERE clause, it will give me a completely empty recordset. Something is really wonky here.
Here is an interesting tidbit. The tables are linked to a SQL Server. If I copy the tables (data and structure) locally, the ADO code above worked flawlessly. If I use DAO it works fine. I've tried this code on Windows XP, Access 2003, and various versions of ADO (2.5, 2.6, 2.8). ADO will not work if the tables are linked.
There is some flaw in ADO that causes the issue.
Absolutely I do. Remember, the DEBUG.PRINT query you see runs perfectly in the query analyzer. It returns the following:
Job/Sub Rev Description Qty Per
36511C01 A MAIN ELECTRICAL ENCLOSURE 1
36515C0V A VISION SYSTEM 1
36529C01 A MAIN ELECTRICAL ENCLOSURE 1
However, the same query returns empty values for Description (everything else is the same) when run through the recordset (messagebox errors because of "Null" value).
I tried renaming the "description" field to "testdep", but it's still empty. The only way to make it display data is to remove the WHERE section of the query. I'm starting to believe this is a problem with ADO. Maybe I'll rewriting it with DAO and seeing what results i get.
EDIT: I also tried compacting and repairing a couple of times. No dice.
When using ADO LIKE searches must use % instead of *. I know * works in Access but for some stupid reason ADO won't work unless you use % instead.
I had the same problem and ran accoss this forum while trying to fix it. Replacing *'s with %'s worked for me.
Description is a reserved word - put some [] brackets around it in the SELECT statement
EDIT
Try naming the column something besides Description
Also are you sure you are using the same values in the where clause - because it is a left join so the Description field will be blank if there is no corresponding record in dbo_part
EDIT AGAIN
If you are getting funny results - try a Compact/Repair Database - It might be corrupted
Well, what I feared is the case. It works FINE with DAO but not ADO.
Here is the working code:
Private Sub AltTest()
' Dimension Variables
'----------------------------------------------------------
Dim rsNewTest As DAO.Recordset
Dim dbl As DAO.Database
Dim sqlNewTest As String
Dim Counter As Integer
' Set variables
'----------------------------------------------------------
sqlNewTest = "SELECT dbo_partmtl.partnum as [Job/Sub], dbo_partmtl.revisionnum as Rev, " & _
"dbo_part.partdescription as [TestDep], dbo_partmtl.qtyper as [Qty Per] " & _
"FROM dbo_partmtl " & _
"LEFT JOIN dbo_part ON dbo_partmtl.partnum = dbo_part.partnum " & _
"WHERE dbo_partmtl.mtlpartnum=" & Chr(39) & "3C16470" & Chr(39)
Debug.Print "sqlNewTest: " & sqlNewTest
Set dbl = CurrentDb()
Set rsNewTest = dbl.OpenRecordset(sqlNewTest, dbOpenDynaset)
' rsnewtest.OpenRecordset
Do Until rsNewTest.EOF
For Counter = 0 To rsNewTest.Fields.Count - 1
MsgBox rsNewTest.Fields(Counter).Name
Next
MsgBox rsNewTest.Fields("TestDep")
rsNewTest.MoveNext
Loop
' close the recordset
dbl.Close
Set rsNewTest = Nothing
End Sub
I don't use DAO anywhere in this database and would prefer not to start. Where do we go from here?
I know some time has passed since this thread started, but just in case you're wondering, I have found out some curious about Access 2003 and the bug may have carried over to 2007 (as I can see it has).
I've had a similar problem with a WHERE clause because I needed records from a date field that also contained time, so the entire field contents would look like #6/14/2011 11:50:25 AM# (#'s added for formatting purposes).
Same issue as above, query works fine with the "WHERE ((tblTransactions.TransactionDate) Like '" & QueryDate & "*');" in the query design view, but it won't work in the VBA code using ADO.
So I resorted to using "WHERE ((tblTransactions.TransactionDate) Like '" & QueryDate & " %%:%%:%% %M');" in the VBA code, with ADO and it works just fine. Displays the record I was looking for, the trick is not to use "*" in the Like clause; or at least that was the issue in my case.
I put brackets around the word "Description" in the SELECT statement, but it's behavior remains. It works fine as long as I don't put anything in the WHERE clause. I've found if I put anything in the where clause, the description is blank (despite showing up in the Query analyzer). If I use a LIKE statement in the WHERE clause, the entire recordset is empty but it still works properly in the Query Analyzer.
Ultimately I think it's a problem with running ADO 2.8 on Vista 64
Personally I have always used DAO in Access projects.