0

问题:

我有一个包含 CLOB 的表,它是来自外部源的固定长度记录。其中位置 1-5 = fieldA,位置 6-12 = fieldB,等等。

我有另一个表(LayoutDefinition)定义了记录布局,其中

FieldName = 'fieldA'
FieldStart = 1
FieldLength = 5
FieldName = 'fieldB'
FieldStart = 6
FieldLength = 6

我需要从 CLOB 中检索数据并将其放入 %rowtype 变量中,例如“tableA_rec tableA%rowtype”。

我已经实现了一个使用大量 case 语句的例程,并且 LayoutDefiniton 表中每一行的循环将 CLOB 的区域移动到 tablea_rec 中的适当变量中;

CASE LayoutDefiniton.FieldName
WHEN 'fieldA' THEN tablea_rec.fieldA:= SUBSTR(inputClob,LayoutDefiniton.FieldStart,LayoutDefiniton.FieldLength);
WHEN 'fieldB' THEN tablea_rec.fieldB:= SUBSTR(inputClob,LayoutDefiniton.FieldStart,LayoutDefiniton.FieldLength);

这当然是非常低效的,因为我需要遍历我的布局,以便为每条记录挑选出我的数据。

我想做的是创建一个动态 sql select 语句,该语句将把表中的数据检索到适当的变量中。例如,如果它不是动态的,它可能看起来像;

select substr(inputCLOB,1,5), substr(inputCLOB,6,6) into FieldA, fieldB from CLOBTable;

这可以使用动态 SQL 来完成吗?

如果是这样,语法会是什么样子?

4

1 回答 1

1

以下代码将从 CLOB 列中提取数据并插入到目标表中

DECLARE
  l_sql_str VARCHAR2(4000);
BEGIN
  WITH src_meta_agg AS(
    SELECT LISTAGG(field_name, ',') WITHIN GROUP(ORDER BY field_start) AS field_list
           ,LISTAGG('substr(lob,' || field_start || ', ' || field_length || ')', ',') WITHIN GROUP( ORDER BY field_start) AS field_source
      FROM src_meta)
    SELECT 'INSERT INTO dest(' || field_list || ') SELECT ' || field_source ||
           ' FROM src' INTO l_sql_str
      FROM src_meta_agg;

  EXECUTE IMMEDIATE l_sql_str;
END;

LISTAGG是 11g 函数,用于对数据进行排序并连接值。对于以前的版本,您可以使用wm_concat或任何其他方法。在l_sql_str您将有以下语句

INSERT INTO dest(field1,field2) SELECT substr(lob,1, 5),substr(lob,6, 6) FROM src

如果您需要在 PL/SQL 中处理数据,则此代码可以解决问题

DECLARE
  l_sql_str VARCHAR2(4000);
  TYPE t_dest_tbl IS TABLE OF dest%ROWTYPE;
  l_dest_rows t_dest_tbl;
  l_cursor SYS_REFCURSOR;
BEGIN

  WITH src_meta_agg AS(
    SELECT LISTAGG(field_name, ',') WITHIN GROUP(ORDER BY field_start) AS field_list
           ,LISTAGG('substr(lob,' || field_start || ', ' || field_length || ')', ',') WITHIN GROUP( ORDER BY field_start) AS field_source
      FROM src_meta)
    SELECT 'SELECT ' || field_source ||
           ' FROM src' INTO l_sql_str
      FROM src_meta_agg;

  OPEN l_cursor FOR l_sql_str;
  FETCH l_cursor
  BULK COLLECT INTO l_dest_rows;
  CLOSE l_cursor; 

  FOR i IN 1..l_dest_rows.COUNT LOOP
    dbms_output.put_line(l_dest_rows(i).field1 || ', ' || l_dest_rows(i).field2);
  END LOOP;
END;

这是我使用的架构

create table src(lob clob)
/
insert into src values ('12345ABCDEF')
/
insert into src values ('78901GHIJKL')
/

create table src_meta(field_name varchar2(100), field_start number, field_length number)
/

insert into src_meta values ('field1', 1, 5)
/
insert into src_meta values ('field2', 6, 6)
/

create table dest(field1 varchar2(5), field2 varchar2(6))
/
于 2013-08-26T16:47:45.607 回答