我有一个遗留系统,它使用四个离散字段来捕获日期时间:一个用于日期(例如2015年10月23日),一个用于小时(例如10),一个用于分钟(例如,45) ),一个用于子午线(A或P)。
我正在尝试在MSSQL 2008 R2中构建一个标量函数,该函数将上面的所有字段作为参数,并返回使用所有提供的值创建的日期时间值。
这就是我到目前为止:
CREATE FUNCTION f_getTimeStamp (@date Date, @hour Varchar, @minute Varchar, @meridian Varchar)
RETURNS Datetime
AS
BEGIN
DECLARE @createdDateTime datetime
DECLARE @createdTime varchar
SELECT @createdTime = @hour + ':' + @minute +
CASE
WHEN @meridian = 'A' Then 'am'
WHEN @meridian = 'P' Then 'pm'
Else 'pm'
END
SET @createdDateTime = @date + CAST(@createdTime AS DATETIME)
RETURN @createdDateTime
END
我们的想法是获取创建时间所需的字段,并将它们组合成一个看起来像时间值的字符串,然后将其添加到现有的日期字段中。
我目前在查询中收到以下错误:
从字符串转换日期和/或时间时转换失败。
我应该注意,在使用此函数的查询中,我只发送非空值。
非常感谢任何帮助。
感谢。
答案 0 :(得分:1)
您的代码中只有一个点正在尝试从字符串转换日期/时间:
CAST(@createdTime AS DATETIME)
某些地方的值不会产生可转换的字符串。
您可以在ISDATE()
子句中使用时间构建逻辑和WHERE
找到有问题的值:
SELECT *
FROM YourTable
WHERE ISDATE(CAST(Hour AS VARCHAR(10)+':'+CAST(Minute AS VARCHAR(10)) = 0
'2:4am'
之类的内容会在没有问题的情况下投放到日期时间,因此您的格式本身并不存在问题。
解决此问题后,您应该遇到有关不兼容数据类型的其他错误,因为您无法添加DATE
和DATETIME
,因此您需要更改:< / p>
SET @createdDateTime = @date + CAST(@createdTime AS DATETIME)
要:
SET @createdDateTime = CAST(@date AS DATETIME) + CAST(@createdTime AS DATETIME)
答案 1 :(得分:0)
那里正在进行大量的类型转换。此表达式@date + CAST(@createdTime AS DATETIME)
很可能是给您错误的行。输出可能是`2012-01-01 00:00:002012-01-01 10:45:00&#39;
更好的方法是简单地将时间添加到原始日期。请注意,我更改了函数中的数据类型,以使类型转换不会发生在函数中。
CREATE FUNCTION f_getTimeStamp (@date Date, @hour INT, @minute INT, @meridian CHAR(1))
RETURNS Datetime
AS
BEGIN
DECLARE @TEMP DATETIME
SET @TEMP = @date
IF @hour < 12
SET @TEMP = DATEADD(HOUR, @date, @hour)
SET @TEMP = DATEADD(MINUTE, @date, @minute)
IF @meridian = 'P' AND @hour < 13 -- the hour must already be PM
SET @TEMP = DATEADD(HOUR, @date, 12)
RETURN @TEMP
END
注意:我没有在SQL Server中测试过这个。我可能在那里有一两个错字。但是,这个概念应该是合理的。
答案 2 :(得分:0)
我带来了这个解决方案。我认为使用DATEADD和DATEPART这样的内置函数可以解决这个问题。那是我用过的剧本:
<强> DATEADD:强>
返回具有指定数字间隔的指定日期(已签名) 整数)添加到该日期的指定日期部分。
<强> DATEPART:强>
返回一个表示指定datepart的整数 指定日期。
实际查询:
DECLARE @date DATETIME = '10/23/2015'
, @hour VARCHAR(20) = 10
, @minute VARCHAR(20) = 45
, @meridian VARCHAR(20) = 'P'
, @time DATETIME;
SELECT @time = @hour + ':' + @minute + CASE @meridian
WHEN 'A' THEN 'AM'
WHEN 'P' THEN 'PM'
ELSE 'PM'
END
SELECT DATEADD(MINUTE, DATEPART(MINUTE, @time), DATEADD(HOUR, DATEPART(HOUR, @time), @date));
我在Stack Exchange Data Explorer上构建了一个查询。它为我的场景带来了这个结果:
2015-10-23 22:45:00
它做什么?
P.S。始终为您的VARCHAR声明长度。
如果您没有定义长度,SQL Server将为您分配一个,和 它可能没有你想象的那么宽。在某些情况下,它将是1.