【问题标题】:Try/Catch in UDF not possible? How to "TryCast" a varchar to datetime?无法在 UDF 中尝试/捕获?如何“TryCast”将 varchar 转换为日期时间?
【发布时间】:2011-03-21 11:10:33
【问题描述】:

如何将 varchar 参数转换为日期时间,如果转换失败,则默认使用 GetDate()? 我试图把它放在 Try/Catch 中,但显然这在 UDF 中不起作用。简单地检查 datetime 是否为 null 也不起作用,因为它会抛出异常('将 char 数据类型转换为 datetime 数据类型导致超出范围的 datetime 值'):

CREATE FUNCTION [dbo].[getRZUInfo]
(
    @IMEI varchar(20),
    @StrDeliveryDate varchar(20)
)
RETURNS VARCHAR(8000)
AS
BEGIN
    DECLARE @Info VARCHAR(8000) 
    DECLARE @DeliveryDate datetime;
    SET @DeliveryDate = Convert(datetime,@StrDeliveryDate,102);
    IF @DeliveryDate IS NULL
        SET @DeliveryDate=GetDate();
    SELECT   @Info = COALESCE(@Info + '|', '') + 'TAT_B2B: ' + Convert(varchar,tabData.TAT_B2B) + ', AC' + Convert(varchar,tabData.fimaxActionCode) + ', Diff: ' + Convert(varchar,DateDiff(day,tabData.Received_date,@DeliveryDate))
        FROM   tabData
    WHERE     (SSN_Number = @IMEI) AND (Received_Date >= DATEADD(month, -3, @DeliveryDate))
    ORDER BY SSN_Number,Received_Date DESC
    return @Info
END

【问题讨论】:

  • 您期待任何特定的日期格式吗?或者它是开放的厚厚的? “2010 年 1 月 1 日”、“2011 年 12 月 13 日”、“2010.02.02”等?
  • udf 主要用于 excel 插件,我可以假装格式(02.12.2010)。
  • 你可以假装,但是错误的 DATEFORMAT 设置会抛出 ISDATE,你可能有有效的日期被getdate()替换

标签: sql sql-server-2005 tsql


【解决方案1】:
SET @DeliveryDate = CASE
                      WHEN Isdate(@StrDeliveryDate) = 1 THEN
                      CONVERT(DATETIME, @StrDeliveryDate, 102)
                      ELSE Getdate()
                    END  

【讨论】:

  • 看我的回答。仍在扩展它
  • @Richard - 好点,在set dateformat dmy 之下。 SELECT CONVERT(DATETIME, '2011.12.13', 102),ISDATE('2011.12.13') 返回 2011-12-13 00:00:00.000,0 所以在这种情况下它是不必要的悲观。如果您希望日期为ymd 格式,那么您的日期格式为dmy 是否有意义?
  • 我希望如此。因为我在英国系统(dmy)中工作,但数据来自一些进口,而且 ymd 很常见。
【解决方案2】:

IsDate 的一个常见缺陷是它无法接受 CAST/CONVERT 可以接受的日期格式说明符。

看这个:

set dateformat dmy
declare @StrDeliveryDate varchar(20) set @StrDeliveryDate = '2011.12.13'
select CASE
 WHEN Isdate(@StrDeliveryDate) = 1 THEN
 CONVERT(DATETIME, @StrDeliveryDate, 102)
 ELSE Getdate()
 END 

output: 2011-03-21 22:19:54.683

这是专门用于测试 102 格式日期的更好功能。其实 102 更容易,这足够灵活,可以拾取 yy/yyyy, m/mm, d/dd。

create function dbo.Is102Date(@any varchar(50))
-- 102 = yyyy.mm.dd
returns bit as begin
set @any = ltrim(rtrim(@any))
declare @theyear varchar(10)
set @TheYear = case
       when @any like '%[^0-9.]%' then null
       when @any like '[0-9][0-9].%[0-9].%[0-9]' then
           case when LEFT(@any,2) >=50
           then '19'+LEFT(@any,2)
           else '20'+LEFT(@any,2)
           end
       when @any like '[0-9][0-9][0-9][0-9].%[0-9].%[0-9]' then
           LEFT(@any,4)
       end
declare @YYYYMMDDToTest varchar(50)
set @YYYYMMDDToTest = case
       when @TheYear is not null then
           @TheYear
           + -- month
           SUBSTRING(@any, charindex('.',@any) +1,
           charindex('.',@any,charindex('.',@any)+1)-
           charindex('.',@any)-1)
           + -- day
           right(@any,charindex('.',reverse(@any))-1)
       end
return ISDate(@YYYYMMDDToTest)
end
GO

使用它而不是 ISDATE 来测试 varchar 中的 102 格式日期。

【讨论】:

    【解决方案3】:

    只是在 Null 时检查

    IF @StrDeliveryDate IS NULL
        SET @DeliveryDate = GetDate();
    ELSE
        SET @DeliveryDate = Convert(datetime, @StrDeliveryDate, 102);
    

    【讨论】:

    • @StrDeliveryDate 不会为空,但可能是“-”或“否”或其他。
    • @Tim:好的,我会删除我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    相关资源
    最近更新 更多