I need to insert a varchar in my table. The type in the table is a datetime so I need to convert it. I didn't think this would be to big of a problem however it keeps inserting 1900-01-01 00:00:00.000 instead of the date I want. When I do a select with my converted date it does show me the correct date.
I'll show you the code:
INSERT INTO Item (CategoryId, [Date], Content, CreatedOn)
SELECT
CategoryId, Convert(datetime, '28/11/2012', 103), Content, GetDate()
FROM
Item i
JOIN
Category c ON i.CategoryId = c.Id
JOIN
Division d ON d.Id = c.DivisionId
WHERE
Date = Convert(datetime, '31/03/2005', 103)
AND d.Id = '142aaddf-5b63-4d53-a331-8eba9b0556c4'
The where clause works perfectly and gives me the filtered items I need, all data is correctly inserted except for the converted date. The gives like I said 1900-...
If I just do the select so:
SELECT CategoryId, Convert(datetime, '28/11/2012', 103), Content, GetDate()
FROM Item i
JOIN Category c ON i.CategoryId = c.Id
JOIN Division d ON d.Id = c.DivisionId
WHERE Date = Convert(datetime, '31/03/2005', 103) AND d.Id = '142aaddf-5b63-4d53-a331-8eba9b0556c4'
I get the correct date being: 2012-11-28 00:00:00.000. I have tried to use a different conversion like:
Convert(datetime, '20121128')
But that just gives the same problem. Anyone that sees what I'm doing wrong?
Thx
If you must use a string-based date format, you should pick one that is safe and works in every SQL Server instance, regardless of date format, language and regional settings.
That format is known as ISO-8601 format and it's either
YYYYMMDD (note: **NO** dashes!)
or
YYYY-MM-DDTHH:MM:SSS
for a DATETIME column.
So instead of
Convert(datetime, '28/11/2012', 103)
you should use
CAST('20121128' AS DATETIME)
and then you should be fine.
If you're on SQL Server 2008 - you could also look into using DATE (instead of DATETIME) for cases when you only need the date (no time portion). That would be even easier than using DATETIME and having the time portion always be 00:00:00
Just wanted to throw out the fact that I found this SO Question (and many others like it) years later while trying to find the answer to my problem.
If you are troubleshooting this inside a stored procedure, the parameter of the stored procedure is where you need to modify. The programmer who created the code I'm troubleshooting had #ddt CHAR(10) and no modifications inside the stored procedure resolved the problem. I had to change the parameter to #ddt smalldatetime.
Related
I've got a table that currently has all columns stored as nvarchar(max), so I'm converting all the datatypes to be what they should be. I have a column of dates, however when I run this:
ALTER TABLE Leavers ALTER COLUMN [Actual_Termination_Date] date;
I get
"Conversion failed when converting date and/or time from character string".
This is relatively normal, so I did the following to investigate:
SELECT DISTINCT TOP 20 [Actual_Termination_Date]
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
which returned:
NULL
13/04/2017
14/04/2017
17/04/2017
19/04/2017
21/04/2017
23/04/2017
24/04/2017
26/04/2017
28/04/2017
29/03/2017
29/04/2017
30/04/2017
31/03/2017
42795
42797
42813
42817
42820
42825
The null and excel style date formats (e.g. 42795) are no problem, however it's the ones appearing as perfectly normal dates I'm having a problem with. I usually fix issues like this by using one of the following fixes:
SELECT cast([Actual_Termination_Date] - 2 as datetime)
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
or
SELECT cast(convert(nvarchar,[Actual_Termination_Date], 103) - 2 as datetime)
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
When these return back the dates as I would expext, I'd then do an UPDATE statement to change them in the table and then convert the column type. However I keep getting an error message telling me that various dates can't be converted such as:
Conversion failed when converting the nvarchar value '21/04/2017' to data type int.
Any thoughts? Thanks!
Probably because of your language setting. For '21/04/2017' to work, you'll need to be using the BRITISH language, or other language that uses dd/MM/yyyy. I suspect you are using ENGLISH which is actually American.
American's use MM/dd/yyyy meaning that '21/04/2017' would mean the 4th day of the 21st month in the year 2017; obviously that doesn't work.
The best method is to use an unambiguous format, regardless of language and data type. For SQL Server that's yyyyMMdd and yyyy-MM-ddThh:mm:ss.nnnnnnn (yyyy-MM-dd and yyyy-MM-dd hh:mm:ss.nnnnnnn are not unambiguous in SQL Server when using the older datetime and smalldatetime data types).
Otherwise you can use CONVERT with a style code:
SELECT CONVERT(date,'21/04/2017', 103)
The problem with your data, however, is that you have values that are in the format dd/MM/yyyy and integer values. The int (not varchar) value 42817 as a datetime in SQL Server is 2017-03-25. On the other hand, if this data came from Excel then the value is 2017-03-23. I am going to assume the data came from Excel, not SQL Server (because the ACE drivers have a habit of reading dates as numbers, because the thing they aren't is "ace").
You'll need to therefore convert the values to an unambiguous format first, so that'll be yyyyMMdd. As we have 2 different types of values, this is a little harder, but still possible:
UPDATE dbo.Leavers
SET Actual_Termination_Date = CONVERT(varchar(8), ISNULL(TRY_CONVERT(date, Actual_Termination_Date, 103), DATEADD(DAY, TRY_CONVERT(int, Actual_Termination_Date),'18991230')), 112);
Then you can alter your table:
ALTER TABLE dbo.Leavers ALTER COLUMN [Actual_Termination_Date] date;
DB<>Fiddle using Michał Turczyn's DML statement.
Put the column into a canonical format first, then convert:
update leavers
set Actual_Termination_Date = try_convert(date, [Actual_Termination_Date], 103);
ALTER TABLE Leavers ALTER COLUMN [Actual_Termination_Date] date;
The update will do an implicit conversion from the date to a string. The alter should be able to "undo" that implicit conversion.
Back up the table before you do this! You are likely to discover that some dates are not valid -- that is pretty much the rule when you store dates as strings although in a small minority of cases, all date strings are actually consistently formatted.
The actual date does not matter. The error happens when you try to subtract 2 from a string:
[Actual_Termination_Date] - 2
The clue comes from the error message:
Conversion failed when converting the nvarchar value '21/04/2017' to data type int.
To fix the problem, use DATEADD after the conversion:
SELECT DATEADD(days, -2, convert(datetime, [Actual_Termination_Date], 103))
You just have inconsistent date format within your column, which is terrible.
Having wrong datatype lead to it, that's why it is so important to have proper data types on columns.
Let's investigate it a little:
-- some test data
declare #tbl table (dt varchar(20));
insert into #tbl values
(NULL),
('13/04/2017'),
('14/04/2017'),
('17/04/2017'),
('19/04/2017'),
('21/04/2017'),
('23/04/2017'),
('24/04/2017'),
('26/04/2017'),
('28/04/2017'),
('29/03/2017'),
('29/04/2017'),
('30/04/2017'),
('31/03/2017'),
('42795'),
('42797'),
('42813'),
('42817'),
('42820'),
('42825');
-- here we handle one format
select convert(date, dt, 103) from #tbl
where len(dt) > 5
or dt is null
-- here we handle excel like format
select dateadd(day, cast(dt as int), '1900-01-01') from #tbl
where len(dt) = 5
So, as you can see you have to apply to different approaches for this task. CASE WHEN statement should fit here nicely, see below SELECT:
select case when len(dt) = 5 then
dateadd(day, cast(dt as int), '1900-01-01')
else convert(date, dt, 103) end
from #tbl
I have a main table called Cases that I am inserting data into. I have a alternative table where all of the raw data called rawTableData is stored and then sent to the main table.
I have a nvarchar column in my rawTableDatathat stores a datetime string in this format
2016-04-04-10.50.02.351232
I have a column in my Cases table that has a datatype of DATETIME.
I first tried to find the bad data in this method below
SELECT CONVERT(datetime, nvarcharDateColumn, 103)
FROM rawTableData
WHERE ISDATE(CONVERT(datetime, nvarcharDateColumn, 103)) != 1
And I get the error below
The conversion of nvarchar data type to a datetime data type resulted in an out-of-range value.
Then I tried a different approach hoping to find all of the out of range values
SELECT nvarcharDateColumn
FROM rawTableData
WHERE ISDATE(nvarcharDateColumn)
But that only returns all rows since its nvarchar.
Again, I kept going and tried a different approach
SELECT CONVERT(DATETIME, CASE WHEN ISDATE(nvarcharDateColumn) = 1 THEN nvarcharDateColumn END, 103)
FROM rawTableData
I am not sure what I am doing wrong here and any help would be appreciated.
I am using SQL Server 2012
You can use TRY_CONVERT:
SELECT nvarchardatecolumn, TRY_CONVERT(date, nvarchardatecolumn)
FROM rawTableData
And if you only want to return the invalid dates, use a derived table:
SELECT *
FROM (SELECT nvarchardatecolumn, TRY_CONVERT(date, nvarchardatecolumn) DateCheck
FROM rawTableData
) A
WHERE DateCheck IS NULL
I want to find records from my database which lie between any user input date range(say between 10/2/2008 to 26/9/2024). I tried using
SELECT NAME
,TYPE
,COMP_NAME
,BATCH_NO
,SHELF
,MFG_DATE
,EXP_DATE
,QTY
,VAT
,MRP
FROM STOCK_LOCAL
WHERE
convert(VARCHAR(20), EXP_DATE, 103)
BETWEEN convert(VARCHAR(20), #MEDICINEEXP_DATE, 103)
AND convert(VARCHAR(20), #MEDICINEEXPDATE, 103)
but with this query i need to enter perfect date range which is available in my database, it is not giving me data lying in between any date entered.
Thanks in advance
Since it is a poolr designed schema there isnt going to be any decent/Efficient solution for this.
In sql server if you are storing Date or Date & Time data. Use the Data or DATETIME datatypes for your columns.
In your case you are trying to compare a string with passed date. and even when you tried to convert the string (Date) into date datatype you didnt do it correctly.
My suggestion would be Add new columns to your table with Date datatype and update these columns with existing date/string values.
For now you can convert the Date(string) into date datatype using the following code.
DECLARE #MEDICINEEXP_DATE DATE = 'SomeValue1'
DECLARE #MEDICINEEXPDATE DATE = 'SomeValue1'
SELECT query....
FROM TableName
WHERE
CAST(
RIGHT(EXP_DATE, 4)
+SUBSTRING(EXP_DATE,CHARINDEX('/',EXP_DATE)+1,2)
+LEFT(EXP_DATE,2)
AS DATE) >= #MEDICINEEXP_DATE
AND CAST(
RIGHT(EXP_DATE, 4)
+SUBSTRING(EXP_DATE,CHARINDEX('/',EXP_DATE)+1,2)
+LEFT(EXP_DATE,2)
AS DATE) <= #MEDICINEEXPDATE
Note
This solution will get you the expected results but very inefficient method. It will not make use of any indexses on your EXP_DATE Column even if you have a very buffed up index on that column.
I have a bunch of dates in varchar like this:
20080107
20090101
20100405
...
How do I convert them to a date format like this:
2008-01-07
2009-01-01
2010-04-05
I've tried using this:
SELECT [FIRST_NAME]
,[MIDDLE_NAME]
,[LAST_NAME]
,cast([GRADUATION_DATE] as date)
FROM mydb
But get this message:
Msg 241, Level 16, State 1, Line 2Conversion failed when converting date and/or time from character string.
The error is happening because you (or whoever designed this table) have a bunch of dates in VARCHAR. Why are you (or whoever designed this table) storing dates as strings? Do you (or whoever designed this table) also store salary and prices and distances as strings?
To find the values that are causing issues (so you (or whoever designed this table) can fix them):
SELECT GRADUATION_DATE FROM mydb
WHERE ISDATE(GRADUATION_DATE) = 0;
Bet you have at least one row. Fix those values, and then FIX THE TABLE. Or ask whoever designed the table to FIX THE TABLE. Really nicely.
ALTER TABLE mydb ALTER COLUMN GRADUATION_DATE DATE;
Now you don't have to worry about the formatting - you can always format as YYYYMMDD or YYYY-MM-DD on the client, or using CONVERT in SQL. When you have a valid date as a string literal, you can use:
SELECT CONVERT(CHAR(10), CONVERT(datetime, '20120101'), 120);
...but this is better done on the client (if at all).
There's a popular term - garbage in, garbage out. You're never going to be able to convert to a date (never mind convert to a string in a specific format) if your data type choice (or the data type choice of whoever designed the table) inherently allows garbage into your table. Please fix it. Or ask whoever designed the table (again, really nicely) to fix it.
Use SELECT CONVERT(date, '20140327')
In your case,
SELECT [FIRST_NAME],
[MIDDLE_NAME],
[LAST_NAME],
CONVERT(date, [GRADUATION_DATE])
FROM mydb
In your case it should be:
Select convert(datetime,convert(varchar(10),GRADUATION_DATE,120)) as
'GRADUATION_DATE' from mydb
I was also facing the same issue where I was receiving the Transaction_Date as YYYYMMDD in bigint format. So I converted it into Datetime format using below query and saved it in new column with datetime format. I hope this will help you as well.
SELECT
convert( Datetime, STUFF(STUFF(Transaction_Date, 5, 0, '-'), 8, 0, '-'), 120) As [Transaction_Date_New]
FROM mydb
Just to add more info about all solution above:
SELECT [FIRST_NAME],
[MIDDLE_NAME],
[LAST_NAME],
CONVERT(date, [GRADUATION_DATE])
FROM mydb
Assuming you don't have a WHERE clause, it is ok, the Convert will try to return all dates even if it is not a valid date like '00000000' (it was in my case).
But, if you need a WHERE clause, so you can see a message like this:
So I tested a mix of some approaches mentioned above like:
DECLARE #DateStart datetime = '2021-02-18'
DECLARE #DateEnd datetime = '2021-02-19'
SELECT [FIRST_NAME],
[MIDDLE_NAME],
[LAST_NAME],
CONVERT(date, [GRADUATION_DATE])
FROM mydb
WHERE
--THIS LINE SHOULD BE ENOUGTH TO AVOID WRONG DATES, BUT IT IS NOT
ISDATE([GRADUATION_DATE]) = 1 AND
CONVERT(char(10), [GRADUATION_DATE], 120) BETWEEN #DateStart and #DateEnd
And Finally I used this way with success:
DECLARE #DateStart datetime = '2021-02-18'
DECLARE #DateEnd datetime = '2021-02-19'
SELECT [FIRST_NAME],
[MIDDLE_NAME],
[LAST_NAME],
CONVERT(date, [GRADUATION_DATE])
FROM mydb
WHERE
CONVERT(char(10),
-- I ADDED THIS LINE TO IGNORE WRONG DATES
CASE WHEN ISDATE([GRADUATION_DATE]) = 1 THEN [GRADUATION_DATE] ELSE '1900-01-01' END, 120)
BETWEEN #DateStart and #DateEnd
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.....