SSIS - сбой, если в какой-либо строке исходного набора данных отсутствуют значения? - PullRequest
2 голосов
/ 27 мая 2020

Допустим, у меня есть следующие данные:

FirstName | LastName | Age | Date Added to Database (derived column) 
John      | Doe      | 23  | dd/mm/yyyy
Jane      | Doe      | 31  | dd/mm/yyyy
Bob       |          | 40  | dd/mm/yyyy
Janet     | Smith    |     | dd/mm/yyyy

И я хотел бы перенести их из источника Excel / Flat File на Sql Server. Однако я бы хотел, чтобы задача полностью завершилась неудачей, если любая строка в исходном наборе данных не имеет значения. До сих пор я видел учебники, в которых мы можем сделать что-то вроде этого:

enter image description here

Где записи с нулевыми значениями разделяются, если они содержат нулевые значения. Однако я не хочу вообще вставлять ЛЮБЫЕ значения, если какое-либо из значений является нулевым, скорее я хотел бы сделать что-то вроде отправки электронного письма при сбое, уведомляющего об отсутствии значений.

Возможно ли это в SSIS? Можно ли это сделать с помощью промежуточной таблицы и т. Д. c?

Ответы [ 3 ]

4 голосов
/ 27 мая 2020

Ничто из коробки напрямую не поддерживает этот сценарий, но я могу придумать несколько подходов, которые вы можете совместить, чтобы выполнить свой запрос.

Самый чистый / простой в реализации - это просто поместить все ваши данные в промежуточную таблицу, и, поскольку я ленив, я бы добавил вычисляемый столбец в определение таблицы, который помечает строку как имеющую где-то значение NULL.

ALTER TABLE dbo.stageData 
ADD HasNull AS (CASE WHEN Col1 IS NULL OR Col2 IS NULL THEN 'Y' ELSE 'N');

Затем вы должны добавить две задачи «Выполнить SQL» после потока данных. Первый отправляет электронное письмо (при условии, что у вас настроен msdb.dbo.sp_send_dbmail) Я бы сделал что-нибудь

IF EXISTS (SELECT * FROM dbo.StageData AS SD WHERE SD.HasNull = 'Y')
BEGIN
    EXECUTE msdb.dbo.sp_send_db_mail @recipient = 'ocean800', @subject = 'Null detected';
END 

Я бы тогда получил задачу Execute SQL, которая привязывает данные со сцены к финальной стол. Дважды проверьте мой лог c здесь, так как я его не закодировал. Может потребоваться ЛЮБОЙ или просто повторить logi отправки почты c и добавить вставку в качестве предложения ELSE. Черт, это могло бы быть проще ...

INSERT INTO dbo.Final SELECT * FROM dbo.StageData AS SD WHERE NOT EXISTS (SELECT * FROM dbo.StageData AS SDI SDI.HasNull ='Y');

Подход без таблицы этапов заключался бы в двойной обработке вашего файла. Первым потоком данных будет источник плоского файла для условного разделения, а затем ... что угодно на самом деле. Я бы go просто использовал преобразование Row Count, которое заполнит созданную вами переменную SSIS с именем RowsNull. После запуска потока данных у вас будет значение ноль (готово к загрузке) или больше нуля - отправьте электронное письмо.

Раздвоение задачи потока данных в задачу потока данных, которая фактически сохраняется в нашей таблице и уведомлении (Отправить задачу по электронной почте, выполнить SQL задачу по отправке электронной почты, что угодно). Хитрость здесь заключается в том, чтобы изменить прецедентное ограничение между родительской задачей (поток данных) и дочерними путями. Вы установите для него Expression and Constraint. Ограничение остается успешным, а ограничения следующие: @ [User :: RowsNull] == 0 и @ [User :: RowsNull]> 0

Другими менее удачными методами может быть указание того, что назначение OLE DB сохраняет настройки по умолчанию ( Строки в пакете пустые, а максимальный размер фиксации вставки равен max int). Этот параметр представляет собой фиксацию всего или ничего - вам просто нужно что-то, чтобы взорвать неявную транзакцию, поэтому в вашем условном разделении для пути HasNull перенаправьте строки в задачу сценария, которая вызвать событие ошибки. Это убьет груз. Или определите свою целевую таблицу со спецификатором NOT NULL для этих столбцов, и тогда данные будут загружаться или нет, и вам просто нужно добавить задачу электронной почты по вашему выбору в ограничение прецедента Failure потока данных, чтобы уведомить, когда загрузка не удалась.

3 голосов
/ 27 мая 2020

Вы определенно можете использовать промежуточную таблицу в качестве промежуточной точки в потоке данных, а затем проверить все логические c, необходимые в SQL, прежде чем перемещать его дальше. Этот подход довольно прост и имеет дополнительное преимущество, заключающееся в том, что всякий раз, когда ваш процесс выходит из строя, ваша промежуточная таблица будет содержать все данные из последнего файла, так что исследовать ее будет проще. хуже с точки зрения производительности и / или требуемых ресурсов и обычно не используются. Например, теоретически можно загрузить данные файла через источник задачи сценария в набор записей ADO в памяти , проверяя значения в сценарии по мере их отправки на выход буфер и генерирование исключения, если с данными что-то не так. Если этот поток данных не дает сбоя, то на следующем шаге данные из этого набора записей могут быть загружены в реальную таблицу.

(Заявление об отказе от ответственности: вышеупомянутая альтернатива настолько неудобна и неэффективна, что ее никогда нельзя рассматривать как жизнеспособный подход. . Я не знаю, с чего начать описывать его недостатки. Лично я мог бы подумать о чем-то вроде этого только в том случае, если моя реальная цель - «все испортить, насколько это возможно, не давая своему работодателю формального повода для войны», чего я никогда не делал. делать.)

1 голос
/ 27 мая 2020

Это можно сделать с помощью промежуточной таблицы. Для ваших образцов данных вы должны использовать DDL ниже.

Хитрость заключается в том, чтобы иметь ограничение NOT NULL для каждого столбца. Дополнительную информацию об ограничении можно найти в этом сообщении в блоге на SQLShack .

Когда SSIS пытается вставить значение NULL, это не удастся. Не самое элегантное решение, но делает то, что вы просите, без особых затрат.

CREATE TABLE Staging
(
    FirstName VARCHAR(50) NOT NULL
    , LastName VARCHAR(50) NOT NULL
    , Age INT NOT NULL
    , DateAdded DATETIME NOT NULL
)
...