我有一个数据库,其中有一个名为stringNextDue
的列,其中包含日期(英国格式)和文本(例如“过期”,“已完成”)等数据
我正在尝试创建一个视图,显示从现在起一个月内到期的课程:
WHERE
CONVERT(DATETIME, mt.stringNextDue , 103) < DATEADD(MONTH, 1, GETDATE())
这会引发错误:
从字符串转换日期和/或时间时转换失败。
这可能是因为stringNextDue
可能包含实际的文本字符串。
我尝试使用
WHERE
ISDATE(mt.NextDateString) = 1
AND CONVERT(DATETIME, mt.stringNextDue , 103) < DATEADD(MONTH, 1, GETDATE())
但是ISDATE
只接受美国日期格式,因此忽略了许多实际日期作为字符串
尝试set dateformat 'dmy'
,修复了IsDate
问题,但无法在视图中使用。
有什么建议吗?
服务器更新不是一个选项
答案 0 :(得分:2)
如果你不能使用新的TRY_CONVERT
,你可以使用这样的函数:
注意:这不会像31.06.2016一样错误的日期,如果你需要,你必须修改BETWEEN 1 AND 31
......
注意2:如果您的文字可能包含xml中禁止使用的字符,则应将<
替换为<
,将>
替换为>
,将&
替换为&
} ...
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;
结果
SureNoDate EuropeanDate WrongFormat BadDate
NULL 2016-04-01 NULL NULL
您可能会将有效日期(RETURN GETDATE()
?)而不是RETURN NULL
传回给外面的比较。这取决于您的需求......
答案 1 :(得分:0)
应该可以使用以下方法替换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)
结果:
NextDateString yyy mmm ddd
01-01-2015 2015 0001 0001
答案 2 :(得分:0)
感谢您的建议,
我通过在用户设置上将语言设置为英国来修复它
EXEC sp_defaultlanguage 'username', 'british'