为啥 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::CurrentDate
:10/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 变量没有将毫秒部分传递给查询?的主要内容,如果未能解决你的问题,请参考以下文章