SQL转换字符串(日期或文本)到日期

时间:2016-03-30 13:54:46

标签: sql sql-server sql-server-2008-r2

我有一个数据库,其中有一个名为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问题,但无法在视图中使用。

有什么建议吗?

服务器更新不是一个选项

3 个答案:

答案 0 :(得分:2)

如果你不能使用新的TRY_CONVERT,你可以使用这样的函数:

注意:这不会像31.06.2016一样错误的日期,如果你需要,你必须修改BETWEEN 1 AND 31 ......

注意2:如果您的文字可能包含xml中禁止使用的字符,则应将<替换为&lt;,将>替换为&gt;,将&替换为&amp; } ...

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'