如何使用SSIS脚本任务将数据从多个存储过程写入文件?

时间:2011-08-17 16:02:01

标签: sql stored-procedures ssis

我在SQL Server 2008中创建了一个SSIS包,需要迭代一个包含ID的表,输出文件的位置,要执行的spname以及包含表中每个clientID的数据。存储过程输出不同的报告并包含不同的字段,这是自动化当前使用多个SSIS包进行客户报告的过程所需的,我希望简化整个过程。

我创建的包中包含一个SQL脚本组件,用于将数据保存到变量对象,'for each container'遍历对象变量并将数据保存到单个变量中。但是我需要脚本任务的帮助,因为我当前可以连接到oledb连接管理器,但是在尝试执行存储过程时脚本任务失败,可能因为数据不是通过视图或表输出的。

我是VB.NET脚本的新手,并且对VB.NET没有太多了解,我使用以下线程来获取当前位置并用

替换dbcommand
Dim query As String = "Exec " & Dts.Variables("User::RunSP").Value

我使用以下帖子来达到目前的位置:

Exporting data from multiple SQL tables to different flat files using SSIS Script Task

执行脚本任务时,它会在trydbconnection打开时失败。我已尝试对此进行评论并在没有try部分的情况下运行脚本任务,但它仍然出错。

1 个答案:

答案 0 :(得分:3)

由于您使用我提供的示例作为问题Exporting data from multiple SQL tables to different flat files using SSIS Script Task的答案,因此我采用了相同的示例并对其进行了修改以运行存储过程。

似乎没有任何问题。确保它与您尝试的操作相匹配。此示例使用SSIS 2005SQL Server 2008 R2数据库。

分步流程

创建三个表,即dbo.TablesList,dbo.Source1和dbo.Source2。使用一些示例数据填充表格。此外,创建两个名为dbo.SP1和dbo.SP2的存储过程。下面给出的脚本执行这些任务来创建表和存储过程。

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,
    [SPName] [varchar](50) NOT NULL,
    [FilePath] [varchar](255) NOT NULL,
CONSTRAINT [PK_Tables] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

INSERT INTO dbo.TablesList (FilePath, SPName) VALUES 
    ('F:\Temp\Item_Details.txt', 'SP1'),
    ('F:\Temp\Country_StateProvince.txt', 'SP2');
GO

INSERT INTO dbo.Source1 (ItemNumber, ItemName) VALUES 
    ('34534', 'Keyboard'),
    ('24312', 'Mouse'),
    ('78555', 'Monitor');
GO

CREATE PROCEDURE [dbo].[SP1]
AS
BEGIN   
    SET NOCOUNT ON;

    SELECT * FROM dbo.Source1
END
GO

CREATE PROCEDURE [dbo].[SP2]
AS
BEGIN   
    SET NOCOUNT ON;

    SELECT * FROM dbo.Source2
END
GO

表格中的数据如下图所示。

Sample data

在SSIS包上,为SQL Server实例创建连接管理器。

Connection manager

在SSIS包上,创建4个变量,即DelimiterFileNameRunSPSPsList。此外,在“控制流”选项卡上放置“执行SQL任务”,“Foreach循环”容器和“脚本”任务,如下面的屏幕截图所示。

Variables and Control Flow

配置执行SQL任务以获取存储过程列表,如以下两个屏幕截图所示。

Execute SQL Task General

Execute SQL Task Result Set

配置Foreach循环容器以循环存储在变量SPsList中的结果集,如以下两个屏幕截图所示。

Foreach Loop container Collection

Foreach Loop container Variable Mappings

在“脚本任务”的“脚本”部分中,单击“设计脚本...”按钮以启用VSTA编辑器。

Script Task

用下面给出的代码替换VB.NET代码。粘贴代码后,关闭VSTA编辑器以保存更改。

Imports System
Imports System.Data
Imports System.Data.OleDb
Imports System.IO
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime

Public Class ScriptMain

    Public Sub Main()

        Dim varCollection As Variables = Nothing

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

        Dim fileName As String = varCollection("User::FileName").Value.ToString()
        Dim query As String = "EXEC " & varCollection("User::RunSP").Value.ToString()
        Dim delimiter As String = varCollection("User::Delimiter").Value.ToString()

        Dim writer As StreamWriter = Nothing
        Dim connection As OleDbConnection = New OleDbConnection(Dts.Connections("Learn2008R2").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()

            writer = New System.IO.StreamWriter(fileName)

            Dim row As Integer = 0
            Dim header 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

            If reader.HasRows Then
                While reader.Read()
                    Dim counter As Integer = 0
                    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
                End While
            End If
        Catch ex As Exception
            Throw ex
        Finally
            connection.Close()
            writer.Close()
        End Try

        Dts.TaskResult = Dts.Results.Success

    End Sub

End Class

执行包之前文件夹F:\ Temp的内容。该文件夹为空。

F Temp empty

成功的包执行显示在下面的屏幕截图中。

Success

文件夹路径F:\ Temp现在包含使用各个存储过程SP1和SP2提供的数据由程序包内的脚本任务生成的两个文件。

F Temp with files

文件内容显示在以下屏幕截图中。文件内容以管道分隔,您可以注意到数据与早期屏幕截图中显示的表数据匹配。

File 1

File 2

希望有所帮助。