转换和验证日期字符串的最佳方法

KM.*_*KM. 11 t-sql sql-server sql-server-2005

我在存储过程中有一个char(8)变量格式化为ddmmyyyy(此值的质量和有效性未知且超出我的控制范围).将值移动到datetime变量的最有效方法是什么,如果它不是有效的datetime则抛出错误.

DECLARE @Source       char(8)
DECLARE @Destination  datetime

SET @Source='07152009'

--your solution here


SELECT @Destination
Run Code Online (Sandbox Code Playgroud)

这是我能想到的最佳方式:

DECLARE @Source             char(8)
DECLARE @Temp               varchar(10)
DECLARE @Destination        datetime

set @Source='07152009'
SET @Temp=LEFT(@Source,2)+'/'+SUBSTRING(@Source,3,2)+'/'+RIGHT(@Source,4)

IF ISDATE(@Temp)!=1
BEGIN
    RAISERROR('ERROR, invalid date',16,1)
END
SET @Destination=@Temp

SELECT @Source AS Source, @Temp AS  Temp, @Destination AS Destination
Run Code Online (Sandbox Code Playgroud)

编辑这里是我要去的...

DECLARE @Source             char(8)
DECLARE @Destination        datetime

set @Source='07152009'
BEGIN TRY
    SET @Destination=CONVERT(datetime,RIGHT(@Source,4)        -- YYYY
                                      +LEFT(@Source,2)        -- MM
                                      +SUBSTRING(@Source,3,2) -- DD
                             )
END TRY
BEGIN CATCH
    PRINT 'ERROR!!!' --I'll add a little more logic here and abort processing
END CATCH

SELECT @Source AS Source, @Destination AS Destination
Run Code Online (Sandbox Code Playgroud)

mar*_*c_s 12

首先,既然您正在使用SQL Server 2005,那么您应该将可能失败的代码放入BEGIN TRY.....END TRY BEGIN CATCH....END CATCH块中 - 使用T/SQL的try/catch块!

其次,对于所有日期操作,我总是使用ISO-8601格式,无论SQL Server中设置了什么当前日期格式,它都将起作用.

ISO-8601格式仅YYYYMMDD适用于日期或YYYY-MM-DDTHH:MM:SS日期与时间 - 所以我将您的代码编写为:

BEGIN TRY
  SET @Source='07152009'
  SET @Temp = RIGHT(@Source, 4) +             -- YYYY
              LEFT(@Source, 2) +              -- MM
              SUBSTRING(@Source, 3, 2)        -- DD

  IF ISDATE(@Temp)!=1
  BEGIN
      RAISERROR('ERROR, invalid date',16,1)
  END

  SET @Destination = CAST(@Temp AS DATETIME)
END TRY
BEGIN CATCH
      -- handle error if something bombs out
END CATCH
Run Code Online (Sandbox Code Playgroud)

不要依赖任何特定的日期格式!把你的代码发给我,我会在瑞士 - 德国系统上试一试 - 我几乎可以保证,如果你盲目地假设"en-US"并因此"mm/dd/yyyy"它会破裂 - 它在各地的设置都不一样这个星球.

不幸的是,SQL Server处理日期相当薄弱 - 也许这可能是一个扩展点,在SQL Server中使用CLR程序集是有意义的,可以利用.NET中更丰富的日期处理函数?

PS:似乎是ISO-8601格式,我知道YYYY-MM-DD并不总是在SQL Server中运行 - 与在线书籍似乎宣传的相反.使用YYYYMMDD或YYYY-MM-DDTHH:MM:SS代替.
谢谢,gbn!


gbn*_*gbn 6

您可以使用SET DATEFORMAT保证日期 - 月 - 年订单.这意味着ISDATE将于2009年7月15日解析'15 -07-2009'

否则,考虑到外部限制,您的方法已经足够好了......但您也可以重新订购ANSI/ISO.

在marc_s回答之后:"SET DATEFORMAT dmy"适用于大多数欧洲设置......

好:

SET LANGUAGE british
SELECT ISDATE('2009-07-15') --this is ansi says marc_s. It gives "zero"
SELECT ISDATE('2009-07-15T11:22:33') --this really is ANSI and gives true


SET LANGUAGE german
SELECT ISDATE('2009-07-15') --false
SELECT ISDATE('2009-07-15T11:22:33') --true
Run Code Online (Sandbox Code Playgroud)