Requery using a variable within string - sql

I am having trouble to requery my subform using a SQL string, here is my code:
Dim Day As Integer
Day = txt_Days.Value
SQL = "SELECT [qry_Records].[Tool_ID], [qry_Records].[Cal_Date]," _
& "[qry_Records].[Cal_By], [qry_Records].[As_Received], " _
& "[qry_Records].[Result], [qry_Records].[Next_Due], " _
& "[qry_Records].[Due] FROM [qry_Records]" _
& " WHERE [qry_Records].[Due] < Day;"
subform_View_Search_Records.Form.RecordSource = SQL
I tried to use different variations to quote the Day variable at the end of the SQL String such as below but nothing works:
& " WHERE [qry_Records].[Due] < ""Day"";"
& " WHERE [qry_Records].[Due] < '"Day"';"
Your help is much appreciated!

You just need to add a couple of ampersands
& " WHERE [qry_Records].[Due] < " & Day & ";"

I would try this:
SQL = "SELECT [Tool_ID], [Cal_Date]," _
& "[Cal_By], [As_Received], " _
& "[Result], [Next_Due], " _
& "[Due] FROM [qry_Records]" _
& " WHERE [Due] < " & format$(txtDays, "\#dd\/mm\/yyyy\#")
subform_View_Search_Records.Form.RecordSource = SQL
The final ";" is useless.

Related

SQL Query using VBA and ADO record set - Code takes far less time to execute when run the second time

I have a VBA Code that involves, among other things, looping of an SQL query written as a Function. When I run the code for the first time, it takes nearly 155 seconds(which is understandable given the complexity of the calculation), when I run it for the second time it takes about 19 seconds. I would like to know why? Also how can I make it run faster? The SQL server version is 2008.
FunctionX() below, is used subsequently in For and Do while Loops, so I understand that a new Connection is created every time it runs.
Option Explicit
Public
Public conn As Object 'connection
________________________________________
Sub CreateConnection ()
Set conn = CreateObject("ADODB.connection")
Dim connstring As String
connstring = "Driver={SQL Server};Server=172.20.1.172;Database=WindAccess_dat_MRK;Uid=MRK_user;Pwd=MRK010usr;"
conn.Open connstring
conn.CommandTimeout = 120
End Sub
____________________________________
FunctionX(ActiveConnection as Object, arg1,arg2,....)
Dim SQLqryfunc1 As String
Dim SQLqryfunc2 As String
Dim SQLqryfunc3 As String
Dim fValue As Variant
Set wb = ThisWorkbook
Dim recset As Object
Set recset = CreateObject("ADODB.Recordset")
Dim ItemString1 As String
Dim ItemString2 As String
Dim ItemString3 As String
Dim ItemString4 As String
Dim ItemString5 As String
Dim StartZeit As String
Dim EndZeit As String
Select Case ChooseZeit
Case 1
StartZeit = Format(InputDateErsterTag, "yyyy-mm-dd hh:mm:ss.000")
EndZeit = Format(InputDateLetzterTag, "yyyy-mm-dd 23:50:ss.000")
ItemString3 = " AND HAL150.WTUR_AVG.MaxPwrSetpoint >=" & MaxPwrSetpoint_AvgVal
ItemString4 = " AND HAL150.WTUR_MIN.MaxPwrSetpoint >=" & MaxPwrSetpoint_MinVal
ItemString5 = " AND HAL150.WTUR_AVG.W >=" & WAvg_Min
Case 2
StartZeit = Format(InputDateErsterTag, "yyyy-mm-dd hh:mm:ss.000")
EndZeit = Format(InputDateLetzterTag, "yyyy-mm-dd hh:mm:ss.000")
ItemString3 = ""
ItemString4 = ""
ItemString5 = ""
End Select
Select Case Item
Case 1 ' 1= m
ItemString1 = " count(case when WindSpeed_Avg"
ItemString2 = " then 1 end)"
Case 2 ' 2= p
ItemString1 = " sum(case when WindSpeed_Avg"
ItemString2 = " then Leistung_Avg end)"
End Select
SQLqryfunc1 = "SELECT" _
& ItemString1 _
& " >=" _
& myWindSpeedFrom _
& " and" _
& " WindSpeed_Avg" _
& " <" _
& myWindSpeedTo _
& ItemString2 _
& " as '13.48 bis 14'" _
SQLqryfunc2 = " from" _
& " (" _
& " SELECT Time_Stamp, LDName as MONr,HAL150.WTUR_AVG.W as Leistung_Avg," _
& " WdSpd as WindSpeed_Avg, HAL150.WTUR_AVG.MaxPwrSetpoint as MaxPwrSetpoint_Avg,HAL150.WTUR_MIN.MaxPwrSetpoint as MaxPwrSetpoint_Min" _
& " FROM WSKD.RegCtrPeriodBlock" _
& " INNER JOIN HAL150.WNAC_AVG " _
& " ON WSKD.RegCtrPeriodBlock.idPBlock = HAL150.WNAC_AVG.idPBlock" _
& " INNER JOIN HAL150.WTUR_AVG" _
& " ON WSKD.RegCtrPeriodBlock.idPBlock = HAL150.WTUR_AVG.idPBlock" _
& " INNER JOIN WSKD.Components" _
& " ON WSKD.RegCtrPeriodBlock.IdLD = WSKD.Components.IdLD" _
& " INNER JOIN HAL150.WTUR_MIN" _
& " ON WSKD.RegCtrPeriodBlock.idPBlock = HAL150.WTUR_MIN.idPBlock" _
& " WHERE Time_Stamp BETWEEN" _
& " '" & StartZeit & "'" _
& " AND" _
& " '" & EndZeit & "'" _
& " AND" _
& " LDName in" _
& " (" & "'" & MONr & "'" & ")" _
& ItemString3 _
& ItemString4 _
& ItemString5 _
& " )" _
& " tbl"
SQLqryfunc3 = SQLqryfunc1 & SQLqryfunc2
'Debug.Print SQLqryfunc3
recset.Open SQLqryfunc3, myActiveConnection
fValue = recset.Getrows
Functionx = fValue(0, 0)
'Debug.Print Functionx
End Function
The second time your queries are executed they are likely cached by SQL server.
Lowest hanging fruit to making your query faster would be to take a sample output from this function and run it through SQL Server Management Studio with execution plan enabled: https://learn.microsoft.com/en-us/sql/relational-databases/performance/display-an-actual-execution-plan?view=sql-server-ver15 . It'll give you some tips on what indexes could be added to certain columns to make your query faster. If you have create privileges on database you can create some indexes to speed things up a bit. You'll also be able to see which parts of your query are the most expensive.
Also, dynamic SQL is hard on SQL server precisely because it has to come up with a new optimized execution plan each time and isn't able to keep it for very long. The reason it slows down again is because the optimized execution plan it creates the first time is ejected from the cache. SQL concatenation like this & " WHERE Time_Stamp BETWEEN" _ & " '" & StartZeit & "'" _ also opens you up to SQL injection attacks if the input is from the user. So if you can use parameters in your query instead using ADODB much like in this example answer here: https://stackoverflow.com/a/10353908/4641232 it would make your code more secure.
Another idea to optimize your code might be to move the processing of conditionals onto SQL server. For example, this case here:
Select Case ChooseZeit
Case 1
StartZeit = Format(InputDateErsterTag, "yyyy-mm-dd hh:mm:ss.000")
EndZeit = Format(InputDateLetzterTag, "yyyy-mm-dd 23:50:ss.000")
ItemString3 = " AND HAL150.WTUR_AVG.MaxPwrSetpoint >=" & MaxPwrSetpoint_AvgVal
ItemString4 = " AND HAL150.WTUR_MIN.MaxPwrSetpoint >=" & MaxPwrSetpoint_MinVal
ItemString5 = " AND HAL150.WTUR_AVG.W >=" & WAvg_Min
Case 2
StartZeit = Format(InputDateErsterTag, "yyyy-mm-dd hh:mm:ss.000")
EndZeit = Format(InputDateLetzterTag, "yyyy-mm-dd hh:mm:ss.000")
ItemString3 = ""
ItemString4 = ""
ItemString5 = ""
End Select
Instead of having two possible WHERE clauses, have your VBA create a SQL script that includes both and have SQL server make the distinction. For example, the WHERE clause in your output might look like this:
...
WHERE
...
AND
(
(
2 = 1 -- ChooseZeit == 2 in VB so that's where the 2 comes from.
AND HAL150.WTUR_AVG.MaxPwrSetpoint >= 4 -- I just picked a random number here.
AND HAL150.WTUR_MIN.MaxPwrSetpoint >= 2 -- I just picked a random number here.
AND HAL150.WTUR_AVG.W >= 3 -- I just picked a random number here.
)
OR
(
2 = 2 -- ChooseZeit == 2 in VB so that's where the 2 comes from.
)
)
...
With your WHERE clause constructed this way you give SQL Server a constant query structure to build an optimized path. If you use parameters, you can also now more easily move the scripted query created by VB into a stored procedure that you can compile on SQL server to possibly give even more gains.

SQL concatenation inside a vbscript

I have a problem with a SQL concatenation used in VB script.
I'm trying to contatenate a variable inside a SQL request but whatever the concatenation method i use, it fails !
Here is my code
dim nbr3Eu as integer = 6
dim waa2Eu as string
waa2Eu = "" _
& "SELECT riblib" _
& " ," & nbr3Eu _
& " FROM PCH" _
& " WHERE RibPaysNuf <> 'NufSocPaysMU'" _
& " AND PchID in " & XPchID _
& " GROUP BY DevCode"
I've tried it with the PLUS sign concatenation but i still have the same result
dim nbr3Eu as integer = 6
dim waa2Eu as string
waa2Eu = "" _
+ "SELECT riblib" _
+ " ," + nbr3Eu _
+ " FROM PCH" _
+ " WHERE RibPaysNuf <> 'NufSocPaysMU'" _
+ " AND PchID in " + XPchID _
+ " GROUP BY DevCode"
Need help, THANKS
You must concatenate String, try replacing & nbr3Eu by & CStr(nbr3Eu)

item cannot be found in the collection corresponding to the requested name or ordinal

My code gives the following error. How can I correct this?
Item cannot be found in the collection corresponding to the requested name or ordinal
ElseIf Me.chkItem.Checked = True Then
Dim CheckNumber As String = ""
Dim CheckRef As String = ""
dsvoucheritem.Clear()
DSVoucher_Expense.Clear()
DSVoucher_Check.Clear()
Try
Me.lstCV.Items.Clear()
strDiscount = Nothing
rec.Open("select billpaymentcheckline.txnnumber, billpaymentcheckline.txndate" _
& ", billpaymentcheckline.payeeentityreffullname" _
& ", billpaymentcheckline.amount, billitemline.itemlineitemreffullname" _
& ", billitemline.memo" _
& ", billpaymentcheckline.appliedtotxndiscountamount" _
& ", billpaymentcheckline.appliedtotxnrefnumber, billpaymentcheckline.bankaccountreffullname" _
& ", billpaymentcheckline.appliedtotxndiscountaccountreffullname" _
& ", billpaymentcheckline.appliedtotxntxndate, billpaymentcheckline.appliedtotxnamount" _
& ", billpaymentcheckline.refnumber, account.AccountNumber from (billitemline inner join" _
& " billpaymentcheckline on billitemline.refnumber=billpaymentcheckline.appliedtotxnrefnumber) left outer join" _
& " account on billitemline.APAccountreflistid=account.listid where" _
& " billpaymentcheckline.bankaccountreflistid='" &Me.lblBankID.Text & "' and" _
& " billpaymentcheckline.refnumber between '" & CInt(Me.txtRefFR.Text)
& "' and '" & CInt(Me.txtRefTO.Text) & "'", con, ADODB.CursorTypeEnum.adOpenForwardOnly, ADODB.LockTypeEnum.adLockReadOnly)
It's saying it doesn't recognize one of your column names. Double check all of them. You can also try removing fields until you find the culprit.
memo is a reserved word in Access SQL.
Try billitemline.[memo]

access 2013 increasing quantity in a table field

Good day. I'm a little stumped about what is happening in my code. I have a userform which collects txtQntyRecd and cboSupplySource. I calculate the lookupValue. And it works just fine. It successfully places the txtQntyRecd in the correct tblWarehouseLocations.WQuantity location. The code is:
updateQnty = "UPDATE tblSupplySources INNER JOIN ((tblWarehouseLocations " & _
"INNER JOIN tblSupplySource_WarehouseLocation ON tblWarehouseLocations.WLocation_ID = tblSupplySource_WarehouseLocation.SWLocation_ID)) " & _
"ON tblSupplySources.SupplySourceID = tblSupplySource_WarehouseLocation.Supply_Source_ID " & _
"SET tblWarehouseLocations.WQuantity = '" & Me.txtQntyRecd & "'" & _
"WHERE (((tblSupplySource_WarehouseLocation.Supply_Source_ID)= " & Me.cboSupplySource & ") " & _
" AND ((tblWarehouseLocations.WLocation_ID)=" & lookupValue & "))"
CurrentDb.Execute updateQnty, dbFailOnError
What I want to do is add the next quantity to the same location. I get weird results if I change the SET statement to the following:
SET tblWarehouseLocations.WQuantity = tblWarehouseLocations.WQuantity + '" & Me.txtQntyRecd & "'"
If I put 200 in the first statement, I get 200 in my WQuantity field. When I change to the second statement and I try to add 1 to the 200 I get a result of 211. If I add 1 again, the result is 223. Add 1 again, the result is 236.
Could someone explain what is happening and why the results aren't 201, 202 and 203? In the future I will need to subtract quantities from WQuantity as well.
Thanks
You're adding quotes around an integer and appending it as a string. Change it to:
".....
SET tblWarehouseLocations.WQuantity = tblWarehouseLocations.WQuantity + " & val(Me!txtQntyRecd) & "....
...."
I've changed the . to a ! as I think it's still a nice distinction between objects properties and controls, and used the val function as it converts the string number value to the integer value.
This is your query in full:
' When I use values from controls, I like to store them in vars
Dim quantityReceived As integer
quantityReceived = val(Me!txtQntyRecd)
updateQnty = "UPDATE tblSupplySources INNER JOIN ((tblWarehouseLocations " & _
"INNER JOIN tblSupplySource_WarehouseLocation ON tblWarehouseLocations.WLocation_ID = tblSupplySource_WarehouseLocation.SWLocation_ID)) " & _
"ON tblSupplySources.SupplySourceID = tblSupplySource_WarehouseLocation.Supply_Source_ID " & _
"SET tblWarehouseLocations.WQuantity = tblWarehouseLocations.WQuantity + " & quantityReceived & _
" WHERE (((tblSupplySource_WarehouseLocation.Supply_Source_ID)= " & Me.cboSupplySource & ") " & _
" AND ((tblWarehouseLocations.WLocation_ID)=" & lookupValue & "))"
I solved the problem. I created a SELECT query to get the present amount in WQuantity. Now quantityReceived = Me!txtQntyRecd + the present amount. With SET tblWarehouseLocations.WQuantity = " & quantityReceived it works fine. However, if just seems so cumbersome.
' lookupValue gives the index into the tblWarehouseLocations where WQuantity resides
Dim lookupValue As Integer
lookupValue = DLookup("[WLocation_ID]", "[tblWarehouseLocations]", "[Location_Name] = '" & Me.cboWLocation & "'")
'Define SQL Query
strSQL = "select tblWarehouseLocations.WQuantity FROM tblWarehouseLocations WHERE (((tblWarehouseLocations.WLocation_ID)= " & lookupValue & "))"
Set rs = db.OpenRecordset(strSQL)
If IsNull(rs!WQuantity) Then
dbvalue = 0
Else
dbvalue = rs!WQuantity
End If
Dim quantityReceived As Integer
quantityReceived = Val(Me!txtQntyRecd) + dbvalue
updateQnty = "UPDATE tblSupplySources INNER JOIN ((tblWarehouseLocations " & _
"INNER JOIN tblSupplySource_WarehouseLocation ON tblWarehouseLocations.WLocation_ID = tblSupplySource_WarehouseLocation.SWLocation_ID)) " & _
"ON tblSupplySources.SupplySourceID = tblSupplySource_WarehouseLocation.Supply_Source_ID " & _
"SET tblWarehouseLocations.WQuantity = " & quantityReceived & _
" WHERE (((tblSupplySource_WarehouseLocation.Supply_Source_ID)= " & Me.cboSupplySource & ") " & _
" AND ((tblWarehouseLocations.WLocation_ID)=" & lookupValue & "))"
CurrentDb.Execute updateQnty, dbFailOnError

SQL Query works in MS-Access but cannot implement it in vb.net form

The block of code immediately following (given to me by a stackoverflow solver) works perfectly in MS-Access. I'm trying to convert it to work in a vb.net form accessing the very same MS-Access database. I get an error and cannot see my mistake. Are there any vb.net coders that can see what I'm doing wrong. The first block of code works in MS-Access and is the code I'm trying to convert. And the second block of code is my conversion attempt.
SELECT at.animalID, amt.milestoneType
FROM
animals_Table at
LEFT JOIN
(
SELECT animalID, milestoneType
FROM animalMilestones_Table
WHERE milestoneType = 'Intake'
) amt
ON at.animalID = amt.animalID
Now, my conversion attempt:
dim selectAnimal as string
selectAnimal = "SELECT at.animalID, amt.milestoneType" & _
" FROM animals_Table at" & _
" LEFT JOIN" & _
" (" & _
" SELECT animalID, milestoneType" & _
" FROM animalMilestones_Table" & _
" WHERE milestoneType = '" & "Intake" & "'" & _
" ) amt" & _
" ON at.animalID = amt.animalID"
The error code I get is
!ErrorInfo.GetDescription failed with E_FAIL(0x80004005)
It appears that ACE.OLEDB doesn't like at as a table alias. Try this instead
Dim selectAnimal As String
selectAnimal = "SELECT atbl.animalID, amtbl.milestoneType" & _
" FROM animals_Table atbl" & _
" LEFT JOIN" & _
" (" & _
" SELECT animalID, milestoneType" & _
" FROM animalMilestones_Table" & _
" WHERE milestoneType = '" & "Intake" & "'" & _
" ) AS amtbl" & _
" ON atbl.animalID = amtbl.animalID"