[英]SSIS OPENROWSET query flat file
我目前有一个名为 InvoiceFileName 的变量名,它通过 foreach 循环创建 .csv 文件。 然后将 .csv 列表输出到文件夹中。
然后我需要查询每个 .csv 文件以选择每个 .csv 的标题和第一行数据。 我相信我需要使用OPENROWSET
来查询 .csv。 我有2个问题。
OPENROWSET
。 下面是一个简单的OPENROWSET
,它只提供文件的标题。
SELECT
top 1 *
FROM OPENROWSET(BULK N'\\myservername\f$\reports\Invoices\CokeFiles\54ASBSd.csv', SINGLE_CLOB) AS Report
你对数据库有什么样的权限? 如果您拥有或可以获得稍微提升的权限,您可以使用BULK INSERT
和xp_cmdShell
来完成此操作,但就像@scsimon 所说的那样,您将不得不使用动态 sql。 这是一个快速示例:
-----------------------------------------------------------------------------------------------------
-- Set up your variables
-----------------------------------------------------------------------------------------------------
DECLARE
@folderPath AS VARCHAR(100) = '\\some\folder\path\here\',
@cmd AS VARCHAR(150), -- Will populate this with a command to get a list of files in a directory
@InvoiceFileName AS VARCHAR(100), -- Will be used in cursor loop
@targetTable AS VARCHAR(50) = 'SomeTable',
@fieldTerminator AS CHAR(1) = ',',
@rowTerminator AS CHAR(2) = '\n'
-----------------------------------------------------------------------------------------------------
-- Create a temp table to store the file names
-----------------------------------------------------------------------------------------------------
IF OBJECT_ID('tempdb..#FILE_LIST') IS NOT NULL
DROP TABLE #FILE_LIST
--
CREATE TABLE #FILE_LIST(FILE_NAME VARCHAR(255))
-----------------------------------------------------------------------------------------------------
-- Get a list of the files and store them in the temp table:
-- NOTE: this DOES require elevated permissions
-----------------------------------------------------------------------------------------------------
SET @cmd = 'dir "' + @folderPath + '" /b'
--
INSERT INTO #FILE_LIST(FILE_NAME)
EXEC Master..xp_cmdShell @cmd
--------------------------------------------------------------------------------
-- Here we remove any null values
--------------------------------------------------------------------------------
DELETE #FILE_LIST WHERE FILE_NAME IS NULL
-----------------------------------------------------------------------------------------------------
-- Set up our cursor and loop through the files
-----------------------------------------------------------------------------------------------------
DECLARE c1 CURSOR FOR SELECT FILE_NAME FROM #FILE_LIST
OPEN c1
FETCH NEXT FROM c1 INTO @InvoiceFileName
WHILE @@FETCH_STATUS <> -1
BEGIN -- Begin WHILE loop
BEGIN TRY
-- Bulk insert won't take a variable name, so dynamically generate the
-- SQL statement and execute it instead:
SET @sql = 'BULK INSERT ' + @targetTable + ' FROM ''' + @InvoiceFileName + ''' '
+ ' WITH (
FIELDTERMINATOR = ''' + @fieldTerminator + ''',
ROWTERMINATOR = ''' + @rowTerminator + ''',
FIRSTROW = 1,
LASTROW = 2
) '
EXEC (@sql)
END TRY
BEGIN CATCH
-- Handle errors here
END CATCH
-- Continue your loop
FETCH NEXT FROM c1 INTO @path,@filename
END -- End WHILE loop
-- Do what you need to do here with the data in your target table
一些免责声明:
BULK INSERT
和xp_cmdShell
。xp_cmdShell
使用xp_cmdShell
(并且有充分的理由),但这是一个快速而肮脏的解决方案,对您的环境做出了很多假设。为了通过 SSIS 执行此操作,理想情况下您可能需要使用格式文件进行批量操作,但您必须具有一致的格式文件并删除 SINGLE_CLOB 选项。 这样做的一个非常hacky和非理想的方法是做这样的事情:
假设您的文件包含以下数据:
Col1,Col2,Col3,Col4
Here's,The,First,Line
Here's,The,Second,Line
Here's,The,Third,Line
Here's,The,Fourth,Line
然后你基本上可以像这样解析数据:
SELECT SUBSTRING(OnlyColumn, 0, CHARINDEX(CHAR(10), OnlyColumn, CHARINDEX(CHAR(10), OnlyColumn, 0)+1) )
FROM OPENROWSET(BULK '\\location\of\myFile.csv', SINGLE_CLOB) AS Report (OnlyColumn)
你的结果是这样的:
Col1,Col2,Col3,Col4 Here's,The,First,Line
这显然取决于您的行尾是否一致,但是如果您希望结果在单列和单行中(就像使用 SINGLE_CLOB 选项的批量操作的行为一样),那应该可以满足您的需求。
您可以查看此 SO 帖子上的解决方案,了解有关如何将 SSIS 变量值作为参数传递给查询的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.