【问题标题】:Convert VARCHAR to SMALLDATETIME as part of UPDATE statement将 VARCHAR 转换为 SMALLDATETIME 作为 UPDATE 语句的一部分
【发布时间】:2013-10-20 16:11:24
【问题描述】:

我正在对 CSV 文件执行批量数据导入。在 CSV 文件中,我的“日期”列包含格式为“YYYYDDMMHHMM”的日期(例如 200603010929)。

就目前而言,如果我在创建表时选择“smalldatetime”,数据导入将失败并出现以下错误:

批量加载数据转换错误(类型不匹配或无效字符 对于指定的代码页)对于第 2 行第 2 列(日期)。

据我了解,要使其正常工作,日期必须采用某种格式才能工作。

因此,我的一个想法是将日期值导入到 VARCHAR 类型的字段中,然后在导入完成后,我想对每一行执行 UPDATE 以将日期转换为 smalldatetime。这会延长导入过程,但我认为这比尝试对 CSV 数据进行查找和替换(这是一个巨大的数据集)要容易得多,也快得多。

所以,我的问题是: 1)这可能吗? 2)我如何实现它?

这是我目前所拥有的:

UPDATE NYSE
SET [date]=CONVERT(smalldatetime, [date])

这失败了,因为文本的格式不正确。是否可以在 CONVERT 函数中指定字符串的格式,还是有其他方法?

我感谢所有 cmets。谢谢。

【问题讨论】:

  • 真的是 YYYYDDMM 而不是 YYYYMMDD?所以 20060301 是 1 月 3 日,而不是 3 月 1 日?
  • 您确定没有时间的 YYYYDDMM 实际导入正确吗?那些可能是交换 D 和 M 值...
  • 所以你不在乎数据是否准确?所以用户输入了 3 月 1 日,但您将其解释为 1 月 3 日,这可以吗?我很困惑。
  • 您在该页面的何处看到 YYYY-DD-MM?
  • 我建议告诉向您提供此数据的人不要再傻了,并提供有效的格式。或者在添加 SQL Server 复杂性之前使用非常简单的命令行程序对文件进行预处理。

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


【解决方案1】:
DECLARE @s TABLE([date] VARCHAR(20));

INSERT @s SELECT '200603010929';

UPDATE @s SET [date] = CONVERT(CHAR(16), CONVERT(SMALLDATETIME, 
  LEFT([date],4) + SUBSTRING([date],7,2) + SUBSTRING([date],5,2) 
  + ' ' + STUFF(RIGHT([date],4),3,0,':')), 120);

SELECT [date], CONVERT(SMALLDATETIME, [date]) FROM @s;

如果真的是YYYYMMDD,那就稍微简单一点:

DECLARE @s TABLE([date] VARCHAR(20));

INSERT @s SELECT '200603010929';

UPDATE @s SET [date] = CONVERT(CHAR(16), CONVERT(SMALLDATETIME, 
  LEFT([date],8) + ' ' + STUFF(RIGHT([date],4),3,0,':')), 120);

SELECT [date], CONVERT(SMALLDATETIME, [date]) FROM @s;

【讨论】:

  • 感谢您的回答。如果有机会,您能否编辑答案以演练正在发生的事情?这将帮助我理解它并检查这是否适用于我的场景。
  • 它基本上只是将无效字符串的碎片拉开以形成有效字符串。从第二行开始,开始计算前 4 个字符(2006),然后是第 7 和第 8 个字符(01),然后是第 5 和第 6 个字符(01)。这形成了 YYYYMMDD 格式的有效且明确的日期。然后在第 3 行,我们添加一个空格并在最后 4 个字符 (0929) 中注入一个冒号,使其成为有效时间 (09:29) 并形成一个完整的字符串 20060103 09:29。我们可以将这个字符串转换为 smalldatetime,但是为了以这种方式存储字符串,我们还需要一个样式。
  • 我按照您提供的方式运行了 Update 语句,但出现错误,“字符串或二进制数据将被截断”。我的 varchar 目前有 15 个字符的限制。我将 CHAR(16) 参数更改为 CHAR(15) - 它抛出了错误,“将 varchar 数据类型转换为 smalldatetime 数据类型导致超出范围的值。”。这次跑得更久了。在运行此之前,我是否需要提高我的 varchar 的限制?
  • 是的,您会注意到我使用 varchar(20) 进行填充。您现在遇到的错误是因为您至少有一个日期不是您描述的格式。试试SELECT ... FROM dbo.table WHERE ISDATE(LEFT([date],4) + SUBSTRING([date],7,2) + SUBSTRING([date],5,2) + ' ' + STUFF(RIGHT([date],4),3,0,':')) = 0;
  • 我想你错过了我说你有一些我的答案无法修复的无效数据的部分,你必须使用我在评论中发布的 SELECT 来识别它并修复它...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
相关资源
最近更新 更多