SQL Server : Convert from VARCHAR to DATETIME - tsql

Current Date Format: 12-18-2018-03:14:48
I want to convert to: 2018-12-18 03:14
Currently using SQL Server 2008
I'm using this code syntax:
DECLARE #input VARCHAR(35) = '12-18-2018-03:14:48'
SELECT CONVERT(DATETIME, #input, 120)
Error:
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value
Please help. Thank you!

I'm not sure that your current datetime literal falls into any mask which SQL Server can recognize. But we can try using TRY_CONVERT here, replacing the middle dash with a space:
SELECT TRY_CONVERT(datetime, STUFF(#input, 11, 1, ' ')) AS output;
18/12/2018 03:14:48
Demo
Edit:
If you are using an earlier version of SQL Server which does not support TRY_CONVERT, then we can try explicitly using CONVERT:
SELECT CONVERT(datetime, STUFF(#input, 11, 1, ' ')) AS output;

Related

T-SQL- How to extract pattern '(yyyy)' in string with where 'like' query

I have a string data like 'wordword (2018)', want to extract those data with pattern (yyyy). have tried with '%/([0-9][0-9][0-9][0-9]/)%' but doesn't work
Building on HABO's comment, you can use something like:
DECLARE #Pattern VARCHAR(50) = '%([0-9][0-9][0-9][0-9])%'
SELECT A.value, yyyy = SUBSTRING(A.value, NULLIF(PATINDEX(#pattern, A.Value), 0) + 1, 4)
FROM (
VALUES
('wordword (2018)'),
('Nothing here'),
('this (2010) and that (2020)')
) A(value)
SQL Server has a very limited pattern matching support, so I converted your regex to the closest thing that SQL Server supports. The NULLIF() in the above converts a not-found index of zero to a null, which propagates to the result.
Did you try CHARINDEX?
SUBSTRING(#str,
CHARINDEX(‘[0-9][0-9][0-9][0-9]’,#str),4)

SQL RIGHT function not working as expected

I'm trying to extract the month number from a date as a left padded string with 0's.
So, for example, from '2018-01-31' I want the string '01'.
Currently I have this:
SELECT RIGHT('0' + CAST(MONTH('2018-01-31') AS CHAR(2)), 2)
Which is returning '1' but I would have expected it to return '01' because I've provided the second argument to RIGHT as 2.
Could someone explain why this isn't working as I think it should?
You need to change CHAR to VARCHAR:
SELECT RIGHT('0' + CAST(MONTH('2018-01-31') AS VARCHAR(2)), 2)
db<>fiddle demo
CHAR(2) is blank padded so you get RIGHT('01 ',2) which is '1 '.
You could use FORMAT instead, when you first cast the string to a DATE type.
SELECT FORMAT(CAST('2018-01-31' as DATE),'MM')
As for why that SQL with the right didn't work?
Try this SQL and notice the difference (the extra space):
SELECT quotename('0' + CAST(1 AS CHAR(2))), quotename('0' + CAST(1 AS VARCHAR(2)))

like with nvarchar is not working correctly?

Using Microsoft SQL Server 2012 - 11.0.5058.0 (X64) Express Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1) (Hypervisor)
with that creation/fill script :
CREATE TABLE tbl (col CHAR (32) )
insert into tbl values ('test')
Those kind of statements :
declare #var varchar(32) = 'test'
delete from tbl where col like #var
or
delete from tbl where col like 'test'
actually delete the line but why this one :
declare #nvar nvarchar(32) = 'test'
delete from tbl where col like #nvar
do not delete the line ?
According to this page... https://msdn.microsoft.com/en-us/library/ms179859.aspx
When you use Unicode data (nchar or nvarchar data types) with LIKE,
trailing blanks are significant;
Since you are using CHAR data type with length 32, the actual data stored is "test" + 28 spaces.
In your comparison, you are mixing CHAR and nvarchar. Because of the differing data types, SQL Server converts the CHAR data type to NCHAR to perform the comparison.
If you change the data type of the column to VARCHAR, your code works. You could also change your code to:
delete from tbl where col like #nvar + '%'

Convert a string representing a timestamp to an actual timestamp in PostgreSQL?

In PostgreSQL: I convert string to timestamp with to_timestamp():
select * from ms_secondaryhealthcarearea
where to_timestamp((COALESCE(update_datetime, '19900101010101'),'YYYYMMDDHH24MISS')
> to_timestamp('20121128191843','YYYYMMDDHH24MISS')
But I get this error:
ERROR: syntax error at end of input
LINE 1: ...H24MISS') >to_timestamp('20121128191843','YYYYMMDDHH24MISS')
^
********** Error **********
ERROR: syntax error at end of input
SQL state: 42601
Character: 176
Why? How to convert a string to timestamp?
One too many opening brackets. Try this:
select *
from ms_secondaryhealthcarearea
where to_timestamp(COALESCE(update_datetime, '19900101010101'),'YYYYMMDDHH24MISS') >to_timestamp('20121128191843','YYYYMMDDHH24MISS')
You had two opening brackets at to_timestamp:
where to_timestamp((COA.. -- <-- the second one is not needed!
#ppeterka has pointed out the syntax error.
The more pressing question is: Why store timestamp data as string to begin with? If your circumstances allow, consider converting the column to its proper type:
ALTER TABLE ms_secondaryhealthcarearea
ALTER COLUMN update_datetime TYPE timestamp
USING to_timestamp(update_datetime,'YYYYMMDDHH24MISS');
Or use timestamptz - depending on your requirements.
Another way to convert a string to a timestamp type of PostgreSql is the above,
SELECT to_timestamp('23-11-1986 06:30:00', 'DD-MM-YYYY hh24:mi:ss')::timestamp without time zone;
I had the same requirement as how I read the title. How to convert an epoch timestamp as text to a real timestamp. In my case I extracted one from a json object. So I ended up with a timestamp as text with milliseconds
'1528446110978' (GMT: Friday, June 8, 2018 8:21:50.978 AM)
This is what I tried. Just the latter (ts_ok_with_ms) is exactly right.
SELECT
data->>'expiration' AS expiration,
pg_typeof(data->>'expiration'),
-- to_timestamp(data->>'expiration'), < ERROR: function to_timestamp(text) does not exist
to_timestamp(
(data->>'expiration')::int8
) AS ts_wrong,
to_timestamp(
LEFT(
data->>'expiration',
10
)::int8
) AS ts_ok,
to_timestamp(
LEFT(
data->>'expiration',
10
)::int8
) + (
CASE
WHEN LENGTH(data->>'expiration') = 13
THEN RIGHT(data->>'expiration', 3) ELSE '0'
END||' ms')::interval AS ts_ok_with_ms
FROM (
SELECT '{"expiration": 1528446110978}'::json AS data
) dummy
This is the (transposed) record that is returned:
expiration 1528446110978
pg_typeof text
ts_wrong 50404-07-12 12:09:37.999872+00
ts_ok 2018-06-08 08:21:50+00
ts_ok_with_ms 2018-06-08 08:21:50.978+00
I'm sure I overlooked a simpler version of how to get from a timestamp string in a json object to a real timestamp with ms (ts_ok_with_ms), but I hope this helps nonetheless.
Update: Here's a function for your convenience.
CREATE OR REPLACE FUNCTION data.timestamp_from_text(ts text)
RETURNS timestamptz
LANGUAGE SQL AS
$$
SELECT to_timestamp(LEFT(ts, 10)::int8) +
(
CASE
WHEN LENGTH(ts) = 13
THEN RIGHT(ts, 3) ELSE '0'
END||' ms'
)::interval
$$;

How to make a function in DB2 database to convert an integer to date, and the case when is 0?

I was trying to make a function to work in db2:
CREATE FUNCTION TO_DATE8(DATE_STRING numeric(8,0))
RETURNS DATE
LANGUAGE SQL
IF DATE_STRING > 0 THEN
// ERROR ->
RETURN DATE ( TO_DATE ( SUBSTR ( DATE_STRING , 1 , 8 ) , 'YYYYMMDD' ) )
ELSE
RETURN DATE ( TO_DATE ( '00000000' , 'YYYYMMDD' ) )
END IF
END
ERROR: DATE IS NOT VALID
What to do?
The form of the procedure required seems to be like this (at least on the iSeries version):
CREATE FUNCTION TO_DATE8(DATE_STRING numeric(8,0))
RETURNS DATE
LANGUAGE SQL
BEGIN
RETURN(CASE WHEN DATE_STRING > 0 THEN DATE(SUBSTR(DATE_STRING, 1, 4) || '-' ||
SUBSTR(DATE_STRING, 5, 2) || '-' ||
SUBSTR(DATE_STRING, 7, 2))
ELSE DATE('0001-01-01')
END);
END
However:
Your procedure is misnamed (reading from a date-8, not to it).
Your DATE_STRING is not a string (or even a char), it's numeric. Please rename it to something that does not include the datatype (dateToConvert works)
You seem to want to return something that is not a valid date (all 0s). I'm returning *loval here, although it's possible it should actually be null.
I didn't put in enough checks for a valid date - this will blow up really easily.
If at all possible, the database should be changed to contain actual dates, not a numeric value. Disk is (relative to programmer/architect headaches) cheap.
You may also find a calendar file helpful, if the 8-digit numeric was one of the included columns.
For the benifit of others, this can be done in one line rather than a function:
CASE WHEN MYDATE = 0 THEN NULL ELSE DATE(INSERT(INSERT(LEFT(CHAR(MYDATE),8),5,0,'-'),8,0,'-')) END
MYDATE was 8 packed in my case.