Ваш SQL является частью вашей проблемы. Строки не могут содержать 0x00, или, по крайней мере, библиотеки игнорировали все после нулевого символа в соответствии с моим чрезвычайно туманным воспоминанием о C. Что я могу доказать, так это то, что если вы подключите средство просмотра данных, вы обратите внимание, что между источником 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 в качестве часового значения не имело смысла, это то, что нас действительно волнует.
Как мне сохранить значение 0x00?
Тип данных string / wstring не будет использоваться, поэтому в исходном запросе вам просто нужно оставить его как
SELECT (0x00) AS AsciiNULL
Скорее всего, вам потребуется принудительно обновить метаданные в вашем источнике, когда вы удалите приведение к типу символа. Метаданные теперь должны отображаться как DT_BYTES с длиной 1 и с использованием сценария, аналогичного приведенному выше. Длина теперь равна 1, а значение равно 0. У нас есть двоичные данные, передаваемые в потоке данных, проблема решена!
Ошибка: преобразование данных не выполнено. Преобразование данных для столбца «AsciiNULL» вернуло значение состояния 4 и текст состояния «Текст был усечен или один или несколько символов не соответствовали целевой кодовой странице.»
Возможно, празднование было преждевременным история моей жизни , поскольку менеджер плоских файлов не знает, как обращаться с этим двоичным столбцом. Было бы хорошо, если бы он просто вставил туда 1028 *, но я не смог бы взять его как есть.
Я думал, что смогу сопоставить типы данных, установив этот столбец как двоичный в Диспетчере соединений с плоскими файлами
Это похоже на ответ, но все равно не удастся с вышеуказанной ошибкой.
Сценарий задачи
Швейцарский армейский нож. С заданием скрипта вы можете делать практически все что угодно, и в этом случае мне придется поддерживать выходной формат, поскольку КМ бесполезны.
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);
Это повысит производительность вашего потока данных (по крайней мере, по сравнению с нулевой байтовой строкой в вашем потоке данных). Механизм обрабатывает двоичные данные и типы больших объектов (varchar / nvarchar / varbinary (max)) в том, что он записывает эти данные в файлы и переносит дескриптор через поток данных, а не остается в памяти, как «нормальные» типы данных. Запись в файл на много порядков медленнее, чем в память, поэтому избегайте, если производительность влияет на ваши пакеты.
Редактировать
Был дополнительный вопрос , в котором из-за вышеизложенного были написаны дополнительные символы. Уберите, кажется, что я должен был использовать write.Write((byte)0)
YMMV