I have a column with HHMMSS in a table.
Similar to this out put:
SELECT convert(varchar, getdate(), 108)
I need to be able to make a view in MSSMS with only the HH from time and convert it as an int.
Example
Time
11:08:11,
12:08:12
Int
11
,12
I have tried several tricks from this page but could not find any work around
https://www.mssqltips.com/sqlservertip/1145/date-and-time-conversions-using-sql-server/
Why not just use DATEPART? There's no need to convert the value from a datetime to a varchar and then to an int.
SELECT DATEPART(HOUR, GETDATE());
Edit: on a different note, I strongly suggest you always ensure you declare your length, precision and scale when using a datatype. SELECT CONVERT(varchar, GETDATE(), 108) will return the whole value here, as (in this case) this it converts the value to a varchar(25), however, not declaring these parameters can/does leads to unexpected behaviour.
I've seen many questions where people have asked "Why isn't this working?" because their SP is declared as CREATE PROC MyProc #String varchar AS ..., or they have a variable declaration of DECLARE #MyVar nvarchar;, which in both cases means the length has a value of 1; and thus their values are truncated.
Edit for Irony: And no less than an hour later... Substring function not comparing the output; looks like I need to order a new crystal ball. Exactly why not declaring your Length, Precision or Scale is a bad idea.
One way could be this:
SELECT LEFT(convert(varchar, getdate(), 108),2)
You can use stuff() & do conversations :
select col, datepart(hh, cast(stuff(stuff(col, 3, 0, ':'), 6, 0, ':') as time(0)))
from table t;
This assumes col has varchar type time.
Related
I have a table with 1M rows and a CREATED_AT varchar column. The formatting of the date string in this column:
2021-10-13 05:03:42.638+00
2021-10-18 21:28:49.98+00
2021-12-08 02:09:03.17+00
I want to cast this string into a new datetime column (called CREATED_DT).
Attempts
select
cast([CREATED_AT] as datetime)
from
[mydb].[dbo].[mytable]
Error:
Conversion failed when converting date and/or time from character string
select
convert(datetime, [CREATED_AT])
from
[mydb].[dbo].[mytable]
Conversion failed when converting date and/or time from character string
select
try_convert(DateTime, [CREATED_AT])
from
[mydb].[dbo].[mytable]
Query executes, but returns all nulls.
select
try_convert(DateTime, [CREATED_AT], 108)
from
[mydb].[dbo].[mytable]
Query executes, but returns all nulls.
select
try_cast([CREATED_AT] as datetime)
from
[mydb].[dbo].[mytable]
Query executes, but returns all nulls.
Assuming you never have to care about the useless +00 at the end (either it's always +00 or you don't care if it's ever something else), and you're ok losing a tiny bit of precision, you can take the left 22 characters and try to convert the values with a safe style number (in your case, 120):
DECLARE #d table(CREATED_AT varchar(32));
INSERT #d(CREATED_AT) VALUES
('2021-10-13 05:03:42.638+00'),
('2021-10-18 21:28:49.98+00'),
('2021-12-08 02:09:03.17+00');
SELECT CREATED_AT,
as_datetime = TRY_CONVERT(datetime, LEFT(CREATED_AT, 22), 120)
FROM #d;
If you don't want to lose the precision (you can't keep .638 as datetime, anyway, for example), or if some value might have 1 or 0 decimal places, or some values might not contain the +xx at all, you can do something similar but use some string tricks to truncate the value where the + appears (and also handles if it doesn't):
SELECT CREATED_AT,
as_datetime2 = TRY_CONVERT(datetime2(3),
LEFT(CREATED_AT, COALESCE(NULLIF(CHARINDEX('+',
CREATED_AT), 0), 32)-1), 120)
FROM #d;
Example db<>fiddle
And to demonstrate why using the 120 style number is important here, see this db<>fiddle.
The style you are looking for is 127, but your issue is that you only include the hour for the time-zone, you also need minutes. So just add :00 to each value.
You can then convert to a regular datetime from there, by using SWITCHOFFSET
DECLARE #v varchar(30) = '2021-10-13 05:03:42.638+00';
SELECT TRY_CONVERT(datetimeoffset, #v + ':00', 127);
SELECT CONVERT(datetime, SWITCHOFFSET(TRY_CONVERT(datetimeoffset, #v + ':00', 127), 0));
db<>fiddle
I have a table where there are values like 20170730 and also 0 values are there which is INT type
I am trying to convert it to value like 30/07/2017, for which i am using the below code,
Select convert(NVARCHAR(10),convert(date,convert(NCHAR(8),datecolumn)),103) from table
But for the zero values i am getting the below error
Conversion failed when converting date and/or time from character string.
If i delete all the zero this working fine but problem having with zero.
My requirement is to convert when there a date value and if 0 are there then it should be zero only like below,
Result
30/07/2017
0
Can u pls help
As already pointed out in the comments, you can try to use a CASE expression
SELECT CASE
WHEN nmuloc = 0 THEN
'0'
ELSE
convert(varchar(10),
convert(date,
convert(varchar(8),
nmuloc),
112),
103)
END
FROM elbat;
or try_convert() and coalesce().
SELECT coalesce(convert(varchar(10),
try_convert(date,
convert(varchar(8),
nmuloc),
112),
103),
'0')
FROM elbat;
db<>fiddle
The latter one will also correct other "malformed" data like 123 for example. The former will also fail in such cases. You may want that or not.
But, as also already pointed out in the comments, your real problem is that you use an inappropriate data type. Change the column's datatype to some date/time data type to really fix this.
I have two tables that both have a date column. One is stored as nvarchar, and its formatted as '6012017'. The other is stored as a date, and appears as '06-01-2017'.
I need to be able to link up the tables by matching dates. I've tried casting and converting the nvarchar to a date, which doesn't work.
Thanks in advance!
This should convert your date column to a date accounting for leading '0':
CONVERT(DATE, STUFF(STUFF(RIGHT('0' + [DateColumn], 8), 5, 0, '-'), 3, 0, '-'))
You might consider making this into persisted computed column or scalar function if you do this often.
As noted in comments below, if you ever need to account for "mm-dd-yyyy" or "dd-mm-yyyy", you can use a third parameter to tell CONVERT how to interpret. For your example having "mddyyyy" as original input, this would need style "110" so it matches to the string "mm-dd-yyyy".
CONVERT(DATE, STUFF(STUFF(RIGHT('0' + [DateColumn], 8), 5, 0, '-'), 3, 0, '-'), 110)
For more styles: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql
First you can format the string-formatted datetime to valid DateTime using an aproach such as below:
DECLARE #i NVARCHAR(MAX) = '6012017'
set #i = right(REPLICATE('0',8)+#i,8)
declare #date datetime
Set #date = (select DATEFROMPARTS(SUBSTRING(#i,5,4),SUBSTRING(#i,3,2),SUBSTRING(#i,1,2)))
Select #date
Now, what you have inside #date is a valid DateTime value, which you can use it for your comparison purposes
Note: You can write the whole query inside one SELECT query as below. What is returned by SELECT is a valid DateTime value
SELECT DATEFROMPARTS(
SUBSTRING(RIGHT(REPLICATE('0',8)+'6012017',8),5,4),
SUBSTRING(RIGHT(REPLICATE('0',8)+'6012017',8),3,2),
SUBSTRING(RIGHT(REPLICATE('0',8)+'6012017',8),1,2))
Even for the 06-01-2017 you can follow the same approach as below:
Select DATEFROMPARTS(
SUBSTRING(REPLACE('06-01-2017','-','') ,5,4),
SUBSTRING(REPLACE('06-01-2017','-','') ,3,2),
SUBSTRING(REPLACE('06-01-2017','-','') ,1,2))
Finally if you execute the following query, you will notice that both dates are equal and the comparison procedure is done successfully!
Select DateDiff(Day,
DATEFROMPARTS(
SUBSTRING(RIGHT(REPLICATE('0',8)+'6012017',8),5,4),
SUBSTRING(RIGHT(REPLICATE('0',8)+'6012017',8),3,2),
SUBSTRING(RIGHT(REPLICATE('0',8)+'6012017',8),1,2)),
DATEFROMPARTS(
SUBSTRING(REPLACE('06-01-2017','-','') ,5,4),
SUBSTRING(REPLACE('06-01-2017','-','') ,3,2),
SUBSTRING(REPLACE('06-01-2017','-','') ,1,2)))
I'd argue this is easiest. It's shorter, has less nesting, it uses functions that don't require remembering any weird parameters, and it eliminates the worries about date formats and separators.
select cast(right(dt, 4) + left(right('0' + dt, 8), 4) as date);
The advantage in using the ISO 8601 format is that it is an
international standard with unambiguous specification. Also, this
format is not affected by the SET DATEFORMAT or SET LANGUAGE setting.
https://learn.microsoft.com/en-us/sql/t-sql/data-types/datetime-transact-sql
There are limitations on using only deterministic functions in some scenarios but I'm not sure whether this gets around that restriction.
I have a rather strange issue here. I have a date string, which I've created partly by myself to incorporate a variable. The problem is, that I'm setting another language settings. In this case, I have to also convert the string to fit the language settings format. I'm using this code:
cast(convert(varchar, cast(cast(getdate() as date) as varchar) + ' ' + RIGHT('0' + CAST(#HR as varchar), 2) + ':00:00.000', 120) as datetime)
I get the error "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.", which is normal if you assign wrong date format before casting.
The problem is, that when I try to convert the personally created date string, it doesn't change its format no matter what format code I set it in. That doesn't change even when I hardcode a number instead of my variable:
convert(varchar, cast(cast(getdate() as date) as varchar) + ' 0' + CAST(2 as varchar) + ':00:00.000', 101)
results in 2016-09-14 02:00:00.000
For example,
convert(varchar, dateadd(Hour, 2, getdate()), 101) as datetime
Results in 09/14/2016.
Even though I have a different language setting, isn't SQL server supposed to always recognize the date format in the standard format?
Please give me an advice so I can overcome this issue.
Thanks in advance!
PS: I managed to solve my issue by inserting converted datetime column in a variable before setting bulgarian language. I'm still very interested to know what causes the problem though.
Ok I may have a soution for the question: Why is the format differently handled in SQL-SERVER when converting.
CONVERT(data_type(length),expression,style)
The STYLEvalue only applies for date/time.
So it's because of the datatype that the output is different.
See following example:
SELECT convert(varchar, dateadd(Hour, 2, getdate()), 101) as datetime
You get the result:
09/14/2016
Here your are converting a datetime datatype into a varchar and the STYLE-value with 101 applies for CONVERT and the output is converted in that format.
Example 2 is the same but the inner most part is casted into a varchar before converting it:
SELECT convert(varchar, CAST(dateadd(Hour, 2, getdate()) AS varchar), 101) as datetime
The result you get is:
Sep 14 2016 4:09PM
So because we are trying to convert a varchar into a varchar the STYLE-value doesn't apply for the conversion.
That is also why the first query is handled diffrent then the other:
SELECT convert(varchar, cast(cast(getdate() as date) as varchar) + ' 0' + CAST(2 as varchar) + ':00:00.000', 101)
Here you cast into varchar cast(cast(getdate() as date) as varchar) before converting. So the STYLE-value is not applying because it's not from datatype date/time.
I hope it made it a bit clear. Let me know if this helped.
When you use convert to format the datetime, you can pass a style number to it.
Looky here or here for those numbers.
The query below converts custom created datetimes to the 126 (ISO8601) format.
declare #d int = 2;
SELECT
CONVERT(varchar,
CONVERT(datetime,
CONCAT(FORMAT(GETDATE(),'yyyy-MM-dd'),' ',#d,':0')
)
,126) AS MyDateStamp1,
CONVERT(varchar,
CONVERT(datetime,
CONVERT(varchar,GETDATE(),102)+' '+convert(varchar,#d)+':0'
)
,126) AS MyDateStamp2;
The FORMAT & CONCAT functions can be used in SQL Server 2012 and beyond.
But if you have an earlier version then CONVERT should work instead.
Additional tip:
If you're using the CONVERT solution above, note that
"convert(varchar, CAST(dateadd(Hour, 2, getdate()) AS varchar), 101)" calls for you to set datatype to varchar.
I just came across code
"Convert(date,ML.StartDate,101)"
and since style 101 is mm/dd/yyyy, and the output was yyyy-mm-dd, I knew something was wrong. By changing the code to
"Convert(varchar,ML.StartDate,101)"
the proper date style was displayed in the result set.
This is in MS SQL Server.
I have a varchar in the format yyyy-MM-dd-hh.mm.ss.nnnnnn
For example: 2010-09-17-20.52.31.870000
I want to convert this into a datetime... but ISDATE function in MSSQL says that is not a valid date and CONVERT won't work. Is there a way to use the convert function so that I can tell it what format the date is in?
I also want to check first that it is a valid date since the varchar input may contain nothing or it may contain an invalid date.
For example, invalid data of 2010-xx-r7-99.53esdfd.31.870000... I would skip that data and not even try to convert.
As far as I'm aware, SQL Server 2005 only supports milliseconds up to 3 digits, so you could replace the periods with colons, and grab the left and right portions (ignoring the hyphen between the day and hours) and come up with something like this:
DECLARE #myDate varchar(50)
SET #myDate = '2010-09-17-20.52.31.870000'
PRINT isdate(left(#myDate, 10) + ' ' +
replace(substring(#myDate, 12, 12), '.', ':')) -- Should print '1'
PRINT cast(left(#myDate, 10) + ' ' +
replace(substring(#myDate, 12, 12), '.', ':') as datetime)
... which will effectively give you 870 milliseconds
The ISO 8601 standard separates the date and time with the letter T. Maybe that's all it needs to convert successfully? Some conversion implementations accept a space there too. I've never seen a hyphen there.
You would have to change the punctuation a bit to make it work, and reduce the precision from microseconds to millisecond. This works:
convert(datetime, '2010-09-17 20:52:31.870', 121)
What you are getting in is a bit wonky, but this works (tested):
DECLARE #temp as varchar(50)
SET #temp = '2010-09-17-20.52.31.870'
SET #temp = replace(#temp,'.',':')
set #temp = stuff(#temp,11,1,'T')
set #temp = stuff(#temp,20,1,'.')
select #temp
select cast(#temp as datetime)
NB I cut off the extra 0s, you could do this with substring if there really are those extra ones.