【发布时间】:2016-09-14 15:18:35
【问题描述】:
我正在尝试将SmallDateTime 字段和Time 值(标量值函数的结果)组合成DateTime,但我不断收到以下错误:
从字符转换日期和/或时间时转换失败 字符串。
以下是贯穿始终的变量:
DECLARE @STARTDATETIME AS DATETIME
DECLARE @ENDDATETIME AS DATETIME
SELECT @STARTDATETIME = '8/29/2016 12:00:00'
SELECT @ENDDATETIME = '8/30/2016 12:00:00'
列定义:
FT_START_DATE SmallDateTime
FT_END_DATE SmallDateTime
FT_START_TIME Int
FT_END_TIME Int
日期字段不包含时间戳。时间字段基本上是 24 小时时间,没有冒号分隔符。 (例如:142350 = 14:23:50)
这是我的查询中调用的函数:
USE [PWIN171]
GO
/****** Object: UserDefinedFunction [dbo].[dbo.IPC_Convert_Time] Script Date: 9/13/2016 4:50:49 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[dbo.IPC_Convert_Time]
(
@time int
)
RETURNS time
AS
BEGIN
DECLARE @Result time
SELECT @Result = CONVERT(time
, STUFF(
STUFF(
RIGHT('000000' + CONVERT(varchar(6), @time), 6)
, 5, 0, ':')
, 3, 0, ':')
)
RETURN @Result
END
示例 1 - 失败:
这就是我所追求的。
SELECT * FROM FT WITH (NOLOCK)
WHERE
CAST(FT_END_DATE AS DATETIME) + DBO.[dbo.IPC_Convert_Time](FT_END_TIME) BETWEEN @STARTDATETIME AND @ENDDATETIME;
示例 2 - 作品:
这个运行,但它不会从 8/29 获取记录,因为结束日期将在 8/29 的 12:00:00 之前。
SELECT * FROM FT WITH (NOLOCK)
WHERE
FT_END_DATE BETWEEN @STARTDATETIME AND @ENDDATETIME
AND CAST(FT_END_DATE AS DATETIME) + DBO.[dbo.IPC_Convert_Time](FT_END_TIME) BETWEEN @STARTDATETIME AND @ENDDATETIME;
我想我可以做一个拆分参数并检查结束时间是否也在参数的时间部分之间的方法,但这似乎是朝着错误方向迈出的一步。该错误似乎仅在 where 子句中没有 FT_START_DATE 或 FT_END_DATE 的其他用法时出现。
时间转换功能在我创建的每个场景中都能正常工作。我什至尝试了示例 2,其参数可以使其与示例 1 涵盖的数据 100% 重叠,以防有错误数据导致错误,但它运行良好。
我也不知道错误发生的确切位置,因为它只引用 select 语句开始的行,而不是代码中的实际位置。
为什么会这样?
更新:
TIMEFROMPARTS 不可用,因为它在 SQL Server 2008 上
【问题讨论】:
-
没有第 29 个月。如果您必须使用日期文字,请使用未分隔的日期格式
20160829或完整的 ISO 8601 格式。此外,无论IPC_Convert_Time做什么,您都不需要字符串操作来创建time值。可能还有许多其他错误,例如,如果FT_END_DATE已经是日期类型,为什么还要转换它?为什么使用smalldatetime而不是date或datetime? -
@PanagiotisKanavos - 字段由供应商设置,无法更改。我转换为
datetime,因为如果我不这样做,+操作的最终结果也将是smalldatetime,因此将四舍五入。为什么我不需要字符串操作来从 int 列创建时间值? -
重点是您使用美国特定的日期字符串,这保证在美国以外的任何地方都失败。由于您没有提及 where 发生错误,因此这是可能失败的第一件事。字符串操作使您面临更多此类问题。使用 TIMEFROMPARTS 创建一个
time值,因为您已经拥有每个部分 -
这个问题的范围是在一个数据库内,在一家美国公司内,在一个时区内。虽然系统设计得不好,但它的一致性是无可挑剔的。
-
然而,它失败了。在不知道 where 的情况下,它要么是文字,要么是函数。为什么不把函数换成
TIMEFROMPARTS,去掉字符串呢?
标签: sql-server sql-server-2008