I have the following SQL query in my Access database, connected to SQL Server 2008:
SELECT COUNT(*) as mCount
FROM [Projects]
WHERE [DateProjectSubmitted]>'2014';
This works great and accomplishes exactly what I need.
However, I cannot seem to adapt the query for work within Access within a function I have (all error handling removed):
Public Function getNumberOfYearToDateProjects() As Integer
Dim rsMyRecordSet As ADODB.Recordset
Dim sSql As String
Set rsMyRecordSet = New ADODB.Recordset
sSql = "SELECT COUNT(*) as mCount FROM [Projects] WHERE [DateProjectSubmitted]>#" & Format(Date, "YYYY") & "#"
rsMyRecordSet.Open sSql, CurrentProject.Connection
getNumberOfYearToDateProjects = rsMyRecordSet.Fields("mCount")
End Function
I know Access wants # symbols in the date expression but I cannot seem to make it recognize 2014 as a date for purposes of comparison.
If I copy the SQL directly, I run into problems with data mismatches.
I could do the following, but this just seems ugly
sSql = "SELECT COUNT(*) as mCount FROM [Projects] WHERE [DateProjectSubmitted]>#" & DateSerial(Year(Date), 1, 1) & "#"
Can I modify the SQL query or do I need to use something like DateSerial to create a fake 2014-01-01 date for the comparison?
Assuming that DateProjectSubmitted is a date field, and yourYear is a number
SELECT COUNT(*) as mCount FROM [Projects] WHERE YEAR([DateProjectSubmitted]) > " & yourYear
Related
I'm trying to compare a date from user input with a date stored in an Access database, using ASP Classic.
The user inputs a date (SearchedStartDate), which is submitted through a form, and then my SQL statement should select records where the start date field is more recent than the date the user inputted.
The Access database field is a Date/Time data type, and my SQL statement is like:
SELECT SessionID, StartDate
FROM SessionTable
WHERE StartDate>='"&SearchedStartDate&"'
ORDER BY StartDate DESC"
I've searched around and tried lots of different things, such as using # signs around the date for Access, and SearchedStartDate = FormatDateTime(SearchedStartDate, vbShortDate), but all my attempts result in a "Data type mismatch in criteria expression" error.
How can I get this to work?
As you've "searched around" you must have seen warnings that Dynamic SQL is widely regarded as a bad thing. The correct approach is to use a parameterized query, for example,
Const adDBTimeStamp = 135
Const adParamInput = 1
Dim SearchedStartDate
SearchedStartDate = "2018-01-01" ' test data
Dim cmd
Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con ' currently open ADODB.Connection
cmd.CommandText = _
"SELECT SessionID, StartDate " & _
"FROM SessionTable " & _
"WHERE StartDate >= ? " & _
"ORDER BY StartDate DESC"
cmd.Parameters.Append cmd.CreateParameter("?", _
adDBTimeStamp, adParamInput, , CDate(SearchedStartDate))
Dim rst
Set rst = cmd.Execute ' ADODB.Recordset
Do Until rst.EOF
' work with the values in the current row of the Recordset
rst.MoveNext
Loop
It should read like this:
"SELECT SessionID, StartDate
FROM SessionTable
WHERE StartDate >= #" & SearchedStartDate & "#
ORDER BY StartDate DESC"
where SearchedStartDate should be a string of the format yyyy/mm/dd to express your date value. If Format is available, you can do:
SearchedStartDate = Format(YourDateValue, "yyyy\/mm\/dd")
I am trying to run an Update Query in VBA and am at a lost as to what I'm supposed to write for the code. I'm running a query to find the most recent date from a table. That query works fine. Now I want to run an update query to update another table's date field to equal to the date that was queried. Here is what I have:
Dim Date1 As Date
Dim newdate1
'selects datadate 1
Date1 = CurrentDb.OpenRecordset("Select Max(Date1_Event) from TBL_Event WHERE ID = '" & [Forms]![FRM_Main]![ID] & "'")(0)
'update datadate 1
newdate1 = CurrentDb.OpenRecordset("Update Tbl_Name set CollectionDate = DataDate1 WHERE PID = '" & [Forms]![FRM_Main]![ID] & "'")(0)
Is there a way to run an update query like this? Thank you.
Action queries (DELETE, UPDATE, INSERT INTO) are to be executed (CurrentDb.Execute) while SELECT queries are to be opened as recordsets (CurrentDb.OpenRecordset).
Additionally, consider using parameterization to avoid any need of quote enclosure or string concatenation in query. And here the max date is calculated with domain aggregate, DMax(), instead of opening another query.
Dim strSQL As String
Dim qdef As Querydef
' PREPARE SQL STATEMENT
strSQL = "PARAMETERS [MaxDateParam] Date, [FormIDParam] Long;" _
& "UPDATE Tbl_Name SET CollectionDate = [MaxDateParam]" _
& " WHERE PID = [FormIDParam];"
' BUILD TEMP QUERY
Set qdef = CurrentDb.CreateQueryDef("", strSQL)
' BIND PARAMETERS
qdef!MaxDateParam = DMax("Date1_Event", "TBL_Event", "ID=" & [Forms]![FRM_Main]![ID])
qdef!FormIDParam = [Forms]![FRM_Main]![ID]
' EXECUTE ACTION
qdef.Execute dbFailOnError
Set qdef = Nothing
Though above may look unusual and slightly more lines. Don't be intimidated and run for the easy 1-2 lines. Parameterization is a programming industry best practice not just in VBA but across all general purpose languages that run dynamic SQL queries using values from user input.
This is my first question on Stack Overflow. I have learned a lot from from this site but I have not been able to find the answer for a problem I am having.
I have a SQL query that works in SQL Server 2008 R2 management studio but it does not work when I query it using vba in EXCEL 2013. The query contains a common table expression and it is not returning any records to my recordset.
The SQL query is:
WITH cte AS
( SELECT *, ROW_NUMBER() OVER (PARTITION BY [partNumber]
ORDER BY [date] DESC) AS i FROM [myDB].[dbo].[PartOrders]
WHERE [partDescription] like '%motor%' )
SELECT * FROM cte WHERE i = 1
I have a reference for Microsoft ActiveX Data Objects 6.1 Library
The VBA code I am using is:
Dim conn as ADODB.Connection
Dim sql as String
Dim rst as ADODB.Recordset
Set conn = New ADODB.Connection
conn.ConnectionString = myConnectionString
conn.Open
sql = ";WITH cte AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY " & _
"[partNumber] ORDER BY [date] DESC) AS i " & _
"FROM [myDB].[dbo].[PartOrders]" & _
"WHERE [partDescription] like '%motor%' ) " & _
"SELECT * FROM cte WHERE i = 1 "
Set rst = New ADODB.Recordset
rst.Open sql, conn, adOpenStatic, adLockReadOnly, adCmdText
debug.print rst.recordcount
conn.Close
Set rst = Nothing
Set conn = Nothing
My code prints a "-1" in the Immediate window
I have added the preceding ";" to my query based on a recommendation of another questions response. It does not make a difference.
I have verified the following query string returns a recordset:
sql = "SELECT *, ROW_NUMBER() OVER (PARTITION BY " & _
"[partNumber] ORDER BY [date] DESC) AS i " & _
"FROM [myDB].[dbo].[partNumbers]" & _
"WHERE [partDescription] like '%motor%'"
I am using a CTE due to needing to collect entire records of a table but only of distinct part descriptions. I do not want to see that a motor was ordered 20 times. I would like to see that the motor was was ordered at least once along with the other fields associated with it. I am searching a table with 730,000 records where there are records for 10,000 motors but only 500 distinct types.
I am open to using a different query if it will net the same results but I am really curious as to why my current query is not yielding any records. I hope it is not due to an ADODB and VBA incompability.
Thank you for all of the help I have received from others questions and I appreciate any help you can provide me.
Parfait provided a solution for me in the comments to my original question. Changing my connection string provider to a driver did not work. It caused a Run-time error '-2147467259 (80004005)'
Instead of a CTE, I utilized a derived table in my query.
The SQL query that returns a recordcount for me in VBA is:
SELECT main.*
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY [partNumber]
ORDER BY [date] DESC) AS i FROM [myDB].[dbo].[PartOrders]
WHERE [partDescription] like '%motor%')
AS main WHERE main.i = 1
Thank You!
I had the same issue except I was using Driver as recommended by user7638417. When the recordset returned, the recordcount was -1, but, when I inserted the rows into the spreadsheet, they were all there (24). Used simplified query in example, actual query was more complex which lead me to the CTE method.
Dim sql As String
Dim dbConn As New ADODB.Connection
Dim dbRS As New ADODB.Recordset
Dim rows As Integer
sql = "WITH S1 AS ( SELECT Lot, CollectDt, Mark, Slot, Thick1, Thick2 From Table1 )"
sql = sql + " WHERE Lot = 'lotnumber' "
sql = sql + " SELECT * FROM S1 WHERE Thick2 <> "UNKNOWN" ORDER BY Slot "
dbConn.ConnectionString = "Driver={SQL Server};server=myserver;database=production;uid=guest;pwd=guest"
dbConn.Open
dbConn.CommandTimeout = 600
dbRS.Open sql, dbConn, adOpenStatic, adLockReadOnly
Dim totRow As Integer
totRow = dbRS.RecordCount + 2
' If (dbRS.RecordCount > 0) Then
Sheet1.Cells(2, 1).CopyFromRecordset dbRS
' End If
I had to comment out the check for data in order to get the data from the record set. The value in totRow came back as 1 instead of 26, the expected value which causes other things to fail later in the code.
SQL Server Version: 13.0.4001.0
Excel Version: 2016
I've started to use access recently. I am trying to insert a few rows into the database; however, I am stuck as it is throwing an error:
Too few parameters.
I have a table test with only one column in it named start_date I want to insert all the dates between two dates for example if I consider 1/7/2014 to 3/7/2014 I need dates as 1/7/2014,2/7/2014,3/7/2014 in my table, but I have problem inserting the code I used is as follows
Private Sub createRec_Click()
Dim StrSQL As String
Dim InDate As Date
Dim DatDiff As Integer
Dim db As database
InDate=Me.FromDateTxt
'here I have used a code to find out the difference between two dates that i've not written
For i = 1 To DatDiff
StrSQL = "INSERT INTO Test (Start_Date) VALUES ('" & InDate & "' );"
StrSQL = StrSQL & "SELECT 'Test'"
db.Execute StrSQL
db.close
i=i+1
next i
End Sub
My code throws an error in the line Db.Execuite StrSQL
as too few parameters.
since you mentioned you are quite new to access, i had to invite you to first remove the errors in the code (the incomplete for loop and the SQL statement). Otherwise, you surely need the for loop to insert dates in a certain range.
Now, please use the code below to insert the date values into your table. I have tested the code and it works. You can try it too. After that, add your for loop to suit your scenario
Dim StrSQL As String
Dim InDate As Date
Dim DatDiff As Integer
InDate = Me.FromDateTxt
StrSQL = "INSERT INTO Test (Start_Date) VALUES ('" & InDate & "' );"
DoCmd.SetWarnings False
DoCmd.RunSQL StrSQL
DoCmd.SetWarnings True
You can't run two SQL statements into one like you are doing.
You can't "execute" a select query.
db is an object and you haven't set it to anything: (e.g. set db = currentdb)
In VBA integer types can hold up to max of 32767 - I would be tempted to use Long.
You might want to be a bit more specific about the date you are inserting:
INSERT INTO Test (Start_Date) VALUES ('#" & format(InDate, "mm/dd/yyyy") & "#' );"
Remove this line of code: For i = 1 To DatDiff. A For loop must have the word NEXT
Also, remove this line of code: StrSQL = StrSQL & "SELECT 'Test'" because its making Access look at your final SQL statement like this:
INSERT INTO Test (Start_Date) VALUES ('" & InDate & "' );SELECT 'Test'
Notice the semicolon in the middle of the SQL statement (should always be at the end. its by the way not required. you can also omit it). also, there is no space between the semicolon and the key word SELECT
in summary:
remove those two lines of code above and your insert statement will work fine. You can the modify the code it later to suit your specific needs. And by the way, some times, you have to enclose dates in pounds signs like #
I want to put a where clause in my select statement based on the year and month of a timestamp field in my db
I have a month and a year dropdownlist which give me the following string 01/2012
The date format in my db is "2012-01-01 00:00:00" but when I select an individual date and put it in a message box it converts to "01/01/2012"
I've altered my select statement below to reflect the converted date. However Im still not given the correct details. Any ideas? Is there a particular format that I need to use when dealing with a timestamp field? Can I even use the "Right" function in a select statement?
Dim newRecordDate As String = val1 & "/" & ComboBox2.SelectedValue
Dim sql2 As String = "Select CatA, CatB, CatC, Cost, Currency, MarketingCode, Comment, RecordDate from vw_tblP_Usage_Details where puid = '" & puid & "' right(RecordDate, 7) = '" & newRecordDate & "'"
I say use parameters and the SqlParameter class to pass parameter values to sql server from .NET client instead of using concatenation and string formatting. It makes life easier.
Something Like This:
Dim myDate As Date = DateTime.Now
Dim sql As String = "Select * from SomeTable where MyDate = #some_param"
Using Command As New SqlClient.SqlCommand(sql)
Command.Parameters.AddWithValue("#some_param", myDate)
Using reader As SqlClient.SqlDataReader = Command.ExecuteReader()
'other code here
End Using
End Using