Date format in Access insert into sql statement - ms-access

Code below, but the date in the table is not showing correctly, my computer system date is set to yyyy,mm,dd and the Access table field is selected to short date. As seen in code below the date is showing fine when debugging and stepping through the program but at the end the date in the table is shown as 1905-12-30 (Which should be 2013-12-30) any suggestions please?
InsDate = Date
**InsDate** = Format(InsDate, "yyyy,mm,dd")
AppeQry = "INSERT INTO TStockMaster ( SupplierID, PartID, UnitsID, ConditionID, " & _
"QTY, WarehouseID, BinID, RowID, ColumnID, InsDate ) VALUES ( " & SupID & "," & PrtID & "," & UntID & "," & _
CondID & "," & Qt & "," & WarehID & "," & BnID & "," & RwID & "," & ColID & "," & **InsDate** & ");"

Use a parameter query instead of concatenating values as text into an INSERT statement.
Then, when you execute the statement, and supply the parameter value, you can give it the actual Date/Time value and not be bothered with text format and date type delimiters.
Here is a simplified example. Save this query as qryTStockMasterAppend.
INSERT INTO TStockMaster (InsDate) VALUES (pInsDate);
Then your VBA code can use that saved query, supply the parameter value and execute it.
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
Set qdf = db.QueryDefs("qryTStockMasterAppend")
qdf.Parameters("pInsDate") = Date()
qdf.Execute dbFailOnError

Related

Use date in Excel cell in BETWEEN clause in SQL query

(1) Table DB-Fiddle
CREATE TABLE logistics (
id int primary key,
Product VARCHAR(255),
insert_timestamp Date
);
INSERT INTO logistics
(id, product, insert_timestamp
)
VALUES
("1", "Product_A", "2020-02-24 18:15:48"),
("2", "Product_B", "2020-02-24 20:30:17"),
("3", "Product_C", "2020-02-24 23:54:58"),
("4", "Product_D", "2020-02-25 08:09:30"),
("5", "Product_E", "2020-02-25 10:17:15");
(2) VBA
Value in Cell B1 = 2020-02-24
Sub Get_Data()
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim dateVar As Date
Set conn = New ADODB.Connection
conn.ConnectionString = "DRIVER={MySQL ODBC 5.1 Driver}; SERVER=localhost; DATABASE=bi; UID=username; PWD=password; OPTION=3"
conn.Open
strSQL = " SELECT " & _
" cID " & _
" FROM logistics " & _
" WHERE DATE(insert_timestamp) BETWEEN """ & Format(Sheet1.Range("B1").Value, "YYYY-MM-DD") & "00:00:00" & """ " & _
" AND """ & Format(Sheet1.Range("B1").Value, "YYYY-MM-DD") & "23:59:59" & """ " & _
" GROUP BY 1 "
Set rs = New ADODB.Recordset
rs.Open strSQL, conn, adOpenStatic
Sheet1.Range("A1").CopyFromRecordset rs
rs.Close
conn.Close
End Sub
I want to run a query within the VBA that uses the date in Cell B1 within the BETWEEN statement in the WHERE clause.
When I run this query outside of the VBA it works perfectly:
SELECT
Product
FROM logistics
WHERE DATE(insert_timestamp) BETWEEN "2020-02-24 00:00:00" AND "2020-02-24 23:59:59";
Once, I run it in the VBA it does not give me an error but it also does not give me any result.
I assume the issue is caused by my combination of the sql and the VBA in the strSQL.
How do I have to change the VBA to make it work?
Instead of formatting values like dates or strings into the SQL command, it is much better to use ADODB.Parameter - in that case the driver will do all the work for you. You don't have to take care about quotes around a string, formatting a date so that the database understands it correctly (which is highly depending on database, regional settings and so on). Plus it is a protection against SQL injection. Plus, the query optimizer can do it's job much better because it gets the same SQL command every time and remembers the execution plan.
Drawback: code get's slightly more complicated because you have to involve a ADODB.command object.
In your SQL statement, you put a simple ? at the place where you want to have a parameter. You just have to take care that the numbers and the position of ? and parameters matches.
Dim Conn As New ADODB.Connection, cmd As New ADODB.Command, param As ADODB.Parameter, rs As ADODB.Recordset
Conn.Open "<your connection string>"
Set cmd.ActiveConnection = Conn
cmd.CommandText = "SELECT cID FROM logistics WHERE DATE(insert_timestamp) BETWEEN ? AND ? GROUP BY 1"
Set param = cmd.CreateParameter(, adDate, adParamInput, , Date)
cmd.Parameters.Append param
Set param = cmd.CreateParameter(, adDate, adParamInput, , Date + 1)
cmd.Parameters.Append param
Set rs = cmd.Execute
Debug.Print rs.Fields(0).Name, rs(0).Value
P.S. Was a little lazy for the date handling, if you have data exactly at midnight, you would get too much data.
you are missing a space between the date and the time...
Open your VBE and debug print the formula to see the result (maker sure you have the immediate window [view menu / Immediate window).
Sub test()
Debug.Print Format(Sheet1.Range("B1").Value, "YYYY-MM-DD") & "23:59:59"
End Sub
result
2020-03-1123:59:59
Just can add the space after the DD as follow
Format(Sheet1.Range("B1").Value, "YYYY-MM-DD ") & "23:59:59"
I know you've accepted an answer and it's a perfectly good one. I'm just leaving this here as an alternative method which you might find useful in other cases too:
Dim date_to_use As String
date_to_use = Format(Sheet1.Range("B1").Value, "YYYY-MM-DD")
strSQl = " SELECT " & _
" cID " & _
" FROM logistics " & _
" WHERE DATE(insert_timestamp) BETWEEN '[date to use] 00:00:00'" & _
" AND '[date to use] 23:59:59'" & _
" GROUP BY 1 "
strSQl = Replace(strSQl, "[date to use]", date_to_use)
Storing the contents of B1 in this way before using it also allows you to apply other changes to it - just in case you wanted to clean it up further or reduce the chances of SQL injection being used..

Selecting fields command gives error

I want to sort multiple fields in an access data base but being a newbie I took reference from MSDN program and first trying to sort on a single field. I'm getting error From syntax wrong on the following lines.
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM Banks_Trnx_2018-2019" _
& "ORDER BY SNO DESC;")
The full program as follows.
Option Compare Database
Sub OrderByX()
Dim dbs As Database, rst As Recordset
' Modify this line to include the path to Northwind
' on your computer.
Set dbs = OpenDatabase("E:\FY_2018-2019\Banks\Banks_Trnx_2018-2019.accdb")
' Select the last name and first name values from
' the Employees table, and sort them in descending
' order.
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM Banks_Trnx_2018-2019" _
& "ORDER BY SNO DESC;")
' Populate the Recordset.
rst.MoveLast
' Call EnumFields to print recordset contents.
' EnumFields rst, 12
dbs.Close
End Sub
I am clueless. Please help. As already mentioned I would like to sort on three fields (multiple fields) comprising of text and numerical fields which presently I can easily do by setting columns in proper order and selecting them together while sorting. Since it is a repetitive operation I am trying to develop VBA procedure for the same. Any pointer in the right direction shall be highly appreciated.
You should set your sql to a variable first - makes it a lot easier to troubleshoot - you'd be able to see you've left out some spaces between keywords and table
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018-2019]" _
& "ORDER BY SNO DESC;")
Should be (with added brackets for table as suggested by #skkakkar)
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018-2019] " _
& "ORDER BY SNO DESC;")
You have a - in your table name. I didn't even think that was allowed, either put brackets around your table name or change the table name.
"SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018-2019]" _
& "ORDER BY SNO DESC;"
or
"SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018_2019] " _
& "ORDER BY SNO DESC;"
and change table name.

Microsoft Access VBA INSERT SQL statement

I have created a database within Microsoft access and with it a form.
I have a button attached to the form and when it's clicked I want to insert a new record into the table customerHeader.
There are four fields within that table one being an autonumber. In my SQL statement, I don't include the orderNumber since it is an autofield.
When I try to click the button and the on click event is executed, I get an error saying that Microsoft Access cannot append the records in the append query.
Any ideas, I have looked everywhere and I have not been able to find the solution.
Private Sub addOrder_Click()
Dim mySql As String
Dim rowNum As Integer
Dim recCount As Long
Dim orderNumber As Long
Dim myBool As Boolean
Dim todayDate As Date
todayDate = CDate(Date)
myBool = False
MsgBox todayDate
rowNum = Form.CurrentRecord
rowNum = CInt(rowNum - 1)
'DoCmd.GoToRecord , , acNewRec
mySql = "INSERT INTO orderHeader (orderDate,custNumber,printed) VALUES (" & todayDate & "," & rowNum & "," & myBool & ")"
DoCmd.RunSQL mySql
Me!orderNum.Requery
You don't have to much around - just use the ISO sequence for the format of the string expression for the date value:
mySql = "INSERT INTO orderHeader (orderDate,custNumber,printed) VALUES (#" & Format(todayDate, "yyyy\/mm\/dd") & "#," & rowNum & "," & myBool & ")"
However, it it's today, simply use:
mySql = "INSERT INTO orderHeader (orderDate,custNumber,printed) VALUES (Date()," & rowNum & "," & myBool & ")"

Importing data from excel to mysql database using vba

I´m trying to import data into a MySQL Database, i have searched for many examples and solutions but it didn´t working and i have no idea why. Below is my vba code. I am getting runtime error 2147217900(80040e14) saying that you have an error in your sql syntax; chek the manual that corrsponds to your mysqlfor the right syntax to use near '='41282'
Sub Getdata()
Dim conn As New ADODB.Connection
Dim server_name As String
Dim database_name As String
Dim user_id As String
Dim password As String
Dim a As Long ' counter
Dim i As Long, j As Variant, k As Long
Dim sqlstr As String ' SQL to perform various actions
Dim table1 As String, table2 As String
Dim field1 As String, field2 As String
Dim field3 As String
Dim rs As ADODB.Recordset
sqlstr = "INSERT INTO" & table1 & "SET" _
& field1 & " = '" & i & "', " _
& field2 & " = '" & j & "', " _
& field3 & " = '" & k & "'"
conn.Execute sqlstr
Next a
End With
skipwrite:
End Sub
Simply, space out the table name and SET command in the concatenated string. Also, add tick marks before and after due to the reserved words used in column names (which by the way should be avoided as best practices):
sqlstr = "INSERT INTO " & table1 & " SET " _
& "`" & field1 & "` = '" & Format(i, "YYYY-MM-DD") & "', " _
& "`" & field2 & "` = '" & j & "', " _
& "`" & field3 & "` = '" & k & "';"
Also as mentioned by #Lelio, format the date to read properly into a MySQL Date column.
Date in Excel are stored as number of days between 1899-12-31 and the actual date. What you are trying to do is to store a number in a field that has a numeric format.
41282 is the number of days. So you should calculate something like:
'1899-12-31' + 'i days'
to get the date in mysql format (that by default is YYYY-MM-DD). I don't know the exact string manipulation command for VBA to get this but on the MYSQL side this should fix your error

VBA Access - Multiple Tables count by date

We'd like to count from an Access database that has multiple tables - about 50.
We need to count from 1 column in each table that is 'QCPASS' This is a check box - if a product passed the box was checked if failed then not. We need to count both for EACH table, also allowing the user to specify a date range from a date column that exists in every table.
I've tried this with a query but I am told the query is unable to select, count and do the date range. Any VBA help would be great.
Exporting to Excel would be great, but any results would be fine. Here is the query I created that counts in a column from each table passes and failures. I can't iterate with a query either, so VBA seems the way to go:
SELECT "Table1" , Count('qcpass') AS column
FROM 5000028
GROUP BY [5000028].qcpass
union
SELECT "Table2",count('qcpass')
FROM 5000029
Group By [5000029].qcpass;
You can traverse the full TableDefs collection in your database, and create a query using VBA.
A word of warning: The TableDefs collection has the Access database system tables, so you need to skip this. A way I suggest you is to check for a specific table name prefix (it is noted in the code below).
public sub createMyBigUnionQuery()
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourFinalQuery", strSQL
db.close
exit sub
Notice that you can define any valid query you want. Take this as a hint, and tweak it to fit your specific needs.
Hope this helps you
Adressing #HansUp comment, if you need to filter your data by date, you have two options:
Include the where condition on every select created by the procedure
Include the date field in your query and group by it, and create a second query to filter the data you need from the created query.
I would personally go with option 1, and here is a sample code:
public sub createMyBigUnionQueryWithDates(d0 as date, d1 as date)
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourOtherFinalQuery", strSQL
db.close
exit sub
The reason I use cDbl(d0) is because Access dates are sensitive to regional settings, and I've had a lot of headaches dealing with it. Access (and many other Microsoft products) store dates as floating-point numbers (the integer part is the date, and the decimal part is the time).
Another word of warning: If your dates don't include time, then the between condition will work. But if they do include time, then I recommend you change the where condition to this:
"where rowDate >= " & cDbl(d0) & " and rowDate < " & cDbl(d1 + 1)"