使用 SSIS 加载列数不断变化的 Excel 文件

问题描述 投票:0回答:1

我需要使用 SSIS 加载 Excel 文件,其格式与此类似:

EmpID 2024年8月 2024年9月
12 100 350

并将其取消旋转,如下所示:

EmpID 日期 价值
12 2024年8月 100
12 2024年9月 350

总列数会不断变化。该数字可能会增加以同时保留时间段 11.2024-12.2026,但范围可能会更改为 09.2025-12.2026。我无法控制这些更改,我想找到一个自动化的解决方案,而不是使用新的文件格式手动更改解决方案。

是否可以在 SSIS 中逆透视时加载此类 Excel 文件?

我不太熟悉 SSIS 功能,也不熟悉 C#(如果可以通过脚本组件实现的话)。

我知道如何进行旋转本身,我的问题与如何通过不断变化的标题来做到这一点有关。我已经读过有关导入不带标头的文件并稍后将它们映射到数据库中的信息,但标头名称不可预测,因此我无法走这条路。

sql-server excel ssis etl
1个回答
0
投票

我不知道SSIS能做什么,但我相信T-SQL可以实现。

根据这个问题的答案,看来您可以使用

SELECT * INTO #ExcelStaging FROM OPOPENROWSET(...)
将Excel数据导入到临时表中,而无需提前知道列。然后,您可以查询结果表模式以提取感兴趣的列名称,以便您可以构建并执行动态 SQL 来执行
UNPIVOT
将导入的数据转换为所需的最终形式。

初始导入应该能够使用如下命令:

SELECT *
INTO #ExcelStaging
FROM OPENROWSET(
    'Microsoft.ACE.OLEDB.12.0',
    'Excel 12.0;Database=C:\Path\Name.xlsx;HDR=YES',
    'SELECT * FROM [Sheet1$]'
)

但是,如果您需要使用变量或参数中包含的文件路径,我相信您需要使用动态 SQL(因为

OPENROWSET
似乎不接受表达式)。 比如:

DECLARE @FilePath NVARCHAR(MAX) = N'C:\Path\FileName.xlsx'
DECLARE @ImportSql = N'
    SELECT *
    INTO #ExcelStaging
    FROM OPENROWSET(
        ''Microsoft.ACE.OLEDB.12.0'',
        N''Excel 12.0;Database=' + REPLACE(@FilePath, '''', '''''') + N';HDR=YES'',
        ''SELECT * FROM [Sheet1$]''
    )
'
PRINT @ImportSql
EXEC (@ImportSql)

上面的

REPLACE(..., '''', '''''')
处理可能包含撇号的文件路径值。

从那里,您可以查询导入的列并执行取消透视操作,如下所示:

-- Get list of column names like "MM.YYYY" and convert to
-- a list of the form "[MM.YYYY], [MM.YYYY], [MM.YYYY]"
DECLARE @DynamicColumnList NVARCHAR(MAX) = (
    SELECT STRING_AGG(CAST(QUOTENAME(name) AS NVARCHAR(MAX)), ', ')
    FROM tempdb.sys.columns
    WHERE object_id = OBJECT_ID('tempdb..#ExcelStaging')
    AND name LIKE '[0-9][0-9].[0-9][0-9][0-9][0-9]' -- Names like "MM.YYYY"
)

-- Dynamic SQL to select, unpivot, and insert the imported data into the target table
DECLARE @UnpivotSql NVARCHAR(MAX) = '
    INSERT INTO ImportResults (EmpId, Date, Value)
    SELECT U.EmpId, U.Date, U.Value
    FROM (
        SELECT EmpID, ' + @DynamicColumnList + '
        FROM #ExcelStaging
    ) E
    UNPIVOT (
        Value
        FOR Date IN (' + @DynamicColumnList + ')
    ) U
'

-- Execute
PRINT @UnpivotSql 
EXEC (@UnpivotSql )

  -- Show results
SELECT *
FROM ImportResults
ORDER BY EmpId, Date

对于表格的导入数据:

EmpID 垃圾 2024年8月 2024年9月 2024年10月
12 X 100 350 400
13 30 40 50

以上将产生以下结果:

EmpID 日期 价值
12 2024年8月 100
12 2024年9月 350
12 2024年10月 400
13 2024年8月 30
13 2024年9月 40
13 2024年10月 50

请参阅 this db<>fiddle 以获取此过程的部分演示。 fiddle 环境不允许导入实际的 Excel 文件。

我将把它留给您以及其他一些有帮助的贡献者来处理将其适应 SSIS 包的细节。 (正如我之前提到的,我没有这方面的专业知识。)

我欢迎对这篇文章进行任何更正或其他改进。随意直接编辑。

© www.soinside.com 2019 - 2024. All rights reserved.