【问题标题】:Conversion failed when converting date and/or time from character string in SQL从 SQL 中的字符串转换日期和/或时间时转换失败
【发布时间】:2014-07-16 15:24:17
【问题描述】:

我的表中有以下列:

year  decimal(4,0)
month decimal(2,0)
day   decimal(2,0)

我正在尝试将它们转换如下:

SELECT (CAST (CAST(year  AS varchar(4))
             +CAST(month AS varchar(2))
             +CAST(day   AS varchar(2)
             ) AS date ) ) AS xDate
FROM table 
ORDER BY xDate DESC

但我收到此错误:

从字符串转换日期和/或时间时转换失败。

【问题讨论】:

  • 您是否要转换为日期时间?
  • 我用硬编码的数字做了一个快速测试,它对我有用,所以你确定“年”、“月”和“日期”是数字并且在可接受的范围内吗?
  • @Kris - 我正在尝试将其转换为日期,但如果它很容易转换为日期时间,那也没关系,但我遇到了错误。
  • @jimo3 - 是的,它们是数字,但数据类型是十进制并试图转换为日期数据类型。

标签: sql sql-server sql-server-2008 tsql


【解决方案1】:

您的方法没有考虑到monthday 可以是个位数的值。如果你有这样的一行:

year  month  day
----  -----  ---
2014  7      18

您的方法会将这些部分连接为2014718,随后尝试将其转换为date 将导致相关错误。

您可能打算像这样组合这些部分:20140718,这将毫无问题地转换为date。对我来说,从数字部分获取该格式的最简单方法是这样:

  • 计算year * 10000 + month * 100 + day

  • 将之前的结果转换为char(8)

  • 将字符串转换为date

所以,在 Transact-SQL 中应该是这样的:

CAST(CAST(year * 10000 + month * 100 + day AS char(8)) AS date)

另一方面,我不可能知道您是否真的需要像那样存储日期拆分,但如果您确实坚持这样做,至少考虑对部分使用整数类型。我意识到decimal(2,0) 可能会为您提供某种约束,以确保您的月份或日期值不能超过 2 位,但它仍然不能保护您免受无效月份或日期的影响。另一个重点是decimal(2,0) 甚至比int 需要更多的存储空间,更不用说smallinttinyint

所以,这对我来说似乎很好

year  int,
month int,
day   int

但如果你想尽可能节省存储空间,你也可以试试这个:

year  smallint,
month tinyint,
day   tinyint

最后,为了确保这些列中不能包含无效值,您可以添加如下检查约束:

ALTER TABLE tablename
ADD CONSTRAINT CK_tablename_yearmonthday CHECK 
  ISDATE(CAST(year * 10000 + month * 100 + day AS char(8))) = 1
;

【讨论】:

    【解决方案2】:

    这个问题是因为您的表中有冗余数据(您的查询没有问题)。检查表中的以下内容。

    1)。 days 列 的值不得大于 关联月份 中的最大天数(例如,第 2 个月不得有 30 或 31 天)。

    2)。 月份列的值不得大于12或等于0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多