converting varchar to datetime in tsql - sql

I've studied all similar questions here, none of them works, what can be the problem? I want to convert varchar to date
convert(date,substring(replace(ent.Value,' ',''),1,10),103) < '20140101'
It returns error
Conversion failed when converting date and/or time from character string.
ent.Value here is something like '28/02/2014' Actually it works, when I enter something like
convert(date,substring('28/02/2013',1,10),103) < '20140101'
, but it doesn't work directly from the table
Thanks

To convert varchar to datetime : CONVERT(Datetime, '28/02/2014', 103) return the datetime like February, 28 2014 00:00:00+0000
To convert datetime to varchar : CONVERT(VARCHAR(10), datetime_field, 103) return something like '28/02/2014'
In both case you cannot compare it to this kind of text : '20140101'
You can change your text so both informations are ISO like : CONVERT(VARCHAR(10), CONVERT(Datetime, ent.Value, 103), 103) < '01/01/2014'
Or REPLACE(ent.Value,'/','') < '01012014'
But I don't think it's good to compare varchar => you can also do something like this : CONVERT(Datetime, '20140101', 112) :
CONVERT(Datetime, ent.Value, 103) < CONVERT(Datetime, '20140101', 112)
So your both field are in Datetime. ex : SQLFIDDLE DEMO

Break it down a bit: The first conversion works fine with the given example date string, but then you try and compare a DATE to a VARCHAR which requires an implicit conversion. That's never a good sign. However that actually works, so that aside the chances are that you have a date stored in text format that isn't a valid date. Since your examples use the UK date format, perhaps you have an American date in there (02/28/2013 - mm/dd/yyyy). If your default date format is UK style (i.e. you're not using American English settings) then it will fail as being out of range. You might also have entries which aren't dates at all with text in them like wibble or badly formatted dates like 02 Fub 2013.
Basically, you have a duff date somewhere in your table which you'll need to track down. Dates stored as text are a curse and to be avoided at all costs (although I appreciate that's not always possible when you inherit a legacy system - been there myself).
EDIT
To find your possible bad dates try this:
SELECT * FROM MyTable WHERE ISDATE(MyDateAsTextCol) <> 1

Related

How to subtract one month from a date using SQL Server

I have a date in format dd/mm/yyyy. I want to subtract one month from it.
I am using this code but the output is "09/10/2020" I don't know why my code does the subtraction of the year -2 also.
This is my request
SELECT
FORMAT(CONVERT (DATE, DATEADD(MONTH, -1, CONVERT(char(9), GETDATE()))), 'dd/MM/yyyy')
you need to change it to:
select format(CONVERT (date,DATEADD(MONTH, -1,GETDATE())), 'dd/MM/yyyy' )
but as Larnu stated. it seems like you need to change the column.
Your current code doesn't work as expected because:
SELECT CONVERT(char(9), GETDATE());
Returns this (at least in my language):
Nov 9 20
Which is, unfortunately, and again in my language, a valid date (but in {20}20, not {20}22).
Even in the right style (103), char(9) would yield 10/11/202 tomorrow, since 9 digits is only enough if either the day or month is a single digit.
Don't know why you are converting GETDATE() to a string. Just perform date math on it and then format it if you need to (using a specific style number, e.g. 103 for d/m/y):
SELECT CONVERT(char(10), DATEADD(MONTH, -1, GETDATE()), 103);
I really wouldn't use FORMAT() for such simple output, as the CLR overhead really isn't worth it. Ideally you leave it as a date/time type until presentation time - surely your presentation layer can present your date as d/m/y if that's really a wise idea.
And if you are storing or passing dates as strings (and worse, in regional formats like d/m/y) you really should consider fixing that.
First of all,
You should be storing your Date as a string for easier manipulation. If you don't want to change the column, you can always convert from Date to Varchar and then (re)convert it.
Example:
First, convert Date to varchar using the style code '112' ISO for formatting as yyyyMMdd:
DECLARE #date DATE = GETDATE();
DECLARE #dateConverted as VARCHAR (8) = (SELECT CONVERT(VARCHAR, #date, 112));
Then you just subtract the month using DATEADD():
DECLARE #previousMonth AS VARCHAR (8) = (SELECT FORMAT(DATEADD(month, -1, #dateConverted), 'yyyyMMdd'));
Finally, convert varchar do Date again:
DECLARE #previousMonthConverted AS DATE = (SELECT CONVERT(CHAR(10), CONVERT(date, #previousMonth), 120));

Convert and Operation Not working as expected. Ignoring Year value

I have the following code:
CONVERT(VARCHAR(20), TimeCard_Date, 101) <
CONVERT(VARCHAR(20), dateadd(dd,-3,getdate()), 101)
The Original TimeCard_Date value = 2018-06-01
The GetDate() return = 11/14/2017
Can anyone assist as to why it thinks the Timecard_Date value set for June 2018 is less than the GetDate() minus 3 days value?
When you convert, it converts to a varchar datatype. 06/01/2018 is less than 11/14/2017 as a varchar since it is an alphabetical (or by number?) comparison. If you compare by date, the comparison is by the date datatype, which is as you expect.
You can change your code to:
TimeCard_Date < dateadd(dd,-3,getdate())
You don't need to convert DATETIME to VARCHAR in order to compare dates. Just use:
TimeCard_Date < DATEADD(dd,-3,GETDATE())
On the other hand, if you ever have to convert them to do it, you have to standarize the format (yyyyMMdd). You can check the FORMAT function https://learn.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql

Convert to DATE T-SQL

I have a field with date in the format dd.mm.yyyy E.x. 29.05.2016. I want to SELECT it as DATE but I get an error when I try the following:
CAST([PublishedDate] AS DATE) AS PublishedOn
Conversion failed when converting date and/or time from character string.
Reading this I tried the following:
CONVERT(VARCHAR(10), [PublishedDate], 126) AS PublishedDate
But it doesn't change the format.
How do I SELECT to have it in YYYY-MM-DD format.
EDIT: I have 3 different date fields with all three having different formats: dd.mm.yyyy | yyyy-mm-dd | yyyy/mm/dd. I want to select all of them with the same format. Since I use this query to build reports, right now I have dates in different formats. Doing the following:
CONVERT(VARCHAR(10), [PublishedDate], 104) AS PublishedOn
CONVERT(VARCHAR(10), [ValidFromDate], 104) AS ValidFrom
Gives me the following
You should use the right format, in your case it would be:
CONVERT(date, [PublishedDate], 104) AS PublishedDate
Also, once it's in a date, datetime or other date datatype, it doesn't have a format at all.
edit: Once you have your values in a date datatype, of course you can recast to a varchar to get the visual representation of the date you need.
edit2: If you want a date datatype, you should convert to date: CONVERT(DATE, [your column], [your format]).
If you want a nvarchar datatype, you should convert to nvarchar: CONVERT(nvarchar(x), [your column], [your format]).
You have an nvarchar that you want to display in a certain format, so you should first convert to date, then back to varchar (I doubt you need unicode):
CONVERT(VARCHAR(10), CONVERT(date, [PublishedDate], 104), 126)
The 104 you have to change for columns that are currently in a different format.
The best solution by far, is to change the datatypes to date. That is a bit of work, but definitely worthwhile.
If you really want the string do like this:
CONVERT(char(10), CONVERT(date,[date], 104),126) AS PublishedDate
Convert the string to date, using the 104 format (dd.mm.yyyy), as it is your original format, then convert the date into string, using the 126 format (yyy-mm-dd)
If you have a newer version of SQL Server, you may try
SELECT COALESCE(TRY_CAST(adate AS DATE), TRY_convert(DATE, adate, 126), TRY_convert(DATE, adate, 104)), format
FROM (
VALUES ('26.04.2017', 'dkformat') ,
('01.01.2017', 'EU format'),
('12.12.12', 'unknown format')
) a(aDate, format)
But you are going down a dangerous path, when you are trying to guess what format your source is in. Been there, done that, had the t-shirt.
I still hate the 0.1% conversions that are wrong.
This solution will result in NULLs, so you can see where your conversion did not succeed.

Converting string 'yyyy-mm-dd' to date

I want to select from table where date column is equal to specific date which I sending as a string in format 'yyyy-mm-dd'. I need to convert that string and than to compare if I have that date in my table.
For now I am doing this:
select *
FROM table
where CONVERT(char(10), date_column,126) = convert(char(10), '2016-10-28', 126)
date_column is a date type in table and I need to get it from table in this format 'yyyy-mm-dd' and because that I use 126 format. I am just not sure with the other part where I converting string which is already in that format and do I need to convert it because I don't know is it good to use this:
CONVERT(varchar(10), date_column,126) = '2016-10-28'
You don't need to convert the column as well. In fact, you better not convert the column, because using functions on columns prevents sql server from using any indexes that might help the query plan on that column.
Also, you are converting a string to char(10) - better just convert it to date:
where date_column = convert(date, '2016-10-28', 126)
Also, if you are using a datetime data type and not date, you need to check that the datetime value is between the date you pass to the next date.
You can convert string to date as follows using the CONVERT() function by giving a specific format of the input parameter
declare #date date
set #date = CONVERT(date, '2016-10-28', 126)
select #date
You can find the possible format parameter values for SQL Convert date function here
You do not need to do that. yyyy-MM-dd is the default format.
Please note that you need to take into account the time as well, if there's a timestamp in date_column. In that case you should write something like this
... WHERE date_column >= '2016-10-28 00:00:00' AND date_column < '2016-10-29 00:00:00'
... WHERE date_column BETWEEN '2016-10-28 00:00:00' and '2016-10-29 00:00:00'
As I just learned that (other than I thought) BETWEEN actually includes the end timestamp and thus is not equivalent to the above >= ... < approach.
This should use indexes properly as well.

Compare DATETIME and DATE ignoring time portion

I have two tables where column [date] is type of DATETIME2(0).
I have to compare two records only by theirs Date parts (day+month+year), discarding Time parts (hours+minutes+seconds).
How can I do that?
Use the CAST to the new DATE data type in SQL Server 2008 to compare just the date portion:
IF CAST(DateField1 AS DATE) = CAST(DateField2 AS DATE)
A small drawback in Marc's answer is that both datefields have been typecast, meaning you'll be unable to leverage any indexes.
So, if there is a need to write a query that can benefit from an index on a date field, then the following (rather convoluted) approach is necessary.
The indexed datefield (call it DF1) must be untouched by any kind of function.
So you have to compare DF1 to the full range of datetime values for the day of DF2.
That is from the date-part of DF2, to the date-part of the day after DF2.
I.e. (DF1 >= CAST(DF2 AS DATE)) AND (DF1 < DATEADD(dd, 1, CAST(DF2 AS DATE)))
NOTE: It is very important that the comparison is >= (equality allowed) to the date of DF2, and (strictly) < the day after DF2. Also the BETWEEN operator doesn't work because it permits equality on both sides.
PS: Another means of extracting the date only (in older versions of SQL Server) is to use a trick of how the date is represented internally.
Cast the date as a float.
Truncate the fractional part
Cast the value back to a datetime
I.e. CAST(FLOOR(CAST(DF2 AS FLOAT)) AS DATETIME)
Though I upvoted the answer marked as correct. I wanted to touch on a few things for anyone stumbling upon this.
In general, if you're filtering specifically on Date values alone. Microsoft recommends using the language neutral format of ymd or y-m-d.
Note that the form '2007-02-12' is considered language-neutral only
for the data types DATE, DATETIME2, and DATETIMEOFFSET.
To do a date comparison using the aforementioned approach is simple. Consider the following, contrived example.
--112 is ISO format 'YYYYMMDD'
declare #filterDate char(8) = CONVERT(char(8), GETDATE(), 112)
select
*
from
Sales.Orders
where
CONVERT(char(8), OrderDate, 112) = #filterDate
In a perfect world, performing any manipulation to the filtered column should be avoided because this can prevent SQL Server from using indexes efficiently. That said, if the data you're storing is only ever concerned with the date and not time, consider storing as DATETIME with midnight as the time. Because:
When SQL Server converts the literal to the filtered column’s type, it
assumes midnight when a time part isn’t indicated. If you want such a
filter to return all rows from the specified date, you need to ensure
that you store all values with midnight as the time.
Thus, assuming you are only concerned with date, and store your data as such. The above query can be simplified to:
--112 is ISO format 'YYYYMMDD'
declare #filterDate char(8) = CONVERT(char(8), GETDATE(), 112)
select
*
from
Sales.Orders
where
OrderDate = #filterDate
You can try this one
CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000')
I test that for MS SQL 2014 by following code
select case when CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000') then 'ok'
else '' end
You may use DateDiff and compare by day.
DateDiff(dd,#date1,#date2) > 0
It means #date2 > #date1
For example :
select DateDiff(dd, '01/01/2021 10:20:00', '02/01/2021 10:20:00')
has the result : 1
For Compare two date like MM/DD/YYYY to MM/DD/YYYY .
Remember First thing column type of Field must be dateTime.
Example : columnName : payment_date dataType : DateTime .
after that you can easily compare it.
Query is :
select * from demo_date where date >= '3/1/2015' and date <= '3/31/2015'.
It very simple ......
It tested it.....