Regular expression for mm/yy in Microsoft SQL Server - sql

I am trying to execute a regular expression in SQL Server to match a MM/YY formatted VARCHAR string.
I have tried
WHERE ExpiryDate LIKE '[0-9][0-9]/[0-9][0-9]'
which allows incorrect dates like 30/18.
I also tried
WHERE ExpiryDate LIKE '0[1-9]|1[012]/[0-3][0-9]'
But SQL Server does not accept pipe separated as an OR operator.
I need the month to match 01 - 12
I can do
WHERE ExpiryDate LIKE '0[1-9]/[0-9][0-9]'
OR ExpiryDate LIKE '10/[0-9][0-9]'
OR ExpiryDate LIKE '11/[0-9][0-9]'
OR ExpiryDate LIKE '12/[0-9][0-9]'
but I would prefer it to be within the regular expression.
Thanks in advance for any help.

If 2012+, you could use try_convert() to convert the expiration string into a date. Try_Convert() will return a NULL value if the conversion fails.
Example
Declare #YourTable table (ID int, ExpiryDate varchar(25))
Insert Into #YourTable values
(1,'09/17')
,(2,'30/17')
Select *
From #YourTable
Where try_convert(date,replace(ExpiryDate,'/','/01/')) >= '2017-09-01'
-- Where try_convert(date,replace(ExpiryDate,'/','/01/')) is null
Returns
ID ExpiryDate
1 09/17

If you need to convalidate dates, you could try something like this:
SET DATEFORMAT dmy
;WITH A AS (SELECT '18/12' AS EXPDATE UNION ALL SELECT '10/17' UNION ALL SELECT 'x2/16' )
SELECT *, ISDATE('01/'+EXPDATE) AS CHK FROM A
Output:
EXPDATE CHK
18/12 0
10/17 1
x2/16 0

date LIKE '0[1-9]/[0-9][0-9]' OR
date LIKE '1[0-2]/[0-9][0-9]'
Is much shorter. But without | it is hard to make variants... Notice, that LIKE takes not regexes, but wildcards.
Don't forget, that '[1-9]/[0-9][0-9]' can also happen. And other variants, with inner spaces and so on. If you are not absolutely sure in month format used, and don't depend on high speed, use #JohnCampeletti variant.

Related

SQL Server - Value passes ISDATE() but fails to CAST as DATE or DATETIME

I have a varchar column in my database table, on the row I would like to return it is populated as '2018-12-26T00:00:00.000' (quotes mine, not included in actual value). When I try to query for this value whenever it is a valid date, e.g.
SELECT
myValue
FROM
myTable
WHERE
ISDATE(myValue) = 1
it returns properly. However, I need this value to be converted to DATE. When I try something like this:
SELECT
CAST(myValue AS DATE) AS myValueFormatted
FROM
myTable
WHERE
ISDATE(myValue) = 1
I get an error
Conversion failed when converting date and/or time from character string
Is there any other way I can convert this varchar value to Date?
UPDATE: I've noticed through trying some different things, the query seems to be fine with me using the value as a date for anything (DATEDIFF, CONVERT back to string, etc.) in the select portion, but trying to do anything with it in the WHERE clause causes the error. To ensure nothing else is interfering, I created a temp table with only 1 row with the data value above, and running the query just against that one value gives the error
UPDATE 2: Ok, I have no idea why this fixes it, but this is what I found. When I run
SELECT
myValue
FROM
myTable
WHERE
TRY_CONVERT(DATE, myValue) IS NOT NULL
it returns EXACTLY the same values as
SELECT
myValue
FROM
myTable
WHERE
ISDATE(myValue) = 1
However, when I then add AND CAST(myValue AS DATE) < GETDATE() to each WHERE clause, only the first one works. I understand why TRY_CONVERT is safer to use, I'm still not sure why it works over GETDATE()
I can't reproduce your error...
declare #dt varchar(256) = '2018-12-26T00:00:00.000'
select cast(#dt as date)
So, there must be another rogue value in there that can't be converted.
To identify what value is causing the issue on versions < 2012, run this:
SELECT
myValue
FROM myTable
WHERE
ISDATE(myValue) = 0
Note, ISDATE is deterministic only if you use it with the CONVERT function, if the CONVERT style parameter is specified, and style is not equal to 0, 100, 9, or 109.
For 2012 onward, use TRY_CONVERT
SELECT
*
FROM myTable
WHERE
TRY_CONVERT(date, myValue) IS NULL
You could also just try something like this:
SELECT CAST(LEFT(MyValue, 10) AS DATE)
If it still doesn't work, you have some formatting issues with your data.
This helped me....
CAST string as varchar(30) then cast the varchar as datetime2
CAST(CAST(REPLACE(['Timestamp' ],'''','') AS varchar(30)) as datetime2)

Convert VARCHAR to DATE in SQL SERVER

I have VARCHAR column (MyValue) in my table. It has date value in two different format.
MyValue
----------
25-10-2016
2016-10-13
I would like to show them in DATE format.
I wrote query like below:
SELECT CONVERT(date, MyValue, 105) FROM MyTable
SELECT CAST(MyValue as date) FROM MyTable
Both are giving me this error. Conversion failed when converting date and/or time from character string.
Is there anyway convert to DATE datatype format even the value stored in different formats like above?
Expecting your answers. Thanks in advance.
Does this help?
declare #varchardates table
(
vcdate varchar(20)
)
INSERT INTO #varchardates VALUES
('25-10-2016'),
('2016-10-13')
SELECT CONVERT(date,vcdate, case when SUBSTRING(vcdate, 3, 1) = '-'
THEN 105 ELSE 126 END) as mydate
FROM #varchardates
Depending on how many different formats you have in your data, you may need to extend the case statement!
See here for list of the different format numbers
You can use TRY_CONVERT and COALESCE. TRY_CONVERT returns NULL if the conversion fails, COALESCE returns the first NOT NULL value:
SELECT COALESCE(TRY_CONVERT(DATETIME, x, 105), TRY_CONVERT(DATETIME, x, 120))
FROM (VALUES('25-10-2016'), ('2016-10-13')) a(x)
I assumed the value 2016-10-13 is in format yyyy-MM-dd.
You mention in a comment you may have other formats as well. In that case it gets very tricky. If you get a value 01-12-2017 and you have no idea about the format, there is no way to tell whether this is a date in januari or in december.

COALESCE db2 date

I am trying to query on 2 different date fields and one date field (datefield2) has null values. My date field is CCYYDDD and I usually convert this to mm/dd/yyyy by date(digits(datefield)) as NewDate.
This fails
SELECT type, date(digits(datefield1)) AS DateEntered, coalesce(varchar(datefield2),'') as Renewed
FROM MYDATA
WHERE date(digits(datefeld1)) between '06/01/2015' and '6/30/2015' OR date(digits(coalesce(varchar(rendt7),''))) between '06/01/2015' and '06/30/2015'
The following succeeds
SELECT type, date(digits(datefield1)) AS DateEntered, coalesce(varchar(datefield2),'') as Renewed
FROM MYDATA
WHERE date(digits(datefeld1)) between '06/01/2015' and '6/30/2015' OR coalesce(varchar(rendt7),'') between '2015152' and '2015181
How can I query where my date fields contain null values? I plan on passing parameters in for the date range values and would rather just pass mm/dd/yyyy.
I'm a little confused by your question, but I think what you're really looking for is the TIMESTAMP_FORMAT function. I think it would be something like this:
SELECT
type
,DATE(TIMESTAMP_FORMAT(datefield1,'YYYYDDD')) AS DateEntered
,DATE(COALESCE(TIMESTAMP_FORMAT(datefield2,'YYYYDDD'),'0001-01-01')) AS Renewed
FROM MYDATA
WHERE DATE(TIMESTAMP_FORMAT(COALESCE(datefield1, rendt7),'YYYYDDD'))
BETWEEN #date1 AND #date2

How to convert GetDate() in 1 Jan 2014 format?

I using a query where I am selecting some attributes from the table based on a where condition. My where condition is-
date>GetDate();
I have tried this-
SELECT TOP 2 img,name,substring(description,1,80) as
description,Convert(nvarchar,date,106) as date
FROM tbl_test
where date>=Convert(nvarchar,GetDate(),106)
order by date Asc;
This query is running fine but showing different result as compared to a different query of similar kind in which I am not converting the date format.
SELECT TOP 2 img,name,substring(description,1,80) as description,date
FROM tbl_test
where date>=GetDate()
order by date Asc;
Please guide me where I am doing wrong?
Your first query will convert getdate() into nvarchar data type and it will compare date with string while 2nd query will compare 2 dates. So 2nd option is better. Still if you want to convert date into string then check then use 102 format like
WHERE CONVERT(varchar(20),date,102) >= CONVERT(varchar(20), getdate(),102)
For select column you can use format which you want like
SELECT CONVERT(varchar(20),date,106)
Final Query is :
SELECT TOP 2
img,
name,
SUBSTRING(description,1,80) as description,
CONVERT(varchar(20),date,106) as [DisplayDate]
FROM tbl_test
WHERE CONVERT(varchar(20),date,102) >= CONVERT(varchar(20), getdate(),102)
ORDER BY date ASC;
Without convert to varchar, you can cast getdate() to date to remove time part :
SELECT TOP 2
img,
name,
SUBSTRING(description,1,80) as description,
CONVERT(varchar(20),date,106) as [DisplayDate]
FROM tbl_test
WHERE date >= CAST(getdate() as date)
ORDER BY date ASC;
SQL Fiddle Demo
DECLARE #Date Datetime;
SET #Date = GETDATE();
SELECT CONVERT(VARCHAR(12), #Date, 113) AS Date
RESULT
╔══════════════╗
║ Date ║
╠══════════════╣
║ 01 Jan 2014 ║
╚══════════════╝
Edit
as Upendra Chaudhari has explained that when you do comparing column Date with a string =Convert(varchar(20),GetDate(),102),
what is actually happening behind the scenes is Convert(varchar(20),GetDate(),102) returns a string 2014.01.01 but to compare this string with a Datetime column SQL Server does an implicit conversion to compare both values. Sql Server have to have both values in the same datatype to compare them.
Now datatype Datetime has Precedence over nvarchar/varchar datatype so sql server converts the string into datetime datatype which returns something like
SELECT CAST('2014.01.01' AS DATETIME)
Result : 2014-01-01 00:00:00.000
Now in this process of converting your values to string and then back to datetime you have actually lost all the time values in your comparing values. and this is the reason why you are getting unexpected results back.
so make sure whenever you are comparing to have exactly the same datatype on both sides and take control of any data conversions in your code rather then sql server doing datatype conversions for you.
I hope this will explain you why you are getting different results .
You may try:
where date>=CONVERT(VARCHAR(11), GETDATE(), 113)

SQL: Convert String of MMMDD to Datetime

I have a nvarchar(5) column of data that is formatted MMMDD (for example, OCT26). With my select statement, I'd like to convert it to a datetime data type with the current year, and then save that datetime value as an alias, say, UsefulDate. So something like 10-26-2012.
Something like: SELECT (whatever SQL gets the job done) AS UsefulDate
The exact formatting doesn't matter; I just need to be able to compare two dates together with greater than and less than operators. Also, sometimes the column will be blank. In that case, I'd like to set the alias to blank as well. Is this possible?
Thanks for your help!
You can convert varchar fields in format MMMDD to date with current year with :
select convert(datetime,'OCT26'+','+cast(year(getdate()) as varchar),107)
So your query would be something like :
select convert(datetime,case varcharDate when '' then null else varcharDate end +
','+cast(year(getdate()) as varchar),107) as UsefulDate
from table
select CASE WHEN ISDATE(mmmdd+' '+right(year(getdate()),4)) = 1
THEN CAST(mmmdd+' '+right(year(getdate()),4) as datetime)
END UsefulDate, *
from tbl