Reputation: 53
I have a database which has a column called stringNextDue
that contains data like dates (UK format) and text (e.g "overdue", "completed")
I am trying to create a view that shows courses that are due within a month from now:
WHERE
CONVERT(DATETIME, mt.stringNextDue , 103) < DATEADD(MONTH, 1, GETDATE())
This throws an error:
Conversion failed when converting date and/or time from character string.
Which is probably due to the fact that stringNextDue
may contain actual strings of text.
I tried using
WHERE
ISDATE(mt.NextDateString) = 1
AND CONVERT(DATETIME, mt.stringNextDue , 103) < DATEADD(MONTH, 1, GETDATE())
But ISDATE
only accepts US date formats therefore ignoring a lot of actual dates as strings
Tried set dateformat 'dmy'
, which fixed the IsDate
issue, but it cannot be used in views.
Any suggestions?
Server update is not an option
Upvotes: 3
Views: 2023
Reputation: 53
Thank you for suggestions,
I fixed it by setting language to British on user settings
EXEC sp_defaultlanguage 'username', 'british'
Upvotes: 0
Reputation: 44316
It should be possible to replace WHERE clause using this:
SELECT *
FROM
-- sample data
(values('2015-01-01'),('01-01-2015'), ('x-x-x-x')) mt(NextDateString)
-- Replace WHERE statement with the following
CROSS APPLY
(
SELECT
RIGHT('0000'+PARSENAME(REPLACE(mt.NextDateString, '-', '.'), 1),4) yyy,
RIGHT('0000'+PARSENAME(REPLACE(mt.NextDateString, '-', '.'), 2),4) mmm,
RIGHT('0000'+PARSENAME(REPLACE(mt.NextDateString, '-', '.'), 3),4) ddd
) x
WHERE
x.yyy BETWEEN '1950' AND '2050'
AND x.mmm BETWEEN '0001' AND '0012'
AND x.ddd BETWEEN '0001' AND '0031'
AND ISDATE(mt.NextDateString) = 1
AND x.yyy+x.mmm+x.ddd < CONVERT(char(8), DATEADD(MONTH, 1, GETDATE()), 112)
Result:
NextDateString yyy mmm ddd
01-01-2015 2015 0001 0001
Upvotes: 0
Reputation: 67301
If you cannot use the new TRY_CONVERT
you might use a function like this:
Attention: This will not catch a wrong date like 31.06.2016, you'd have to modify the BETWEEN 1 AND 31
if you need this...
Attention2: If your text might include characters forbidden in xml you should replace <
with <
, >
with >
and &
with &
...
CREATE FUNCTION dbo.TestDate(@TestString VARCHAR(100))
RETURNS DATE
AS
BEGIN
DECLARE @x XML=CAST('<x>' + REPLACE(@TestString,'.','</x><x>') + '</x>' AS XML)
DECLARE @p1 VARCHAR(10) = @x.value('x[1]','varchar(10)');
DECLARE @p2 VARCHAR(10) = @x.value('x[2]','varchar(10)');
DECLARE @p3 VARCHAR(10) = @x.value('x[3]','varchar(10)');
IF LEN(@p1)=2 AND ISNUMERIC(@p1)=1 AND CAST(@p1 AS INT) BETWEEN 1 AND 31
AND LEN(@p2)=2 AND ISNUMERIC(@p2)=1 AND CAST(@p2 AS INT) BETWEEN 1 AND 12
AND LEN(@p3)=4 AND ISNUMERIC(@p3)=1 AND CAST(@p3 AS INT) BETWEEN 1900 AND 2100
RETURN CONVERT(DATETIME, @TestString , 103);
RETURN NULL;
END
GO
SELECT
dbo.TestDate('overdue') AS SureNoDate
,dbo.TestDate('01.04.2016') AS EuropeanDate
,dbo.TestDate('2016.04.01') AS WrongFormat
,dbo.TestDate('01.13.2016') AS BadDate;
GO
DROP FUNCTION dbo.TestDate;
The result
SureNoDate EuropeanDate WrongFormat BadDate
NULL 2016-04-01 NULL NULL
You might pass back a valid date (RETURN GETDATE()
?) instead of RETURN NULL
for your comparisson outside. This depends on your needs...
Upvotes: 2