[英]SQL convert string(date or text) to date
I have a database which has a column called stringNextDue
that contains data like dates (UK format) and text (eg "overdue", "completed") 我有一个数据库,其中有一个名为stringNextDue
的列,其中包含日期(英国格式)和文本(例如“逾期”,“已完成”)等数据
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. 这可能是由于stringNextDue
可能包含实际的文本字符串。
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 但ISDATE
只接受美国日期格式,因此忽略了很多实际日期作为字符串
Tried set dateformat 'dmy'
, which fixed the IsDate
issue, but it cannot be used in views. 尝试set dateformat 'dmy'
,修复了IsDate
问题,但不能在视图中使用。
Any suggestions? 有什么建议?
Server update is not an option 服务器更新不是一个选项
If you cannot use the new TRY_CONVERT
you might use a function like this: 如果你不能使用新的TRY_CONVERT
你可以使用这样的函数:
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... 注意:这不会像31.06.2016那样错误的日期,如果你需要,你必须修改BETWEEN 1 AND 31
...
Attention2: If your text might include characters forbidden in xml you should replace <
with <
注意2:如果您的文本可能包含xml中禁止的字符,则应替换<
with <
, >
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. 你可以传回一个有效的日期( RETURN GETDATE()
?)而不是RETURN NULL
为你的comparisson外。 This depends on your needs... 这取决于你的需求......
It should be possible to replace WHERE clause using this: 应该可以使用以下替换WHERE子句:
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
Thank you for suggestions, 谢谢你的建议,
I fixed it by setting language to British on user settings 我通过在用户设置上将语言设置为英语来修复它
EXEC sp_defaultlanguage 'username', 'british'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.