我认为主要的问题是OLEDB源如何检测参数数据类型,我没有找到提到这一点的官方文档,但是您可以做一个小实验来看看:
尝试在OLEDB源中的SQL命令中写入以下查询:
SELECT ? as Column1
然后尝试分析查询,您将得到以下错误:
无法唯一推导“@p1”的参数类型;有两种可能是“sql_variant”和“xml”。
这意味着查询解析器试图找出这些参数的数据类型,它与您映射到它的变量数据类型无关。
然后尝试编写以下查询:
SELECT CAST(? AS INT) AS Column1
然后尝试解析查询,您将得到:
已成功分析SQL语句。
现在,让我们将这些实验应用于您的查询:
尝试
SELECT CAST(GETDATE() - ? AS DATE) as Column1
你会得到一个错误的值,然后尝试
SELECT CAST(GETDATE() - CAST(? AS INT) AS DATE) AS Column1
你会得到一个正确的值。
更新1-官方文件信息
来自以下内容
OLEDB Source - Documentation
:
参数映射到在运行时提供参数值的变量。这些变量通常是用户定义的变量,尽管您也可以使用集成服务提供的系统变量。如果使用用户定义的变量,请确保将数据类型设置为与映射参数引用的列的数据类型兼容的类型。
这意味着参数数据类型与变量数据类型无关。
更新2-使用SQL事件探查器的实验
作为实验,我创建了一个ssis包,它将数据从OLEDB源导出到记录集目标。数据源是以下查询的结果:
SELECT *
FROM dbo.DatabaseLog
WHERE PostTime < CAST(GETDATE() - ? as date)
以及参数
?
映射到类型为的变量
Int32
并且有价值
10
在执行包之前,我在SQL Server实例上启动了SQL事件探查器跟踪,在执行包之后,以下查询将记录到跟踪中:
exec [sys].sp_describe_undeclared_parameters N'SELECT *
FROM dbo.DatabaseLog
WHERE PostTime < CAST(GETDATE() -@P1 as date)'
declare @p1 int
set @p1=1
exec sp_prepare @p1 output,N'@P1 datetime',N'SELECT *
FROM dbo.DatabaseLog
WHERE PostTime < CAST(GETDATE() -@P1 as date)',1
select @p1
exec sp_execute 1,'1900-01-09 00:00:00'
exec sp_unprepare 1
第一个命令
exec [sys].sp_describe_undeclared_parameters
是为了描述参数类型,如果我们单独运行它,它将返回以下信息:
结果表明,参数数据类型被认为是
datetime
.
其他命令显示了一些奇怪的语句:
-
首先,价值
@P1
设置为
1
-
使用以下值执行最终查询
1900-01-09 00:00:00
讨论
在SQL Server数据库引擎中,基本日期时间值为
1900-01-01 00:00:00
可以通过执行以下查询来检索:
declare @dt datetime
set @dt = 0
Select @dt
另一方面,在SSIS中:
由年、月、日、小时、分钟、秒和小数秒组成的日期结构。分数秒的固定刻度为7位。
dt_date数据类型是使用8字节浮点数实现的。天以整数增量表示,
从1899年12月30日开始
午夜为时间零点。小时值表示为数字小数部分的绝对值。但是,浮点值不能代表所有实际值;因此,日期范围有限制,可以在dt_日期中显示。
另一方面,dt_dtimestamp由一个结构表示,该结构内部具有年、月、日、小时、分钟、秒和毫秒的各个字段。此数据类型对其可以显示的日期范围具有较大限制。
基于此,我认为ssis日期数据类型之间的datetime基值之间存在差异(
1899-12-30
)以及SQL Server日期时间(
1900-01-01
,这导致在执行隐式转换以评估参数值时两天内出现差异。
工具书类