【问题标题】:Using T-SQL DATEFROMPARTS to return NULL instead of throw error使用 T-SQL DATEFROMPARTS 返回 NULL 而不是抛出错误
【发布时间】:2015-03-13 07:39:52
【问题描述】:

我经常以某种整数组合或单个 8 位整数的形式收到日期。为了将它们转换为可用日期,我尝试了 DATEFROMPARTS 函数,但是当日期不合理时,它会在首选 NULL 时引发错误。

我希望找到一个行为类似于 TRY_PARSE 的函数,它接受整数并为无效日期返回 NULL 而不是错误,但不需要字符串转换,因为我想在 PERSISTED 计算字段中使用它。最后,我只是决定在转换之前测试整数。

CASE WHEN @year BETWEEN 1 AND 9999 AND (@month BETWEEN 1 AND 12 AND @day BETWEEN 1 AND 28
       OR @month IN(1, 3, 5, 7, 8, 10, 12) AND @day BETWEEN 1 AND 31
       OR @month IN(4, 6, 9, 11) AND @day BETWEEN 1 AND 30
       OR @month = 2 AND @day BETWEEN 1 and CASE WHEN NOT @year % 4 = 0 THEN 28 WHEN NOT @year % 100 = 0 THEN 29 WHEN NOT @year % 400 = 0 THEN 28 ELSE 29 END)
     THEN DATEFROMPARTS(@year, @month, @day) END

这为所有 1000 万个相关整数输入(年从 0 到 9999,月从 0 到 99,日从 0 到 99)给出了日期或 NULL 我假设结果是正确的,但我还没有完成测试。有没有更好的方法可以安全地将整数输入转换为持久计算字段的日期(因此不允许字符串转换),不会引发我没有找到的错误?

【问题讨论】:

  • 你需要修复你的数据类型 homie...
  • 虽然我不能像 Zane 那样认识你,但我认为存储 Date、DateTime 或 DateTime2 是更好的做法。年、月、日的计算字段是微不足道的,您将更好地利用索引,并且您不会携带不良数据。简而言之,您选择在后端处理不良数据,而不是在前端停止不良数据。
  • 也许你应该反过来。一个DATE 列和3 个持续计算的yearmonthday 列(正如@jtimperley 指出的那样,快了6 秒)。
  • @AndriyM,使用 TRY_PARSE 的字符串转换不会持续,因为它是不确定的。
  • 好的,谢谢。我的问题是关于支票的,我认为你不需要(我现在已经证实你实际上不需要)。您也不需要内部 TRY_CONVERT 上的 112。除此之外,您的解决方案似乎非常好,我真诚地认为您应该将其发布为答案

标签: sql sql-server tsql


【解决方案1】:

我不确定我是否理解正确,但这可能会有所帮助:

DECLARE @year VARCHAR(100)= '1993';
DECLARE @month VARCHAR(100)= '12';
DECLARE @day VARCHAR(100)= '01';


SELECT CASE 
WHEN  ISNUMERIC(@year) = 0 OR  ISNUMERIC(@month) = 0 OR  ISNUMERIC(@day) = 0 THEN NULL
WHEN @year BETWEEN 1 AND 9999 AND (@month BETWEEN 1 AND 12 AND @day BETWEEN 1 AND 28
       OR @month IN(1, 3, 5, 7, 8, 10, 12) AND @day BETWEEN 1 AND 31
       OR @month IN(4, 6, 9, 11) AND @day BETWEEN 1 AND 30
       OR @month = 2 AND @day BETWEEN 1 and CASE WHEN NOT @year % 4 = 0 THEN 28 WHEN NOT @year % 100 = 0 THEN 29 WHEN NOT @year % 400 = 0 THEN 28 ELSE 29 END)
     THEN DATEFROMPARTS(@year, @month, @day) END;

输出:

1993-12-01

DECLARE @year VARCHAR(100)= '1993';
DECLARE @month VARCHAR(100)= 'Jan';
DECLARE @day VARCHAR(100)= '01';


SELECT CASE 
WHEN  ISNUMERIC(@year) = 0 OR  ISNUMERIC(@month) = 0 OR  ISNUMERIC(@day) = 0 THEN NULL
WHEN @year BETWEEN 1 AND 9999 AND (@month BETWEEN 1 AND 12 AND @day BETWEEN 1 AND 28
       OR @month IN(1, 3, 5, 7, 8, 10, 12) AND @day BETWEEN 1 AND 31
       OR @month IN(4, 6, 9, 11) AND @day BETWEEN 1 AND 30
       OR @month = 2 AND @day BETWEEN 1 and CASE WHEN NOT @year % 4 = 0 THEN 28 WHEN NOT @year % 100 = 0 THEN 29 WHEN NOT @year % 400 = 0 THEN 28 ELSE 29 END)
     THEN DATEFROMPARTS(@year, @month, @day) END;

输出:

【讨论】:

  • 该函数的工作原理是输入是整数。我的问题是,是否有另一种方法可以可靠且安全地从整数中为持久计算字段生成日期。不能有字符串类型,因为语句必须在持久计算字段中可用。
猜你喜欢
  • 2019-03-03
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多