vb.net date format from textbox > MS SQL query - vb.net

I have a date column in a DB tabel that I want to query using a date taken from textbox.text. the user selects a date from the calendar in the format dd/MM/yyyy. I want to use that date to put into a query. How do i format the date to be able to query the database?
Dim datefrom As String =txtDateFrom.Text
Dim dateto As String =txtDateTo.Text
The query will look like this:
WHERE (tblClient.ClientID = " & ClientID & ") AND (tblBackupArchive.BackupDate BETWEEN '" + datefrom + "' AND '" + dateto + "')"
I'm using MS SQL Server btw. Any help most appreciated.
Jonesy

NEVER USE STRING CONCATENATION LIKE THAT TO BUILD YOUR QUERIES!!!
And yes, I did mean to yell, because date formatting is the least of your problems. Imagine what would happen in your current code if something entered the following into one of your date textboxes:
';DROP TABLE tblClient;--
Instead, use a parameterized query. That will fix your date issues and protect against sql injection attacks. Here's an example:
Dim sql As String = " .... WHERE tblClient.ClientID= #ClientID AND tblBackupArchive.BackupDate >= #DateFrom AND tblBackupArchive.Backupdate < #DateTo"
Using cn As New SqlConnection("your connection string here"), _
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("#ClientID", SqlDbType.Int).Value = ClientID
cmd.Parameters.Add("#DateFrom", SqlDbType.DateTime).Value = DateTime.Parse(txtDateFrom.Text)
cmd.Parameters.Add("#DateTo", SqlDbType.DateTime).Value = DateTime.Parse(txtDateTo.Text).AddDays(1)
cn.Open()
cmd.Execute___()
End Using
You can think of it now as if you had run an sql statement more like this:
DECLARE #ClientID Int
DECLARE #DateFrom DateTime
DECLARE #DateTo DateTime
Set #ClientID = ImaginaryFunctionToGetQueryData('ClientID')
Set #DateFrom = ImaginaryFunctionToGetQueryData('DateFrom')
Set #DateTo = ImaginaryFunctionToGetQueryData('DateTo')
SELECT ...
FROM ...
WHERE tblClient.ClientID= #ClientID
AND tblBackupArchive.BackupDate >= #DateFrom
AND tblBackupArchive.Backupdate < #DateTo
The "ImaginaryFunction" in that code is accomplished using the sp_executesql stored procedure, but the point is that the query string as seen by sql server will never substitute data directly into the query string. Code is code, data is data, and never the 'twain shall meet.

Just as an addition to Joel's answer....
I'd avoid using any strings in the equation at all.
IE; Don't use textboxes to store the dates, use proper calendar or datetimepickers.
This way, you won't have to do this;
cmd.Parameters.Add("#DateFrom", SqlDbType.DateTime).Value = DateTime.Parse(txtDateFrom.Text)
as Joel suggests, but instead you can just do;
cmd.Parameters.Add("#DateFrom", SqlDbType.DateTime).Value = dtDateFrom.value
This way your not reliant on the DateTime.parse actually picking the correct format from your string. And you'll only be using date types.

Related

Date and Time Formatting in VB.net and SQL Server

I have a table in which data is been logged in 'yy/MM/dd HH:mm:ss' format and my regional setting is '2016-04-02 14:25:15' type. I want to get details in a following query but it is not populating any results
The query I used is
select
Date_time, alarm_id, alarm_message
from
table01
where
Date_time between '" & DateTimePicker5.Value & "' and '" & DateTimePicker6.Value & "'
I also tried using one function which I had written is
Private Function FormatDate(ByVal dat As String) As String
Dim FTDate As Date
FTDate = FormatDateTime(Convert.ToDateTime(dat), DateFormat.ShortDate)
FormatDate = Format(FTDate, "yy/MM/dd HH:mm:ss")
End Function
And used the same again in query as
select
Date_time, alarm_id, alarm_message
from
table01
where
Date_time between '" & formatdate(DateTimePicker5.Value) & "' and '" & formatdate(DateTimePicker6.Value) & "'
Please suggest appropriate answer make sure that I don't want to change my regional setting and on form load event. I've written the following code
DateTimePicker5.Format = DateTimePickerFormat.Custom
DateTimePicker5.CustomFormat = "yy/MM/dd HH:mm:ss"
DateTimePicker6.Format = DateTimePickerFormat.Custom
DateTimePicker6.CustomFormat = "yy/MM/dd HH:mm:ss"
The Table Is In Below Mentioned Format
**Datetime V1 P1**
16/08/29 19:12:24 10 STB-1
16/08/29 19:12:19 20 STB-1
16/08/29 19:12:18 30 STB-1
16/08/29 19:09:50 40 STB-1
Never ever ever EVER use string concatenation to put values into a query like that! It's practically begging to wake up one morning and find out your site was hacked six months ago.
The first thing you need to do is fix the schema, so that your date values are actually stored as DateTime columns. There are so many reasons for this, I can't even begin to describe them all. Just do it!
Once that's done, you build the query like this:
Const SQL As String = _
"SELECT Date_time, alarm_id, alarm_message
FROM table01
WHERE Date_time between #StartTime AND #EndTime"
Hey, look: it's a constant. Now that's not strictly necessary; I usually just use a normal Dim'd String value. However, I wanted to prove a point here: your SQL statement is set to use specific place holders that will never at any point have data in them. The values you provide for those #StartTime and #EndTime values will be completely separated and quarantined from your SQL command, such that no possibility for injection ever exists.
Once you have the SQL command string, you can use it like this (repeating the string definition so everything is in one place):
Const SQL As String = _
"SELECT Date_time, alarm_id, alarm_message
FROM table01
WHERE Date_time between #StartTime AND #EndTime"
Using cn As New SqlConnection("connection string here"), _
cmd As New SqlCommand(SQL, cn)
cmd.Parameters.Add("#StartTime", SqlDbType.DateTime).Value = DateTimePicker5.Value
cmd.Parameters.Add("#EndTime", SqlDbType.DateTime).Value = DateTimePicker6.Value
cn.Open()
Using rdr As SqlDataReader = cmd.ExecuteReader()
While rdr.Read()
' ...
End While
End Using
End Using
Or if you're filling a DataTable:
Dim result As New DataTable()
Const SQL As String = _
"SELECT Date_time, alarm_id, alarm_message
FROM table01
WHERE Date_time between #StartTime AND #EndTime"
Using cn As New SqlConnection("connection string here"), _
cmd As New SqlCommand(SQL, cn), _
ad As New SqlDataAdapter(cmd)
cmd.Parameters.Add("#StartTime", SqlDbType.DateTime).Value = DateTimePicker5.Value
cmd.Parameters.Add("#EndTime", SqlDbType.DateTime).Value = DateTimePicker6.Value
ad.Fill(result)
End Using
Note that using this method, you never have to worry about your DateTime format. ADO.Net figures it out for you. It knows about .Net DateTime objects, and it knows about Sql Server DateTime columns, and it handles conversions between the two types naturally.
This is some what a tricky solution.
Since year kept as 'yy' in the backend,following are the assumptions.
if the year part of the database field is between 00 to 16 ,need to consider this as 2000 to 2016. for the remaining values script will consider year as 1917 to 1999 .
Can you try with the below script.
SELECT Date_time, alarm_id, alarm_message
FROM table01
WHERE
CASE WHEN LEFT(Date_time,2) between 00 and RIGHT(year(getdate()),2) THEN CONVERT(DATETIME,'20'+Date_time)
ELSE CONVERT(DATETIME,'19'+Date_time) END between '" & DateTimePicker5.Value & "' and '" & DateTimePicker6.Value & "'
You can use Convert function.
select
Date_time, alarm_id, alarm_message
from
table01
where
Convert(Datetime,Date_time) between Convert(Datetime,'" & DateTimePicker5.Value & "') and Convert(Datetime,'" & DateTimePicker6.Value & "')
Since:
Console.WriteLine(#1/31/2016 10:23:22 AM#.ToString("yy/MM/dd HH:mm:ss"))
returns 16/01/31 10:23:22
I guess that:
select
Date_time, alarm_id, alarm_message
from
table01
where
(Date_time >= '" & DateTimePicker5.Value.ToString("yy/MM/dd HH:mm:ss") & "' )
and (Date_time < '" & DateTimePicker6.Value.ToString("yy/MM/dd HH:mm:ss") & "')
will do the trick.
Notice that I've changed the between with simple compare conditions
Run this in SQL Server and check the results:
create table #dateTest (
testDate datetime
)
insert into #dateTest values ('2016-03-01')
select * from #dateTest
declare #fromDate datetime
set #fromDate = '2016-01-01'
declare #toDate datetime
set #toDate = '2016-03-01'
select
testDate
from
#dateTest
where
( testDate between #fromDate and #toDate )
-- 2016-03-01 00:00:00.000
select
testDate
from
#dateTest
where
( testDate <= #fromDate )
and ( testDate < #toDate )
-- No rows selected
drop table #dateTest

VB.NET Access Datetime Querying Issue

I have a bunch of records in an Access db table with a datetime fields
e.g of records (2/2/2015 3:34:21 PM,2/2/2015 8:29:13 AM )
Problem is I need to run a query where I need all records for displayed to be ones that occurred on the same day regardless of the time. How to best structure this query?
I used 'Select * from table where thetime = 2/2/2015' and there was no result returned. I switched the date format to start with the year, no luck.
Any tips as to sql query syntax for Access will be appreciated. Thanks.
Date/Time values in Access always have both a date and time component, so a date literal like 2015-02-02 is equivalent to 2015-02-02 00:00:00. If you want all rows for that date, regardless of the time, you need to use a WHERE clause like
... WHERE thetime >= {that date} AND thetime < {the following day}
The proper way to do that in VB.NET is to use a parameterized query like this:
Using cmd As New OleDbCommand()
cmd.Connection = con ' an open OleDbConnection
cmd.CommandText =
"SELECT * FROM thetable " &
"WHERE thetime >= ? AND thetime < ?"
Dim targetDate As New DateTime(2015, 2, 2) ' example data
cmd.Parameters.Add("?", OleDbType.DBTimeStamp).Value = targetDate
cmd.Parameters.Add("?", OleDbType.DBTimeStamp).Value = targetDate.AddDays(1)
Using rdr As OleDbDataReader = cmd.ExecuteReader
Do While rdr.Read()
Console.WriteLine(rdr("thetime"))
Loop
End Using
End Using

Populate Date Column in Access with dates from 1980-01-01 to today with sql query

I have an Access Table which is named dates and has one single column named Date ( formatted as date ). I would need to have the dates from 1980-01-01 up until today incremented by 1 day at a time in the column. 1980-01-01 would be at the first row.
How can this be done with a sql query?
You could add those dates with Access SQL if you have a suitable table of numbers.
INSERT INTO dates ([Date])
SELECT CDate(n.the_number)
FROM tblNumbers AS n
WHERE n.the_number BETWEEN 29221 AND 42037;
Or start from 1 in tblNumbers and add an offset ...
INSERT INTO dates ([Date])
SELECT CDate(n.the_number + 29220)
FROM tblNumbers AS n
WHERE n.the_number BETWEEN 1 AND 12817;
But if you don't have a suitable numbers table, you would need to create one and populate it. And that is similar to the problem you started with, only loading plain numbers instead of dates.
The original task is simple enough that I would use a throwaway VBA procedure instead of Access SQL. This one took less than 2 seconds to load my dates table with the required 12,817 date values:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim dte As Date
Set db = CurrentDb
Set rs = db.OpenRecordset("dates", dbOpenTable, dbAppendOnly)
With rs
For dte = #1/1/1980# To Date
.AddNew
![Date].Value = dte
.Update
Next
.Close
End With
First, rename your column to something else then Date, as it is a reserved word and it would cause you much trouble. In my example I named the column DateField.
I assume when you said sql query, you meant access sql, in which case it cannot be done, as access sql doesn't support cycles.
However, you can do it easily by VBA, please see below:
Sub Main()
Dim myDate As Date
Dim myDateString As String
Dim strSQL As String
myDate = #1/1/1980#
Do While myDate < Now
myDateString = Format(myDate, "yyyy-mm-dd")
strSQL = "INSERT INTO DateTable (DateField) VALUES(#" & myDate & "#)"
CurrentDb.Execute strSQL
myDate = myDate + 1
Loop
End Sub

Error trying to execute sql statement between two dates

The SQL:
dim sql
sSql = "SELECT * FROM [dbo].[table] WHERE [sent] = 1 and datesent between '" & dStartDate & "' and '" & dFinishDate & "'"
response.write(sSql)
set oRs = oConn.execute(sSql)
When i execute this sql in sql server 2008 it works fine.
However, when i execute it within my application i get error:
Microsoft OLE DB Provider for SQL Server error '80040e07'
The conversion of a char data type to a datetime data type resulted
in an out-of-range datetime value.
Is there something different i have to do in the application? thanks
Have you tried using ISO format dates?
SELECT * FROM [dbo].[Table]
WHERE [sent] = 1 and datesent between '20120101' and '20120127'
(Strictly speaking an ISO 8601 date for sql server is yyyy-mm-ddThh:mm:ss[.mmm])
Side Note: always use ISO format dates when you output to text (or have literals); that way they can be read unambiguously on all systems).
SQL Server ISO 8601 Format Dates
http://msdn.microsoft.com/en-us/library/ms190977(v=sql.90).aspx
SELECT *
FROM [dbo].[Table]
WHERE
[sent] = 1
and datesent between CONVERT(datetime, '01/01/2012', 101) and CONVERT(datetime, '01/27/2012', 101)
OR
Your column datesent is not DATETIME datatype
Check your datetime setting.
set dateformat mdy
select CAST('01/27/2012' as datetime)
set dateformat dmy
select CAST('01/27/2012' as datetime) --> Exception
You can display the current setting with:
DBCC USEROPTIONS
You should always use the ISO-formats 'YYYYMMDD' for your dates, as this will always be parsed correctly by SQL Server, regardless of localization setting.

Convert DateTime to Hex equivalent in VB.NET

How do I achieve the same in VB.NET which is so easily done in SQL Server.
SELECT CAST(GETDATE() AS VARBINARY(8)) --GIVES THE CURRENT TIME IN HEX
Now my question is how can I create the same string in VB.NET so that I can compare in SQL Server as such -
SELECT CASE WHEN GETDATE()=CAST(0X00009F5E00D8DF7C AS DATETIME) THEN 'TRUE' ELSE 'FALSE' END -- 0X00009F5E00D8DF7C WILL BE THE VALUE I GET IN VB.NET WHEN I CONVERT IT DATE.NOW() TO HEX
This answer simply addresses conversion of .NET DateTimes to a binary format that is equivalent to SQL Server's datetime datatype, so I believe it is different enough that it warrants a separate answer (I checked here and here to be sure it was ok).
As #Martin Smith pointed out, the binary format of datetime is not simply a number of ticks since a specific point in time.
datetime is stored as 8 bytes, the first 4 bytes being the number of days since 01-01-1900 and the the second 4 bytes being the number of "ticks" since midnight of that day, where a tick is 10/3 milliseconds.
In order to convert a .NET DateTime to an equivalent binary representation, we need to determine the number of days since '01-01-1900', convert that to hex, and then the number of ticks since midnight, which is slightly complicated since a .NET tick is 100ns.
For example:
DateTime dt = DateTime.Now;
DateTime zero = new DateTime(1900, 1, 1);
TimeSpan ts = dt - zero;
TimeSpan ms = ts.Subtract(new TimeSpan(ts.Days, 0, 0, 0));
string hex = "0x" + ts.Days.ToString("X8") + ((int)(ms.TotalMilliseconds/3.33333333)).ToString("X8");
When I ran this code, dt was 9/14/2011 23:19:03.366, and it set hex to 0x00009F5E01804321, which converted to 2011-09-14 23:19:03.363 in SQL Server.
I believe you will always have a problem getting the exact date because of rounding, but if you can use a query where the datetime doesn't have to match exactly, down to the millisecond, this could be close enough.
Edit
In my comment under the first answer I posted, I asked about SQL Server 2008, because the datetime2 data type does store time with an accuracy of 100ns (at least, it does with the default precision), which matches up nicely with .NET. If you are interested in how that is stored at the binary level in SQL Server, see my answer to an older question.
I had to convert some dates in dbscript from SQL Server's hex format string to standard datetime string (for use with TSQL to MySQL script translation). I used some codes I looked up in here and came up with:
static string HexDateTimeToDateTimeString(string dateTimeHexString)
{
string datePartHexString = dateTimeHexString.Substring(0, 8);
int datePartInt = Convert.ToInt32(datePartHexString, 16);
DateTime dateTimeFinal = (new DateTime(1900, 1, 1)).AddDays(datePartInt);
string timePartHexString = dateTimeHexString.Substring(8, 8);
int timePartInt = Convert.ToInt32(timePartHexString, 16);
double timePart = timePartInt * 10 / 3;
dateTimeFinal = dateTimeFinal.AddMilliseconds(timePart);
return dateTimeFinal.ToString();
}
static string HexDateToDateString(string dateHexString)
{
int days = byte.Parse(dateHexString.Substring(0, 2), NumberStyles.HexNumber)
| byte.Parse(dateHexString.Substring(2, 2), NumberStyles.HexNumber) << 8
| byte.Parse(dateHexString.Substring(4, 2), NumberStyles.HexNumber) << 16;
DateTime dateFinal = new DateTime(1, 1, 1).AddDays(days);
return dateFinal.Date.ToString();
}
Maybe not optimized, but shows the idea.
My first inclination is that the clients should not be constructing sql statements to be executed by your data access layer, but assuming you must get something working soon, you might consider using a parameterized query instead.
If you are making method calls from the client(s) to your other application tiers, you can construct a SqlCommand on the client and pass that to the next tier where it would be executed.
VB.NET is not the language I normally use, so please forgive any syntax errors.
On the client:
Dim dateValue As Date = DateTime.Now
Dim queryText As String = "SELECT CASE WHEN GETDATE() = #Date THEN 'True' ELSE 'False' END"
Dim command As SqlCommand = New SqlCommand(queryText)
command.Parameters.AddWithValue("#Date", dateValue)
If you must send a string, you could convert the DateTime to a string on the client and then convert back to a DateTime on the data access tier, using a common format.
On the client:
Dim queryText As String = "SELECT CASE WHEN GETDATE() = #Date THEN 'True' ELSE 'False' END"
Dim dateValue As Date = DateTime.Now
Dim dateString = DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff", DateTimeFormatInfo.InvariantInfo)
Then send both queryText and dateString to the next tier in your application, where it would convert back to Date and again use a parameterized query:
Dim dateValue As Date
Date.TryParseExact(dateString, "M/d/yyyy H:mm:ss.fff", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, dateValue)
Dim command As SqlCommand = New SqlCommand(queryText)
command.Parameters.AddWithValue("#Date", dateValue)
If your clients are in different time zones, you should (as #Martin Smith mentioned) consider using UTC time.
In .NET
Dim dateValue = DateTime.UtcNow
and also in your query, using GETUTCDATE():
Dim queryText As String = "SELECT CASE WHEN GETUTCDATE() = #Date THEN 'True' ELSE 'False' END"