在SSIS中限制输出平面文件大小

时间:2013-02-27 12:43:44

标签: sql-server ssis

我正在使用Flat File Destination将我的数据导出到Text文件。我需要将输出文件大小限制为1 MB。有可能吗?

3 个答案:

答案 0 :(得分:0)

如果数据超出文件大小,您必须决定要省略哪些数据。只有您或您的客户才能做出决定。

然后编写查询以仅返回所需的数据。

答案 1 :(得分:0)

一些想法:

使用脚本转换,您将拥有生成的类,其中包含逻辑的“获取下一行”方法 - 在该类上添加一个计数器,并在每一行上计算出行的数据大小并将其添加到柜台。如果计数器的行数超过1mb,则不要将该行放入输出缓冲区。

在控制流上使用脚本组件,调用.Net IO方法读取文件的1mb并仅写回(这意味着你要创建一个大文件然后缩小它)。

真的,SSIS不会做这些事情。如果是我的话,我会选择“SELECT TOP X”方法。

答案 2 :(得分:0)

在SSIS中没有任何开箱即用的功能;但是,对脚本转换进行编码相对简单,脚本转换可以充当数据流目标,并且会限制其输出文件的大小。根据需要添加一些代码来创建多个文件(每个小于指定大小)并存储所有结果数据并不困难。

例如,假设您的源查询是

SELECT 
    TABLE_CATALOG,
    TABLE_SCHEMA,
    TABLE_NAME,
    COLUMN_NAME,
    ORDINAL_POSITION,
    COLUMN_DEFAULT,
    IS_NULLABLE,
    DATA_TYPE,
    CHARACTER_MAXIMUM_LENGTH 
FROM INFORMATION_SCHEMA.COLUMNS

并且您尝试将其写入一个或多个CSV文件,而不会超出每个文件的特定大小。

定义三个包级变量,如下所示:

  • User :: TargetFolder(String包含您要写入的文件夹名称)
  • User :: TargetFileNamePattern(String,其中包含输出文件的命名模式;例如SampleOutput{0}.csv
  • User :: MaxFileLength(Int32包含每个文件的最大字符数)

像这样创建数据流:

data flow screenshot

然后编写脚本转换代码:

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

using System;
using System.Data;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    private int _fileCounter;
    private int _bytesWritten;
    private TextWriter _tw;

    private TextWriter CurrentWriter
    {
        get
        {
            if (_tw == null)
            {
                string fileName = String.Format(this.Variables.TargetFileNamePattern, _fileCounter);
                string filePath = Path.Combine(this.Variables.TargetFolder, fileName);
                _tw = File.CreateText(filePath);
            }
            return _tw;
        }
    }

    public override void PreExecute()
    {
        base.PreExecute();
        _fileCounter = 1;
        _bytesWritten = 0;
        _tw = null;
    }

    public override void PostExecute()
    {
        base.PostExecute();
        if (_tw != null)
        {
            _tw.Flush();
            _tw.Close();
        }
    }

    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        string thisLine = String.Format(
                "{0},{1},{2},{3},{4},{5},{6},{7},{8}",
                Row.TABLECATALOG,
                Row.TABLESCHEMA,
                Row.TABLENAME,
                Row.COLUMNNAME,
                Row.ORDINALPOSITION,
                Row.COLUMNDEFAULT_IsNull ? "NULL" : Row.COLUMNDEFAULT,
                Row.ISNULLABLE,
                Row.DATATYPE,
                Row.CHARACTERMAXIMUMLENGTH_IsNull ? "NULL" : Row.CHARACTERMAXIMUMLENGTH.ToString());
        if (_bytesWritten + thisLine.Length > this.Variables.MaxFileLength) 
        {
            _tw.Flush();
            _tw.Close();
            _tw = null;
            _fileCounter += 1;
            _bytesWritten = 0;
        }
        this.CurrentWriter.WriteLine(thisLine);
        _bytesWritten += thisLine.Length;
    }
}

对于源查询中的每一行,这将构建要写入的字符串,然后检查是否将该字符串添加到当前TextWriter会导致文件太大。如果是这种情况,则将当前文件刷新到磁盘并关闭;下一次调用this.CurrentWriter将按顺序为下一个文件创建一个新的TextWriter对象。