How can one convert the string "01 December 2016" to a date type in SQL Server?
CONVERT(date, '01 December 2016', 106)
Expected date outcome "01 Dec 2016"
If 2012+ you can use Format()
Select Format(convert(date,'01 December 2016'),'dd MMM yyyy')
Returns
01 Dec 2016
It is very dangerous to work with culture specific date/time formats and it is even worse to work with language and culture specific formats...
If ever possible store date/time values in appropriate types!
In my (german) system a direct cast or convert would break due to "December", which is "Dezember" in Germany. Have a look at this:
SET LANGUAGE English; --try the same with "German"
DECLARE #d VARCHAR(100)='01 December 2016';
SELECT CONVERT(VARCHAR(11),CONVERT(DATE,#d,106),106);
The result
01 Dec 2016
One should never rely on implicit conversions: Call CONVERT with the third parameter in any case!
The third parameter 106 tells SQL Server the date's format (how to parse it). The first CONVERTSs target type is DATE. This - now properly represented! - date can be converted again to VARCHAR(11) with 106 as third parameter now specifying the output format.
For deeper insight in language specific date parts you can run this query:
SELECT * FROM sys.syslanguages;
btw: If you are using SQL Server 2012+ you should call FORMAT() as pointed out by John Cappelletti
Related
I have a SQL Server table that stores Time as follows (in a varchar column):
08 SEP 2015 09:15:16
08 SEP 2015 09:15:22
08 SEP 2015 09:15:22
08 SEP 2015 09:15:22
08 SEP 2015 09:15:26
08 SEP 2015 09:15:27
08 SEP 2015 09:15:31
I want to write a query that can give me all entries that are in a particular month and year. Like 'JAN 2016' and so on.
I am using SQL Server.
If, you are not able to change the type of dates that you have then you will need to cast them with format() function to format the date(MMM yyyy) available from 2012+
SELECT
FORMAT(CAST(<column> AS DATE), 'MMM yyyy') as dates
FROM table t
You could also use the datepart() function to filter the dates
WHERE
DATEPART(MONTH, dates) = 1 and DATEPART(year, dates) = 2015
In order to just the want to display the counts use count() function
SELECT COUNT(*)
FROM table
WHERE DATEPART(MONTH, dates) = 1 AND
DATEPART(year, dates) = 2015
As already mentioned in the comments, I would recommend to change this data type to a date/timestamp field in order to avoid risk of data inconsistency and/or having part of your application crashing when trying to convert string (that do not respect the format of a date) to a date object.
Now if and only if it is not feasible in short term, you have two ways to proceed:
1. data conversion:
The first one is to extract all the records from the table and convert them to date type before doing the comparison,
however if there is at least one varchar that is not a well formed date, your query will fail.
2. work with string:
Another way of doing is to query your DB directly using a varchar like described hereunder to avoid those conversion issues:
select * from table_A where date_column like '%JAN 2016%'
However query using like are kind of slow and should only be used as a temporary work-around, in long term adapt your data model to ease
your life and have a more stable/robust application.
Last but not least, try to run some queries to check if there are not already some wrong data (format or strings that are not dates) inserted in your DB. You might face already some data inconsistency issues.
Have researched a lot, both on this site, and others, but still don't have a valid solution. I have a column of varchar datatype, it contains DateTime data. I need to store only the Date portion in a Date type column. Tried different ways of Cast, Convert, and other functions, but still haven't been able to make it work.
Basically I want to convert this
Tue Apr 26 2016 13:54:53 GMT+0200 (CEST)
to
04/26/2016
Assuming your Day and Month part is always 3 characters long this can be done simply as this:
DECLARE #d VARCHAR(100)='Tue Apr 26 2016 13:54:53 GMT+0200 (CEST)';
SELECT CONVERT(DATE,SUBSTRING(#d,4,12),109);
If this was to easy one would have to find the blank(s) with CHARINDEX, but I don't think so...
The format code 109 means mon dd yyyy hh:mi:ss:mmmAM (or PM) Details here.
And be aware that formats containing language depending parts are directly sent by the devil to create never ending pain... This will not work on a server with a different language setting!
Declare #String varchar(max) = 'Tue Apr 26 2016 13:54:53 GMT+0200 (CEST)'
Select cast(Substring(#String,12,4)+Substring(#String,4,7) as date)
Returns
2016-04-26
Okay a few things here you have a field that looks to be psuedo ISO 8601 but is not the standard. The first question will be: "Where does this come from?" Typically you don't have the 'Tue' or 'GMT' or '(CEST)' in a standard and the offset from Greenwich Meantime is in the format (+/-)##:## NOT (+/-)####. SQL and many other formats can easily accept a standardized string in the ISO 8601 format. Good brief here: https://www.w3.org/TR/NOTE-datetime
That being said you can easily get what you want with a little know how:
DECLARE
#S VARCHAR(128) = 'Tue Apr 26 2016 13:54:53 GMT+0200 (CEST)'
, #Valid VARCHAR(128)
--Legitimate ISO 8601 string:
SELECT #Valid = RTRIM(LTRIM(REPLACE(STUFF(STUFF(#S, 1, 4, ''), LEN(#S)-12, 12, ':00'), 'GMT', '')))
SELECT #Valid
--Legitimate DateTimeOffset
SELECT CAST(#Valid AS DATETIMEOFFSET)
--Now that I have a legimiate DateTimeOffset I can downconvert easily
SELECT CAST(CAST(#Valid AS DATETIMEOFFSET) AS DATE)
--AND... Now that I have a legimate Date I can format it many different ways
SELECT CONVERT(VARCHAR, CAST(CAST(#Valid AS DATETIMEOFFSET) AS DATE), 101)
The real thing to realize here is there is magical conversion of DateTime using the convert function. But you may be wondering 'what if I want it to look different?'. Try this page:
http://www.sql-server-helper.com/tips/date-formats.aspx
I would be leery though of just finding the placement of were things appear to be coming from a string even though I can parse your example. If you are getting things not following a standard you should know why. The main reason being you may be able to get this to work for a specific instance but not be able to repeat this pattern over and over.
I have an Oracle SQL script that I'm converting to run in MS SQL Server. The script has the to_date function in it and uses the RR date format. Here's the function:
to_date('07-AUG-14','DD-MON-RR')
I'm going to use the MS SQL Server function CONVERT like this
CONVERT(DATETIME, '07-AUG-14', num)
where num is the code of the format I need.
What code should I use in MS SQL Server to get the same type of functionality as the Oracle RR format?
For a U.S. datetime conversion, you can use:
CONVERT(DATETIME, '07-AUG-14', 10)
-- ^^
For other cultures, style (the 3rd argument) will differ; but style needs to be a Without century (yy) value for your purpose.
The semantics of Oracle's RR date format apply to SQL Server's yy date styles too. CAST and CONVERT (Transact-SQL) (for SQL Server 2008) on MSDN explains...
By default, SQL Server interprets two-digit years based on a cutoff year of 2049. That is, the two-digit year 49 is interpreted as 2049 and the two-digit year 50 is interpreted as 1950.
...and lists the numeric values for the Without century (yy) date styles.
(For reference, another SO answer explains the equivalent semantics of Oracle's RR date format.)
You can more broadly confirm the default semantics of SQL Server's (U.S.) yy date style with the following queries...
SELECT CONVERT(DATETIME, '07-AUG-14', 10)
SELECT CONVERT(DATETIME, '07-AUG-49', 10)
SELECT CONVERT(DATETIME, '07-AUG-50', 10)
SELECT CONVERT(DATETIME, '07-AUG-51', 10)
..., which yield...
2014-08-07 00:00:00.000 -- This century assumed.
2049-08-07 00:00:00.000 -- This century assumed.
1950-08-07 00:00:00.000 -- Last century assumed.
1951-08-07 00:00:00.000 -- Last century assumed.
...with a default two-digit year cutoff configuration. (yy date styles for other cultures should behave similarly.)
Why is SQL Server (2005) misinterpreting this ISO 8601 format date? (YYYY-MM-DD)
DECLARE #FromDate DATETIME
SET #FromDate = '2013-01-05'
PRINT #FromDate
-- Prints: May 1 2013 12:00AM
The date in text format, is clearly the 5th of January but for some reason SQL Server is interpreting as the 1st of may. There is no date format in the world which is YYYY-DD-MM so why is this happening? I've been using this format for years and never had a problem before so I'm not sure what's different in this instance.
Even if I force it into ISO8601 using CONVERT, it still gets it wrong:
DECLARE #FromDate DATETIME
SET #FromDate = CONVERT(VARCHAR, '2013-01-05', 126)
PRINT #FromDate
-- Still prints: May 1 2013 12:00AM
EDIT: Oops - I'm using 'CONVERT(VARCHAR above where I really mean CONVERT(DATETIME), so that's why that wasn't taking any effect. Thanks #RBarryYoung
However if I run either of the two examples above on a different server (SQL 2012) they both correctly print 'Jan 5 2013 12:00AM'
What's happening here? I thought one of the main reasons to use ISO format with SQL Server was that it made the month and day unambiguous?
It only makes it unambiguous for the newer datatypes (date/datetime2)
For backward compatibility this still is dateformat dependent for datetime.
On SQL Server 2012
SET DATEFORMAT DMY
SELECT CAST('2013-01-05' AS DATETIME), /*May*/
CAST('2013-01-05' AS DATETIME2), /*Jan*/
CAST('20130105' AS DATETIME), /*Jan*/
CAST('20130105' AS DATETIME2) /*Jan*/
You can use yyyymmdd as an unambiguous format when dealing with those datatypes.
See The ultimate guide to the datetime datatypes (this is referred to as the unseparated format in that article)
In SQL Server 2008, how do I convert a string of type 'MMMM DD,YYYY' (i.e. June 01, 2013) to a regular datetime type (20130601)?
As far as I know, Convert() only works to convert dates into strings, not the other way around. I'm sure there's a standardized answer somewhere, but I can't find one for SQL Server. Should I write a custom procedure to parse the string?
While it's not recommended to store your date in string formats, you still could properly convert string to date. When you know exact format, avoid using cast and use convert - see possible formats here.
set language english
select convert(datetime, 'June 01, 2013', 107)
-----------------------
2013-06-01 00:00:00.000
Conversion from and to 107 format depends on your connection settings. If, for example, your connection language is not english, you could get an error
set language norwegian
select convert(datetime, 'June 01, 2013', 107)
-----------------------
Msg 241, Level 16, State 1, Line 2
Conversion failed when converting date and/or time from character string.