Oracle 过程使用现有过程中使用的数据拆分逻辑将数据反透视到目标

Posted

技术标签:

【中文标题】Oracle 过程使用现有过程中使用的数据拆分逻辑将数据反透视到目标【英文标题】:Oracle Procedure unpivot data into destination using data splitting logic used in existing procedure 【发布时间】:2020-11-10 04:37:22 【问题描述】:

我有一个 PL/SQL 过程,它在运行时采用逗号分隔的字符串,将其拆分并推送到表中。 这里给出了过程和表格的示例: 过程是push_data。 当前插入数据的表是 push_data_temp。

现在根据要求,我需要编写一个新程序,其中逻辑将保持与拆分数据相同,但在新表 push_data_pivot(数据透视内的结构)中,应显示以这种格式旋转的数据。

例如:如果 push_data_temp 中的当前数据是:

数据应该在新过程中进入 push_data_pivot,如下所示:

逻辑应该保持不变,只是插入的数据将进入列而不是行,填充 id 和 value 列。

这里的 id 列是两个表中传递的字符串的唯一标识符。基本上和原表一样。

无法更新 push_data_pivot 结构的小提琴,因此在此提及最新的结构和数据: PUSH_DATA_PIVOT:

create table PUSH_DATA_PIVOT
(
id_pk NUMBER,
  id NUMBER,
  label_id number,
  label varchar2(4000),
  value varchar2(4000)
);

insert into push_data_pivot values(1,null,'COL01',null);
insert into push_data_pivot values(1,null,'COL02',null);
insert into push_data_pivot values(1,null,'COL03',null);
insert into push_data_pivot values(1,null,'COL04',null);
insert into push_data_pivot values(1,null,'COL05',null);
insert into push_data_pivot values(1,null,'COL06',null);
insert into push_data_pivot values(1,null,'COL07',null);
insert into push_data_pivot values(1,null,'COL08',null);
insert into push_data_pivot values(1,null,'COL09',null);
insert into push_data_pivot values(1,null,'COL10',null);
insert into push_data_pivot values(1,null,'COL11',null);
insert into push_data_pivot values(1,null,'COL12',null);
insert into push_data_pivot values(1,null,'COL13',null);
insert into push_data_pivot values(1,null,'COL14',null);

示例数据是单个字符串,用于单个 label_id 和相应的一组列标签值。但是实际表会在 id 列的基础上插入多个此类字符串,与原始要求相同。这已经在现有过程中使用游标处理。

唯一的要求是,使用新的目标表作为 push_data_pivot 和未透视格式的数据创建新过程。拆分逻辑将与现有程序中的相同。

【问题讨论】:

那么如果 PUSH_DATA_TEMP 表中有不止一行,你想发生什么?想必这是数据中的行数不固定吧?您需要一个可以处理一行或多行的过程。您是否期望最大行数? 现有已经用光标处理它,因此将插入多个 id 的行。预计新表中也会出现类似情况,只是数据不会被转置。 另外,目标表现在是 push data_pivot。我给出了现有过程的参考,因为在运行时拆分作为输入传递的字符串的逻辑是相同的。 因此,正如在屏幕截图和小提琴中引用的那样,字符串将 push_data_temp 中的数据推送到列中。我希望编写类似的过程,具有类似的拆分逻辑,只是目标表现在是 push_data_pivot 并且采用屏幕截图中显示的格式。 所以,数据之前是按列拆分的,现在同样会按行拆分。 【参考方案1】:

如果 PUSH_DATA_TEMP 中的列列表是固定的,那么标准的 UNPIVOT 将满足所有需要,例如

SQL> create table push_data_temp
  2   ( id  int,
  3     col1 varchar2(20),
  4     col2 varchar2(20),
  5     col3 varchar2(20),
  6     col4 varchar2(20),
  7     col5 varchar2(20),
  8     col6 varchar2(20),
  9     col7 varchar2(20),
 10     col8 varchar2(20),
 11     col9 varchar2(20),
 12     col10 varchar2(20),
 13     col11 varchar2(20),
 14     col12 varchar2(20),
 15     col13 varchar2(20),
 16     col14 varchar2(20)
 17  );

Table created.

SQL>
SQL> insert into push_data_temp values
  2   (1,'c1data','c2data','c3data','c4data','c5data','c6data','c7data',
  3      'c8data','c9data','c10data','c11data','c12data','c13data','c14data' );

1 row created.

SQL>
SQL> insert into push_data_temp values
  2   (2,'c1dataX','c2dataX','c3dataX','c4dataX','c5dataX','c6dataX','c7dataX',
  3      'c8dataX','c9dataX','c10dataX','c11dataX','c12dataX','c13dataX','c14dataX' );

1 row created.

SQL>

反透视 ...

SQL> select *
  2  from   push_data_temp
  3  unpivot (value for label
  4    IN (col1 AS 'COL-1', col2 AS 'COL-2',col3 AS 'COL-3',col4 AS 'COL-4',col5 AS 'COL-5',col6 AS 'COL-6',col7 AS 'COL-7',
  5        col8 AS 'COL-8',col9 AS 'COL-9',col10 AS 'COL-10',col11 AS 'COL-11',col12 AS 'COL-12',col13 AS 'COL-13',col14 AS 'COL-14'
  6    ));

        ID LABEL  VALUE
---------- ------ --------------------
         1 COL-1  c1data
         1 COL-2  c2data
         1 COL-3  c3data
         1 COL-4  c4data
         1 COL-5  c5data
         1 COL-6  c6data
         1 COL-7  c7data
         1 COL-8  c8data
         1 COL-9  c9data
         1 COL-10 c10data
         1 COL-11 c11data
         1 COL-12 c12data
         1 COL-13 c13data
         1 COL-14 c14data
         2 COL-1  c1dataX
         2 COL-2  c2dataX
         2 COL-3  c3dataX
         2 COL-4  c4dataX
         2 COL-5  c5dataX
         2 COL-6  c6dataX
         2 COL-7  c7dataX
         2 COL-8  c8dataX
         2 COL-9  c9dataX
         2 COL-10 c10dataX
         2 COL-11 c11dataX
         2 COL-12 c12dataX
         2 COL-13 c13dataX
         2 COL-14 c14dataX

28 rows selected.

SQL>

【讨论】:

我需要为此编写一个单独的程序并且不能使用 push_data_temp。我为数据拆分逻辑提供了参考。我需要编写新的proc,目标为push_data_pivot,它将字符串作为输入,根据给定的正则表达式逻辑拆分它,然后如果记录存在则推送到push_data_pivot表中,否则更新。我也不能将合并用于插入/更新,因为 oracle 12.1 不支持 proc 内的合并并且无法升级到更高版本。 我迷路了——如果你有现有的逻辑可以将字符串拆分成一个带有键和 14 列的结构,那么该结构很容易成为嵌套表类型或全局临时表,并且unpivot SQL 可以解决这个问题。此外,MERGE 在 proc 中运行良好,您只需要在必要时使用动态 SQL 而不是静态 SQL 你是对的,但因为我在 pl/sql 方面缺乏经验,所以我需要帮助。我们可以拆分和使用嵌套表和 unpivot。但是需要帮助。合并也不适用于 oracle 12.1 它将从 12.2 开始工作【参考方案2】:

我得到了这个问题的答案。

https://dbfiddle.uk/?rdbms=oracle_18&fiddle=412a6e27a22741ee1c31eee4a3f2bf3

【讨论】:

以上是关于Oracle 过程使用现有过程中使用的数据拆分逻辑将数据反透视到目标的主要内容,如果未能解决你的问题,请参考以下文章

oracle 存储过程中查询结果无法赋值到变量,请指教

获取字符串,按分隔符拆分并插入到 Oracle 中的表过程 [重复]

使用 C# 中的存储过程更新 Oracle 表 Odd bug

使用输出参数调用oracle存储过程时Azure逻辑应用程序出错

如何提取函数/过程中使用的所有 Oracle 关键字

Oracle创建存储过程