PL/SQL中如何实现列转行并按指定格式完成数据插入
PL/SQL宽表转窄表列转行插入实现
核心逻辑
将源表中每个TDC_NO对应的两组极值字段拆分为2行记录,分别映射C、MN两个元素的上下限,写入目标窄表。
字段提示:
min、max为SQL标准内置聚合函数关键字,不建议直接作为表字段名使用,以下示例统一使用min_val、max_val指代目标表的极值字段。如果你的目标表已固定使用min/max作为字段名,写入时需要用双引号包裹字段名做转义,即写成"min"、"max"。
假设源表名为source_tdc,包含字段TDC_NO、C_MIN、C_MAX、MN_MIN、MN_MAX;目标窄表名为target_tdc,包含字段tdc_no、element、min_val、max_val,可选择以下任意一种方案实现。
方案1:UNION ALL 通用写法(全Oracle版本兼容)
无版本限制,逻辑直观易维护,生产环境兼容性最好,通过两次查询源表分别拼接两类元素的数据,用UNION ALL合并结果集直接插入:
INSERT INTO target_tdc (tdc_no, element, min_val, max_val) -- 映射C元素数据 SELECT tdc_no, 'C' element, c_min min_val, c_max max_val FROM source_tdc UNION ALL -- 映射MN元素数据 SELECT tdc_no, 'MN' element, mn_min min_val, mn_max max_val FROM source_tdc;
注意这里必须用UNION ALL而非UNION,避免不必要的去重排序开销,两类元素的固定取值不存在重复记录,不需要去重。正式插入前可以单独执行SELECT部分的语句,核对转换结果是否符合预期再执行写入。
方案2:CROSS APPLY 行值构造写法(Oracle 12c及以上版本支持)
12cR1及以上版本支持行值构造语法,仅需单次扫描源表即可完成行拆分,大表场景下性能优于UNION ALL写法,代码更简洁:
INSERT INTO target_tdc (tdc_no, element, min_val, max_val) SELECT s.tdc_no, v.element, v.min_val, v.max_val FROM source_tdc s CROSS APPLY ( VALUES ('C', s.c_min, s.c_max), ('MN', s.mn_min, s.mn_max) ) v(element, min_val, max_val);
转换结果校验
针对提供的样例源数据,执行上述SELECT逻辑后返回的结果完全匹配要求:
- TDC_NO=BS24,element=C,min_val=0.06,max_val=0.12
- TDC_NO=BS24,element=MN,min_val=0.45,max_val=0.65
- TDC_NO=HX11,element=C,min_val=0.14,max_val=0.16
- TDC_NO=HX11,element=MN,min_val=0.55,max_val=0.6
内容的提问来源于stack exchange,提问作者Dhiraj Kumar
相关产品推荐
相关产品推荐

