我正在使用SSIS将多个打包字段(十六进制值)写入大型机系统的平面文件。我发现写入0x00或NULL不写入NULL,写入0x20或空格。有没有办法用SSIS将NULL字符写入平面文件?谢谢!
这是我在OLE DB Source中使用的SQL,用于将NULL写入文件
SELECT CONVERT(VARCHAR, (0x00)) AS NullValue
答案 0 :(得分:4)
您提供的SQL是您的问题的一部分。字符串不能携带0x00,或者根据我对极其模糊的C回忆,至少库会忽略空字符之后的所有内容。我可以证明,如果你附加数据查看器,那么你' ll看到在OLEDB源和实际进入数据流之间,0x00值被转换为空字符串。我在源和目标之间删除了以下脚本任务
int charvalue = -1;
char[] rep = Row.AsciiNULL.ToCharArray();
if (rep.Length > 0)
{
charvalue = Convert.ToInt32(rep[0]);
}
Row.Information = string.Format("Length {0} 0x{1:X}", Row.AsciiNULL.Length, charvalue);
0xFFFFFFFF只是-1表示为十六进制。使用0作为哨兵值是没有意义的,这是我们真正关心的。
string / wstring的数据类型不会提供,因此在源查询中,您需要将其保留为
SELECT (0x00) AS AsciiNULL
当您删除强制转换为字符类型时,您很可能需要强制在源上刷新元数据。元数据现在应显示为长度为1的DT_BYTES,并使用与上面类似的脚本,长度现在为1,值为0.我们在数据流中有二进制数据流,问题解决了!
由于平面文件管理器不知道如何处理二进制列,因此庆祝活动可能是过早的 我生命的故事 。如果它只是坚持它在那里会很好,但我无法让它按原样拍摄。
我以为我可以通过在Flat File Connection Manager中将该列设置为二进制来使我的数据类型匹配
这感觉更接近答案,但上述错误仍会失败。
瑞士军刀时间。您可以使用脚本任务执行大部分操作,在这种情况下,我将不得不维护输出格式,因为CM没用。
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
string fileName;
System.IO.StreamWriter writer;
public override void PreExecute()
{
base.PreExecute();
// pull this from a variable or something clever
this.fileName = @"C:\ssisdata\so\buzzzzjay.txt";
writer = new System.IO.StreamWriter(System.IO.File.Open(this.fileName, System.IO.FileMode.Create));
}
public override void PostExecute()
{
base.PostExecute();
writer.Flush();
writer.Close();
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
// hooray, managing file formats is fun
// 1 2 3 4 5 6
// 5 5 4 2 3 1
// aaaaabbbbbccccddd000X_
// _ signifies 0x00
// if you have NULL values for input, this will become rather unpleasant
writer.Write(string.Format("{0}{1}{2}{3}{4}{5}", Row.column0.PadRight(5), Row.column1.PadRight(5), Row.column2.PadRight(4), Row.column3.PadRight(2), Row.column4.PadRight(3), Row.column5.PadRight(1)));
writer.Write((char)Row.AsciiNULL[0]);
// uncomment me to do away with the shenanigans of carrying binary values
//writer.Write((char)0);
}
}
您真正感兴趣的是代码将空值写出的部分。如果你想在整个转换过程中携带DT_BYTES
类型的列,要将其最终写入文件,你需要像writer.Write(char(0)Row.AsciiNULL[0]);
这样的东西,但老实说,没有必要像这样混淆它。您将知道每次ProcessInputRow方法触发时,您都需要将0x00附加到该行,因此只需使用writer.Write((char)0);
这将为您的数据流带来性能提升(至少与数据流中的null bytestring相比)。引擎处理二进制数据和LOB类型(varchar / nvarchar / varbinary(max))的方式是它将数据写入文件并通过数据流携带句柄,而不是像“普通”数据类型一样保留在内存中。文件写入比内存慢很多几个数量级,因此请避免在程序包中性能问题。
有一个followup question,其中上面的内容导致了额外的字符被写入。带走似乎是我应该使用write.Write((byte)0)
YMMV