如何以编程方式获取SSIS包中的MS Access表列表?

Lok*_*i70 9 ms-access ssis foreach-loop-container

我继承了一个非常复杂的 MS Access数据库,我需要将其导入SQL.Access数据库中有几千个表,字段定义相同.我有一些SSIS的经验,导入一个表非常简单.

但是,我需要创建一个进程,我可以循环遍历几千个表名列表并导入每个表.我找到了这个语句,它将获取Access数据库中所有表名的列表:

SELECT Name FROM MSysObjects WHERE(((MSysObjects.Type)= 1)AND((Left([Name],4))<>"MSys"));

但是,我不确定如何使用它(脚本任务语法?).我想我会想这样做来填充"对象"类型的SSIS变量.这样,我可以使用ForEach循环遍历此表列表并执行导入.我怎样才能做到这一点?或者是否有更好的方法循环数据库中的每个表并执行相同的过程?

我非常感谢任何建议.谢谢!

小智 18

只要Access中的所有表具有相同的结构,您就可以实现将Access数据加载到SQL Server中的一种可能方法.这个例子将通过表圈的访问,即CountryStateProvince.此示例中的包将在SQL中创建这两个表(如果它们不存在),然后使用Access中的数据填充它们.

分步过程:

  1. 访问表CountryStateProvince显示在屏幕截图#1和#2中.

  2. 在SSIS包上,创建两个OLE DB连接以连接到SQL Server和Access,如屏幕截图#3所示.另外,创建3个变量,如屏幕截图#4所示.变量SelectQuery,TableName应由Access中的有效表指定.这是包的初始配置所必需的.在这种情况下,我选择了Country,它确实存在于Access中.

  3. 选择变量SelectQuery,然后按F4查看属性窗格.在"属性"窗格上,将属性设置EvaluateAsExpressTrue并将表达式粘贴"SELECT * FROM " + @[User::TableName]Expression属性中.此表达式将评估当前正在循环的表.参见截图#4

  4. 截图#5和#6显示了表dbo.Countrydbo.StateProvince没有在SQL Server中存在.

  5. 配置Control FlowSSIS包的选项卡,如屏幕截图#7所示.放置一个Script Task并将其连接到Foreach Loop container.在容器内,放置一个Execute SQL Task和一个Data Flow Task.

  6. 使用"脚本任务代码"部分下给出的代码替换脚本任务中的代码.此代码将循环Access模式,并将仅获取表名.然后将表名列表存储在package变量中AccessTables,然后由变量使用Foreach loop container.

  7. 在SQL Server数据库中,创建一个dbo.CreateTable使用SQL Scripts Section 下提供的脚本命名的存储过程.此存储过程将在SQL Server中创建一个表(如果它尚不存在).Make sure that you alter the table schema defined in the stored procedure according to your needs.

  8. 配置Foreach loop container如屏幕截图#8和#9所示.

  9. 配置执行SQL任务,如屏幕截图#10和#11所示.

  10. 此时我们无法配置数据流任务,因为SQL Server中不存在这些表.因此,我们将在此时执行包,以便在SQL Server中创建Access表结构.屏幕截图#12显示了示例包执行.屏幕截图#13显示表结构已在SQL Server中创建,但它们尚未填充数据.

  11. 现在,我们将配置Data Flow Task.放置数据流任务OLE DB SourceOLE DB Destination在其中.将OLE DB源连接到OLE DB目标.参见截图#14.

  12. 配置OLE DB Source如屏幕截图#15和#16所示.

  13. 配置OLE DB Destination如屏幕截图#17和#18所示.

  14. 屏幕截图#19显示了其中的示例包执行Data Flow Task.

  15. 屏幕截图#20显示SQL Server表现在填充了Access表中的数据.

此示例仅适用于具有相同结构但名称不同的表.如果另一个名为Employees的表添加到Access,只有列IdName.执行此示例包将在SQL Server中创建相同的表,并且还将使用数据填充它.

希望有所帮助.

SQL脚本:

CREATE PROCEDURE [dbo].[CreateTable]
(
    @TableName  VARCHAR(255)
)
AS
BEGIN

    SET NOCOUNT ON

    DECLARE @SQL VARCHAR(MAX)

    SET @SQL = 'IF NOT EXISTS ( SELECT  * 
                                FROM    sys.objects 
                                WHERE   object_id = OBJECT_ID(N''[dbo].' + @TableName + ''') 
                                AND     type in (N''U''))
                    CREATE TABLE [dbo].' + @TableName + '(
                        [ID] [int] NOT NULL,
                        [Name] [nvarchar](255) NULL
                        ) ON [PRIMARY]'

    EXEC (@SQL)
END
GO
Run Code Online (Sandbox Code Playgroud)

脚本任务代码:

只能使用的C#代码SSIS 2008 and above.

/*
   Microsoft SQL Server Integration Services Script Task
   Write scripts using Microsoft Visual C# 2008.
   The ScriptMain is the entry point class of the script.
*/

using System;
using System.Collections;
using System.Data;
using System.Data.OleDb;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;

namespace ST_9b2714c55db14556be74ca92f345c4e3.csproj
{
    [System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {

        #region VSTA generated code
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion

        public void Main()
        {
            Variables varCollection = null;
            DataTable schemaTables = null;
            ArrayList tableNames = new ArrayList();

            Dts.VariableDispenser.LockForWrite("User::AccessTables");
            Dts.VariableDispenser.GetVariables(ref varCollection);

            using (OleDbConnection connection = new OleDbConnection(Dts.Connections["AccessDB"].ConnectionString.ToString()))
            {
                string[] restrictions = new string[4];
                restrictions[3] = "Table";    
                connection.Open();
                schemaTables = connection.GetSchema("Tables", restrictions);
            }

            foreach (DataRow row in schemaTables.Rows)
            {
                foreach (DataColumn column in schemaTables.Columns)
                {
                    if (column.ColumnName.ToUpper() == "TABLE_NAME")
                    {
                        tableNames.Add(row[column].ToString());
                    }
                }
            }

            varCollection["User::AccessTables"].Value = tableNames;

            Dts.TaskResult = (int)ScriptResults.Success;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

截图#1:

1

截图#2:

2

截图#3:

3

截图#4:

4

截图#5:

五

截图#6:

6

截图#7:

7

截图#8:

8

截图#9:

9

截图#10:

10

截图#11:

11

截图#12:

12

截图#13:

13

截图#14:

14

截图#15:

15

截图#16:

16

截图#17:

17

截图#18:

18

截图#19:

19

截图#20:

20