使用时间转换处理错误

时间:2015-08-17 22:54:14

标签: sql sql-server datetime

我正在使用以下内容来处理我认为用户可以在数据输入表单中键入的多种时间格式(其中代码库在字段验证或强制时间格式中非常有限)。从本质上讲,它是一个自由文本字段,我们“希望”人们阅读鼠标悬停提示“请输入时间如上午8:00”。然后将数据激发到SQL。经过足够长的时间,我知道人们会阅读并以“上午8:00”以外的其他格式输入时间。为了解决这个问题,并且缺乏强制前端验证格式的能力,我在SQL触发器中实现了以下功能,当前端发布到SQL表的结果时处理各种时间格式:

TIME_START = CASE
            --Time Format like 0800 or 1030 or 2230
            WHEN p.TIME_START LIKE '[0-9][0-9][0-9][0-9]' THEN CONVERT(time, LEFT(p.TIME_START,2) + ':' + RIGHT(p.TIME_START,2) + ':00', 108)
            --Time Format like 800 or 930
            WHEN p.TIME_START LIKE '[0-9][0-9][0-9]' THEN CONVERT(time, '0' + LEFT(p.TIME_START,1) + ':' + RIGHT(p.TIME_START,2) + ':00', 108)
            --Time Format like 08:30 or 22:30
            WHEN p.TIME_START LIKE '[0-9][0-9]:[0-9][0-9]' OR p.TIME_START LIKE '[0-9][0-9]:[0-9][0-9]' THEN CONVERT(time, p.TIME_START, 109)
            --Time Format like 8:30 or 9:35
            WHEN p.TIME_START LIKE '[0-9]:[0-9][0-9]' OR p.TIME_START LIKE '[0-9]:[0-9][0-9]' THEN CONVERT(time, p.TIME_START, 108)
            -- Time Format like 08:30 AM or 12:30 PM
            WHEN p.TIME_START LIKE '[0-9][0-9]:[0-9][0-9] AM' OR p.TIME_START LIKE '[0-9][0-9]:[0-9][0-9] PM' THEN                 CONVERT(time, p.TIME_START, 0)
            --Time Format like 8:30 AM or 7:45 PM
            WHEN p.TIME_START LIKE '[0-9]:[0-9][0-9] AM' OR p.TIME_START LIKE '[0-9]:[0-9][0-9] PM' THEN CONVERT(time, p.TIME_START, 0)
            --Time Format like 08:30:00 AM or 21:45:00 PM
            WHEN p.TIME_START LIKE '[0-9][0-9]:[0-9][0-9]:[0-9][0-9] AM' OR p.TIME_START LIKE '[0-9][0-9]:[0-9][0-9]:[0-9][0-9] PM' THEN CONVERT(time, p.TIME_START, 0)
            --Time Format like 8:30:00 AM or 7:45:00 PM
            WHEN p.TIME_START LIKE '[0-9]:[0-9][0-9]:[0-9][0-9] AM' OR p.TIME_START LIKE '[0-9]:[0-9][0-9]:[0-9][0-9] PM' THEN CONVERT(time, p.TIME_START, 0)
            END

哪个效果很好。如果我得到“0800”或“8:00 AM”或“08:00 AM”等等,SQL将始终发布“08:00:00.0000000”(我们希望并需要时间(n)格式来做一些数学运算按时)。

问题是,我似乎无法绕过一些错误处理,如果有人输入的时间不符合这些格式之一,就会向TIME_START发布默认的虚拟值,例如“2930” “或”19:00 AM“,甚至”6 O'Clock“或”Six O'Clock At Night“。目前,SQL只会在发生这种情况时抛出错误。如前所述,将错误处理放在前端代码中不是一个选项(API只支持DATETIME,从来没有真正打算支持“表单生成器”中的仅限时间字段,你很想知道,这是Esri“Web应用程序生成器”)。我只想在时间超出格式的时候得到一个虚拟值,例如“00:00:00.00000”,这样就可以让我们用“00:00:00.00000”查看所有行然后回头看看在数据输入日志中并尝试翻译他们打算输入的内容,或者跟进用户并询问他们真正意味着什么时间,这种情况我希望在5%的时间内发生。希望这是有道理的。

1 个答案:

答案 0 :(得分:0)

啊,服务器端用户输入验证......我感到很痛苦。 :)

对于您的错误案例,您需要做的就是将ELSE指定为CASE语句的一部分。但是,我看到了LIKE语句中可能出现的一些改进。例如,第一种情况将匹配'9999''2468',这两种情况都是无效的。

我有点累了,并且没有能够针对所有情况对此进行测试,但以下情况应该有效:

/*
-- This section provided to give the query context
CREATE TABLE ##TimeTable (
  TIME_START VARCHAR(64) NOT NULL
  );


INSERT INTO ##TimeTable (TIME_START) VALUES('19:00 AM');
INSERT INTO ##TimeTable (TIME_START) VALUES('2930');
INSERT INTO ##TimeTable (TIME_START) VALUES('1930');
*/

SELECT
        CASE
            --Time Format like 0800 or 1030 or 2230
            WHEN p.TIME_START LIKE '[0-1][0-9][0-5][0-9]' 
                OR p.TIME_START LIKE '2[0-3][0-5][0-9]' 
                THEN CONVERT(time, LEFT(p.TIME_START,2) + ':' + RIGHT(p.TIME_START,2) + ':00', 108)
            --Time Format like 800 or 930
            WHEN p.TIME_START LIKE '[0-9][0-5][0-9]' THEN CONVERT(time, '0' + LEFT(p.TIME_START,1) + ':' + RIGHT(p.TIME_START,2) + ':00', 108)
            --Time Format like 08:30 or 22:30
            WHEN p.TIME_START LIKE '[0-1][0-9]:[0-5][0-9]' 
                OR p.TIME_START LIKE '2[0-3]:[0-5][0-9]' 
                THEN CONVERT(time, p.TIME_START, 109)
            --Time Format like 8:30 or 9:35
            WHEN p.TIME_START LIKE '[0-9]:[0-5][0-9]' 
                OR p.TIME_START LIKE '[0-9]:[0-5][0-9]' 
                THEN CONVERT(time, p.TIME_START, 108)
            -- Time Format like 08:30 AM or 12:30 PM
            WHEN p.TIME_START LIKE '0[0-9]:[5-9][0-9] [AP]M' 
                OR p.TIME_START LIKE '1[0-2]:[5-9][0-9] [AP]M' 
                THEN CONVERT(time, p.TIME_START, 0)
            --Time Format like 8:30 AM or 7:45 PM
            WHEN p.TIME_START LIKE '[0-9]:[0-5][0-9] [AP]M' 
                THEN CONVERT(time, p.TIME_START, 0)
            --Time Format like 08:30:00 or 21:45:00
            WHEN p.TIME_START LIKE '[0-1][0-9]:[0-5][0-9]:[0-5][0-9]' 
                OR p.TIME_START LIKE '2[0-3]:[0-5][0-9]:[0-5][0-9]' 
                THEN CONVERT(time, p.TIME_START, 0)
            --Time Format like 08:30:00 AM or 09:45:00 PM
            WHEN p.TIME_START LIKE '0[0-9]:[0-5][0-9]:[0-5][0-9] [AP]M' 
                OR p.TIME_START LIKE '1[0-2]:[0-5][0-9]:[0-5][0-9] [AP]M' 
                THEN CONVERT(time, p.TIME_START, 0)
            --Time Format like 8:30:00 AM or 7:45:00 PM
            WHEN p.TIME_START LIKE '[0-9]:[0-5][0-9]:[0-5][0-9] [AP]M' 
                THEN CONVERT(time, p.TIME_START, 0)
            ELSE CAST('06:00' AS TIME)
        END
FROM ##TimeTable AS p;