SSIS脚本实现多行输出:预订与出勤数据拆分需求
SSIS异步脚本组件实现日期记录拆分(多行输出)
一、配置脚本组件为异步输出
- 在SSIS数据流任务中,拖入脚本组件,选择「转换」类型。
- 双击打开脚本编辑器,切换到「输入和输出」选项卡:
- 选中默认输出(如
Output0),在右侧属性面板找到SynchronousInputID,将其值改为None,开启异步输出模式(允许单输入行生成多输出行)。
- 选中默认输出(如
- 配置输入列:在「输入列」选项卡,勾选需要处理的字段(比如
BookingID、BookedDates、AttendedDates)。 - 配置输出列:在「输出列」选项卡,添加以下列:
BookingID:与原始表主键一致,用于关联记录Date:DateTime类型(或保持string类型,按需调整)Booked:Boolean类型,设置为允许为空Attended:Boolean类型,设置为允许为空
二、编写拆分逻辑代码(C#示例)
在脚本编辑器中选择C#作为脚本语言,替换ScriptMain.cs中的Input0_ProcessInputRow方法为以下代码:
using System; using System.Collections.Generic; using System.Linq; public class ScriptMain : UserComponent { public override void Input0_ProcessInputRow(Input0Buffer Row) { // 1. 解析预订日期,存入HashSet方便快速查找 HashSet<string> bookedDateSet = new HashSet<string>(); if (!Row.BookedDates_IsNull && !string.IsNullOrWhiteSpace(Row.BookedDates)) { foreach (string dateStr in Row.BookedDates.Split(';')) { var trimmedDate = dateStr.Trim(); if (!string.IsNullOrWhiteSpace(trimmedDate)) { bookedDateSet.Add(trimmedDate); } } } // 2. 解析出勤日期,存入字典(日期为键,出勤状态为值) Dictionary<string, bool> attendedDateDict = new Dictionary<string, bool>(); if (!Row.AttendedDates_IsNull && !string.IsNullOrWhiteSpace(Row.AttendedDates)) { foreach (string item in Row.AttendedDates.Split(';')) { var trimmedItem = item.Trim(); if (!string.IsNullOrWhiteSpace(trimmedItem) && trimmedItem.Length >= 9) { string dateStr = trimmedItem.Substring(0, 8); bool isAttended = trimmedItem.EndsWith("T", StringComparison.OrdinalIgnoreCase); if (!attendedDateDict.ContainsKey(dateStr)) { attendedDateDict.Add(dateStr, isAttended); } } } } // 3. 收集所有需处理的日期:预订日期 + 出勤日期(去重) HashSet<string> allDates = new HashSet<string>(bookedDateSet); foreach (var kvp in attendedDateDict) { allDates.Add(kvp.Key); } // 4. 遍历每个日期,生成输出行 foreach (string dateStr in allDates) { Output0Buffer.AddRow(); Output0Buffer.BookingID = Row.BookingID; // 转换日期格式(若使用DateTime类型) if (DateTime.TryParseExact(dateStr, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime date)) { Output0Buffer.Date = date; } else { Output0Buffer.Date_IsNull = true; } // 设置Booked字段:存在于预订日期则为true,否则设为null(或按需改为false) if (bookedDateSet.Contains(dateStr)) { Output0Buffer.Booked = true; } else { Output0Buffer.Booked_IsNull = true; } // 设置Attended字段:存在出勤记录则取对应状态,否则设为null if (attendedDateDict.TryGetValue(dateStr, out bool attendedStatus)) { Output0Buffer.Attended = attendedStatus; } else { Output0Buffer.Attended_IsNull = true; } } } }
三、关键细节说明
- 空值处理:代码中判断了
BookedDates和AttendedDates是否为空,避免空引用错误。 - 去重处理:用
HashSet存储日期,避免重复输出同一日期的记录。 - 逻辑调整:若需要将未预订的日期
Booked设为false,只需把Output0Buffer.Booked_IsNull = true改为Output0Buffer.Booked = false即可。
内容的提问来源于stack exchange,提问作者steve
相关产品推荐
相关产品推荐

