【问题标题】:SQL Date-Time Conversion with nested converts experiences random conversion errors具有嵌套转换的 SQL 日期时间转换遇到随机转换错误
【发布时间】:2015-06-03 18:11:38
【问题描述】:

如果有人有想法,请寻求有关奇怪问题的帮助:

我有一个 SQL,该语句大部分时间都在 T-SQL 脚本中工作,但偶尔会崩溃。我已识别出发生崩溃的数据,但无法识别有效数据行之间的任何差异。

此代码的目标是将时间添加到已经存在的日期时间值,该值具有 00:00:00 作为第二个时间列的时间(如下所述)。我的目标是将两列合并为 YYYY-MM-DD HH:MM:SS 格式,但我必须先将它们转换为 char 以修剪掉原来的 00:00:00。

LogDate - 仅包含 DateTime 格式的日期 (YYYY-MM-DD HH:MM:SS)

LogTime - 包含动作的时间,是 varchar 格式 (HH:MM)

SQL 转换

SELECT CONVERT(DATETIME, CONVERT(CHAR(8), LogDate, 112) + ' ' + CONVERT(CHAR(8), LogTime, 108))
                FROM  TestTable
                WHERE EventSerial = '100001'

但是,如果我将上述语句中的 EventSerial 更改为不同的行,例如“100002”,则该语句有效。

每一行的数据如下:

EventSerial 100001 的值: 记录日期:2015-04-02 00:00:00.000 记录时间:10:04

EventSerial 100002 的值: 记录日期:2015-04-02 00:00:00.000 记录时间:10:48

使用数据集 1 运行失败,使用数据集 2 运行会产生输出。此外,在没有最终日期时间转换的情况下运行代码,或者如果我手动运行带有字符串的代码,它可以工作(如下所述:)

SELECT CONVERT(CHAR(8), LogDate, 112) + ' ' + CONVERT(CHAR(8), LogTime, 108)
                FROM  TestTable
                WHERE EventSerial = '100001'


SELECT  CONVERT(DATETIME, '20150402 10:48')
SELECT  CONVERT(DATETIME, '20150402 10:04') 

任何建议,我确信我错过了一些愚蠢的东西(无论如何我可能花了很长时间解决这个问题。所需的输出将是 2015-04-02 10:04:00

【问题讨论】:

  • 您的数据一定有问题。 I can't reproduce the error. 如果您使用正确的数据类型,这将避免。
  • 完全同意,不幸的是,数据库数据类型和架构早在我来到这里之前就已经定义好了(很遗憾,无法更改)。感谢您尝试复制它,我很感激!
  • 尝试更新有问题的行中的 LogTime 的值,也许那里有一个隐藏字符导致了所有这些问题。

标签: sql-server date datetime time sql-convert


【解决方案1】:

首先,日期时间没有格式。 (why?)

其次,您不需要将datetime值转换为char来添加小时和分钟,只需使用DateAdd即可:

SELECT DATEADD(Minute, 
               CAST(RIGHT(LogTime, 2) as int), 
               DATEADD(Hour, 
                       CAST(LEFT(LogTime, 2) as int), 
                       LogDate
                   )
              )
FROM  TestTable
WHERE EventSerial = '100001'

另外,请注意convert 不包含yyyymmdd hh:mm 的样式

注意:代码是直接写在这里的,可能会有一些错误。

【讨论】:

    【解决方案2】:

    我不确定您为什么会收到错误消息...可能在您的 varchar 时间字段中存在一些看不见的字符...可能是制表符之类的?试试这个查询:

    SELECT ascii(substring(LogTime,1,1)) Char1, 
        ascii(substring(LogTime,2,1)) Char2,  
        ascii(substring(LogTime,3,1)) Char3,  
        ascii(substring(LogTime,4,1)) Char4,  
        ascii(substring(LogTime,5,1)) Char5
    FROM  TestTable
    WHERE EventSerial = '100001'
    

    它应该显示这些结果:

    Char1       Char2       Char3       Char4       Char5
    ----------- ----------- ----------- ----------- -----------
    49          48          58          48          52
    
    (1 row(s) affected)
    

    这样会更有效率:

    select dateadd(minute, datediff(minute,0, LogTime), LogDate)
    FROM  TestTable
    

    但这假设您的日期字段始终包含 00:00:00 时间信息。如果你想确保它也被剥离,你可以使用:

    select dateadd(minute, datediff(minute,0, LogTime), dateadd(day, datediff(day, 0, Logdate),0))
    FROM  TestTable
    

    【讨论】:

    • 有趣。我尝试了这两种方法,但我仍然收到具有相同变化的相同错误(EventSerial2 数据有效,EventSerial1 数据无效)。事实上,如果我以任何形式或方式混淆数据,常见的恶魔似乎是 LogTime 字段。但是,我在十六进制编辑器中检查了它,实际上是 10:04,我在上面做了一个 (LEN),我得到了 5 返回。
    • 是否有可能其中一个零是字母 O?
    • 双重检查,不幸的是,它们实际上是数字 0,而不是 O。好建议!
    • 神秘。尝试运行我添加到答案中的查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多