为啥 SSIS 变量没有将毫秒部分传递给查询?

Posted

技术标签:

【中文标题】为啥 SSIS 变量没有将毫秒部分传递给查询?【英文标题】:Why is the SSIS variable not passing the milliseconds part into the query?为什么 SSIS 变量没有将毫秒部分传递给查询? 【发布时间】:2021-12-30 06:08:04 【问题描述】:

数据库设置:

CREATE TABLE [dbo].[LOG]
(
    [LOAD_DATE] [datetime] NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[PRODUCTS]
(
    [PRODUCT_ID] [int] NULL,
    [PRODUCT_NAME] [nchar](100) NULL,
    [DATE_MODIFIED] [datetime] NULL
) ON [PRIMARY]
GO

INSERT INTO [LOG] (LOAD_DATE)
VALUES (GETDATE())

SELECT * FROM [LOG]

SSIS:

执行 SQL 任务:

SELECT ?=MAX([Load_Date])
FROM [LOG]

任务有一个数据类型为DT_DBTIMESTAMP 的输出参数(比如Param1)。 SSIS 变量数据类型为DateTime

然后在随后的数据流任务(比如 TASK2)中,我有一个 OLE DB 源 SQL 命令文本:

SELECT * 
FROM CANDIDATE
WHERE CANDIDATE_TIMESTAMP>?

以上变量用作输入参数。

在 SQL 分析器中,我可以看到缺少毫秒。那么如果 SSIS 变量不存储毫秒部分呢?如何确保将毫秒部分传递到查询中?

【问题讨论】:

请注意:DateTime 不精确到毫秒级别。最佳精度为 3 毫秒。如果您需要更准确的数据类型,请使用DateTime2 SQL db 或 SSIS 级别的 datetime2? 两者。由于与 Sybase 的遗留兼容性,Sybase 本身试图与 UNIX 系统时钟节拍兼容,SQL Server 中的datetime 数据类型的分辨率为 1/300 秒。 但是ssis中没有datetime2 【参考方案1】:

这是一个 OLE DB 提供程序问题。

OLE DB 提供程序(在我的例子中:SQL Server Native Client 11) 将所有 DateTime 输入参数转换为 SQL Server 中的 DateTime2(0),即使您尝试使用强制数据类型转换函数,例如考虑 OLE DB 源中的以下 SQL 命令。

SELECT *
FROM Users
Where CreationDate > Cast(? as datetime2(3))

从下面的 SQL Profiler 屏幕截图中,您可以看到 OLE DB 提供程序如何强制参数使用 DateTime2(0) 数据类型。

将 DateTime 值从 OLE DB 数据类型转换为数据库引擎数据类型时,毫秒会被截断。 奇怪的是这两种数据类型都支持小数秒(毫秒)

如果您想了解更多关于 SSIS 中不同数据类型系统的信息,可以查看此答案中的“附加信息”部分。

更多解释

我将创建一个具有以下值的 SSIS DateTime 变量 User::CurrentDate10/10/2021 12:00:01.001

在 OLE DB Source 中,我将使用以下语句:

SELECT *
FROM Users
Where CreationDate > Cast(? as datetime)

然后,我将选择创建的变量作为输入参数。

现在如果我点击预览按钮,会抛出以下异常:

标题:Microsoft Visual Studio

显示预览时出错。

附加信息:

提供的时间值的小数部分溢出了 相应的 SQL Server 参数或列。增加 bScale in DBPARAMBINDINFO 或列标度来更正此错误。 (微软 SQL 服务器本机客户端 11.0)

如果我们点击“显示详细信息”按钮,异常堆栈跟踪显示错误是在System.Data.OleDb.OleDbDataReader 类上抛出的。这意味着 OLE DB 提供程序是导致问题的原因。

解决方法

您可以使用字符串数据类型将值存储在 SSIS 中,并使用 OLE DB 源 SQL 命令中的CONVERT() 函数将其转换为 SQL Server 数据库引擎中的DateTime

示例

执行 SQL 任务中使用以下 SQL 语句:

SELECT ? = CONVERT(VARCHAR(23), max([Load_Date]), 121) FROM [LOG]

并将结果存储在String 类型的输出参数中。然后,在 OLE DB 源 中使用以下 SQL 命令:

SELECT * 
FROM CANDIDATE
WHERE CANDIDATE_TIMESTAMP > CONVERT(DATETIME, ?, 121)

参考文献

SSIS 2012 : work around for missing milliseconds in SSIS datetime variable+ Solution for incremental load using datetime column

附加信息

SSIS 数据类型

为了更好地理解,SSIS 中使用的不同数据类型值得一提。集成服务中使用了多种数据类型系统:

    数据库引擎数据类型(SQL Server、Oracle 等) SSIS 变量数据类型 SSIS 管道缓冲区(数据流任务)数据类型 连接提供程序数据类型(OLE DB、ADO.NET、ODBC)

在 SSIS 中任何级别使用的每种数据类型都可能在另一个类中具有相应的数据类型。 “Matija Lah”where most of the data types mappings are provided, besides useful information 提供了一个很好的资源。

下表显示了SSIS不同级别的数据类型映射(查看我提到的文章以获得更多解释)

SQL Server SSIS Variables SSIS Pipeline Buffer OLE DB ADO.NET
bigint Int64 DT_I8 LARGE_INTEGER Int64
binary Object DT_BYTES n/a Binary
bit Boolean DT_BOOL VARIANT_BOOL Boolean
char String DT_STR VARCHAR StringFixedLength
date Object DT_DBDATE DBDATE Date
datetime DateTime DT_DBTIMESTAMP DATE DateTime
datetime2 Object DT_DBTIMESTAMP2 DBTIME2 DateTime2
datetimeoffset Object DT_DBTIMESTAMPOFFSET DBTIMESTAMPOFFSET DateTimeOffset
decimal Object (< SQL 2012) Decimal (>= SQL 2012) DT_NUMERIC NUMERIC Decimal
float Double DT_R8 FLOAT Double
image Object DT_IMAGE n/a Binary
int Int32 DT_I4 LONG Int32
money Object DT_CY (OLE DB) DT_NUMERIC (ADO.NET) CURRENCY Currency
nchar String DT_WSTR NVARCHAR StringFixedLength
ntext String DT_NTEXT n/a String
numeric Object (< SQL 2012) Decimal (>= SQL 2012) DT_NUMERIC NUMERIC Decimal
nvarchar String DT_WSTR NVARCHAR String
nvarchar(max) Object DT_NTEXT n/a n/a
real Single DT_R4 FLOAT, DOUBLE Single
rowversion Object DT_BYTES n/a Binary
smalldatetime DateTime DT_DBTIMESTAMP DATE DateTime
smallint Int16 DT_I2 SHORT Int16
smallmoney Object DT_CY (OLE DB) DT_NUMERIC (ADO.NET) CURRENCY Currency
sql_variant Object DT_WSTR (OLE DB) DT_NTEXT (ADO.NET) Object
table Object n/a
text Object DT_TEXT n/a n/a
time Object DT_DBTIME2 DBTIME2 Time
timestamp Object DT_BYTES n/a Binary
tinyint Byte DT_UI1 BYTE Byte
uniqueidentifier String (OLE DB) Object (ADO.NET) DT_GUID GUID Guid
varbinary Object DT_BYTES n/a Binary
varbinary(max) Object DT_IMAGE n/a Binary
varchar String DT_STR VARCHAR String
varchar(max) Object DT_TEXT n/a n/a
xml Object DT_NTEXT

带小数秒的日期时间(毫秒)

以下是存储毫秒的 DateTime 类型:

1。 SSIS 管道缓冲区数据类型

基于official documentation,在 SSIS 管道缓冲区级别,两种数据类型以小数秒存储日期和时间:

DT_DBTIMESTAMP:小数秒的最大刻度为 3 位。 HH:mm:ss.fff DT_DBTIMESTAMP2:小数秒的最大刻度为 3 位。 HH:mm:ss.fffffff

2。 SSIS 变量数据类型

在 SSIS 变量级别,DateTime 数据类型存储小数秒,最大刻度为 3 位 HH:mm:ss.fff

3。 SQL Server 数据类型

在 SQL Server 数据库引擎中,以下数据类型支持小数秒:

DateTime:小数秒的最大刻度为 3 位数。 HH:mm:ss.fff DateTime2:小数秒的最大刻度为 3 位数。 HH:mm:ss.fffffff

4。 OLE DB 连接提供程序

在 OLE DB 提供程序中,以下数据类型支持小数秒:

DBTIMESTAMP:小数秒的最大刻度为 3 位。 HH:mm:ss.fff DBTIME2:小数秒的最大刻度为 3 位。 HH:mm:ss.fffffff

【讨论】:

【参考方案2】:

如果您需要毫秒部分,您可以使用DT_DBTIMESTAMP2 数据类型。 IT 是映射到 SQL Server 中的Datetime2 数据类型的一种。 Besdies,请确保您在 SQL Server 表中使用DateTime2 数据类型而不是DateTime

查看以下帖子了解更多信息:DT_Date | DT_DBDate | DT_DBTime | DT_DBTime2 | DT_DBTimeStamp | DT_DBTImeStamp2

【讨论】:

DT_DBTIMESTAMP2 是 SSIS 变量数据类型吗? @variable 你应该使用它作为参数数据类型而不是DBTIMESTAMP。 SSIS 变量只有 .NET DateTime 数据类型。主要区别在于为参数指定的数据类型用于从 SQL Server 引擎获取数据,而在 SSIS 级别上,它存储在 DateTime 变量中。 我看不到DT_DBTIMESTAMP2 作为参数数据类型,你在哪里看到的?

以上是关于为啥 SSIS 变量没有将毫秒部分传递给查询?的主要内容,如果未能解决你的问题,请参考以下文章

SSIS - 如何将电源查询的输出导入数据流中的另一个电源查询

将模式名称作为变量传递给查询的最佳方法

Java - 为啥我不能部分输入变量?

将动态表传递给 SSIS 中的 ADO.NET 目标

在ssis包中的sp中传递参数问题

在 SSIS 包中将参数值传递给变量会导致运行时错误