使用 SSIS 脚本任务将数据从多个 SQL 表导出到不同的平面文件

Posted

技术标签:

【中文标题】使用 SSIS 脚本任务将数据从多个 SQL 表导出到不同的平面文件【英文标题】:Exporting data from multiple SQL tables to different flat files using SSIS Script Task 【发布时间】:2011-09-07 04:08:06 【问题描述】:

我正在尝试使用 VB.NET 创建数据网格并将内容导出到文本文件,并且我在 SSIS 脚本任务中执行此操作,以便自动执行将动态表导出到文本文件的过程。我没有收到任何错误,并且文件已创建,但文件为空。

我在这段代码中做错了什么?

Public Sub Main()

    Dim FName As String = "D:\test.TXT"

    ''''''''''''''''''''''''''''''''''''''''''
    If File.Exists(FName) Then
        File.Delete(FName)
    End If
    ''''''''''''''''''''''''''''''''''''''''''

    Dim myConnection As OleDbConnection = New OleDbConnection("Data Source=localhost;Provider=SQLNCLI10;Initial Catalog=AdventureWorksDW2008R2;Integrated Security=SSPI;")
    Dim da As OleDbDataAdapter = New OleDbDataAdapter("Select * from Table")
    Dim ds As DataSet = New DataSet

    da.Fill(ds, "Test")

    Dim DataGrid1 As New DataGrid
    DataGrid1.DataSource = ds.DefaultViewManager
    Dim DataGridView1 As New DataGridView

    DataGridView1.DataSource = ds

    Dim dgvc As DataGridViewCell
    Dim sw As New System.IO.StreamWriter(FName)

    For Each dgvr As DataGridViewRow In DataGridView1.Rows

        Dim intCellCount As Integer = dgvr.Cells.Count
        Dim intCounter As Integer = 1

        For Each dgvc In dgvr.Cells()
            If intCounter <> intCellCount Then
                sw.Write(dgvc.Value.ToString & "|")
            Else
                sw.WriteLine(dgvc.Value.ToString)
            End If

            intCounter += 1
        Next
    Next

    Dts.TaskResult = ScriptResults.Success

End Sub

【问题讨论】:

【参考方案1】:

这是一种使用Script Task 将不同结构的表导出到平面文件的可能方法。此示例将使用脚本任务将包含不同字段和数据的两个表导出到平面文件。为了导出数据,您可以使用DataReader 而不是使用DataGrid。可能还有其他可能的方法来做到这一点。

分步过程:

    使用 SQL 脚本 部分中提供的脚本创建三个名为 dbo.TablesListdbo.Source1dbo.Source2 的表。 使用屏幕截图 #1 中显示的数据填充表 dbo.TablesListdbo.Source1 和 `dbo.Source2``。 在 SSIS 包的 Connection manager 上,创建一个名为 SQLServerOLE DB connection 以连接到 SQL Server 实例,如屏幕截图 #2 所示。 在包中,创建 4 个变量,如屏幕截图 #3 所示。 在控制流中,将Execute SQL TaskForeach Loop ContainerScript Task 放在Foreach loop container 中,如屏幕截图#4 所示。 如屏幕截图 #5 和 #6 所示配置Execute SQL task。 如屏幕截图 #7 和 #8 所示配置Foreach Loop container。 将脚本任务中的 Main 方法替换为 Script Task Code 部分中给出的代码。 屏幕截图 #9 显示了包的执行情况。 屏幕截图 #10 - #12 显示使用脚本任务代码从 SSIS 导出的文件。

希望对您有所帮助。

SQL 脚本:

CREATE TABLE [dbo].[Source1](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ItemNumber] [varchar](20) NOT NULL,
    [ItemName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Source1] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Source2](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Country] [varchar](20) NOT NULL,
    [StateProvince] [varchar](50) NOT NULL,
CONSTRAINT [PK_Source2] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[TablesList](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [TableName] [varchar](50) NOT NULL,
    [FilePath] [varchar](255) NOT NULL,
CONSTRAINT [PK_Tables] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

脚本任务代码:(使用下面给出的代码替换脚本任务中的 Main() 方法)

VBSSIS 2005 and above中可以使用的Main()方法代码:

Public Sub Main()

    Dim varCollection As Variables = Nothing

    Dts.VariableDispenser.LockForRead("User::TableName")
    Dts.VariableDispenser.LockForRead("User::FileName")
    Dts.VariableDispenser.LockForRead("User::Delimiter")
    Dts.VariableDispenser.GetVariables(varCollection)

    Dim fileName As String = varCollection("User::FileName").Value.ToString()
    Dim query As String = "SELECT * FROM " & varCollection("User::TableName").Value.ToString()
    Dim delimiter As String = varCollection("User::Delimiter").Value.ToString()

    Dim writer As StreamWriter = Nothing
    Dim connection As OleDbConnection = New OleDbConnection(Dts.Connections("SQLServer").ConnectionString)
    Dim command As OleDbCommand = Nothing
    Dim reader As OleDbDataReader = Nothing

    Try
        If File.Exists(fileName) Then
            File.Delete(fileName)
        End If

        connection.Open()
        command = New OleDbCommand(query, connection)
        reader = command.ExecuteReader()

        If reader.HasRows Then

            writer = New System.IO.StreamWriter(fileName)
            Dim row As Integer = 0
            While reader.Read()

                Dim header As Integer = 0
                Dim counter As Integer = 0
                Dim fieldCount As Integer = reader.FieldCount - 1

                If row = 0 Then
                    While header <= fieldCount
                        If header <> fieldCount Then
                            writer.Write(reader.GetName(header).ToString() & delimiter)
                        Else
                            writer.WriteLine(reader.GetName(header).ToString())
                        End If
                        header += 1
                    End While
                End If

                While counter <= fieldCount
                    If counter <> fieldCount Then
                        writer.Write(reader(counter).ToString() & delimiter)
                    Else
                        writer.WriteLine(reader(counter).ToString())
                    End If
                    counter += 1
                End While

                row += 1
            End While
        End If
    Catch ex As Exception
        Throw ex
    Finally
        connection.Close()
        writer.Close()
    End Try

    Dts.TaskResult = ScriptResults.Success

End Sub

屏幕截图 #1:

屏幕截图 #2:

截图#3:

屏幕截图 #4:

屏幕截图 #5:

屏幕截图 #6:

截图#7:

截图#8:

屏幕截图 #9:

屏幕截图 #10:

屏幕截图 #11:

屏幕截图 #12:

【讨论】:

嗨,感谢您的介入,我实际上是在将一个表列表拉入 foreachloop,因此不能使用平面文件目标,因为列不同并且不能使用 OLE 作为输入列不同,SSIS 不会即时执行此操作! – 这就是我使用上面代码的原因,为简单起见,我删除了变量并在查询中添加了一个表,以便人们可以进一步理解我的要求,但看起来我还不够清楚。但再次感谢 太好了,是的,工作正常,代码就是我想要的,非常感谢....上帝保佑分享知识 谢谢 siva,顺便说一句,我之前在玩 DataReader,但无法做对应的部分,还有我希望获得列名的 GRID,这就是我尝试它的原因. @Siva:我在你的回答中找不到截图。请尽快提供。 @Siva:即使我在 IE 9.0、Firefox 11.0、Google Chrome 浏览器中尝试过,我仍然无法看到任何屏幕截图。【参考方案2】:

为什么不使用 OLEDB 源组件,将表查询放在那里,然后将其输出到 SSIS 中的平面文件编写器,而不是使用脚本组件? This blog post 说明了如何做到这一点。

【讨论】:

嗨,感谢您的介入,我实际上是在将一个表列表拉入 foreachloop,因此不能使用平面文件目标,因为列不同并且不能使用 OLE 作为输入列不同,SSIS 不会即时执行此操作!

以上是关于使用 SSIS 脚本任务将数据从多个 SQL 表导出到不同的平面文件的主要内容,如果未能解决你的问题,请参考以下文章

从 SQL 代理运行时 SSIS 脚本任务失败

SSIS 包中的 C# 脚本在 SQL Server 表的数据执行过程中挂起,没有明确的错误消息

使用 SSIS 脚本任务刷新 Excel

SSIS - 使用 SSIS 将多个文件 .txt 读取到 SQL

查询值和目标字段的数量不同 - C# 脚本任务 SSIS - 使用动态列将 SQL Proc 的结果导出到 Excel

测量 SSIS 数据流的进度