【问题标题】:Split multi column semicolon separated string and create records拆分多列分号分隔的字符串并创建记录
【发布时间】:2012-11-21 08:38:39
【问题描述】:

我有一个接收三个字符串参数的存储过程

1. p_ReqIDs VARCHAR2
2. p_ItemIDs VARCHAR2
3. p_Qtys    VARCHAR2

以上 3 个字符串变量包含分号分隔的值,如下所示:

p_ReqIDs  := "56;56;56;"  
p_ItemIDs := "3;2;1;"  
p_Qtys    := "400;300;200;"  

我需要像这样拆分值并创建行:

p_ReqIDs   p_ItemIDs   p_Qtys  
------------------------------------
  56           3       400  
  56           2       300  
  56           1       200  

我还需要拆分并插入表格的查询。

谢谢

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

    您可以按如下方式处理参数:

    SQL> declare
      2    type l_rec_type is record(
      3      r_ReqIDs  varchar2(31),
      4      r_ItemIDs varchar2(31),
      5      r_Qtys    varchar2(31)
      6    );
      7  
      8    type l_rec_list is table of l_rec_type;
      9    -- your parameters. 
     10    l_ReqIDs  constant varchar2(31) := '56;56;56;';
     11    l_ItemIDs constant varchar2(31) := '3;2;1;';
     12    l_Qtys    constant varchar2(31) := '400;300;200;';
     13  
     14    l_rec l_rec_list;
     15  begin
     16  
     17  with Parameters(param) as(
     18      select l_ReqIDs  from dual union all
     19      select l_ItemIDs from dual union all
     20      select l_Qtys    from dual
     21    ),
     22    Occurrences(oc) as(
     23      select level
     24        from ( select max(regexp_count(param, '[^;]+')) moc
     25                 from parameters) s
     26     connect by level <= s.moc
     27    )
     28  select max(res1)
     29       , max(res2)
     30       , max(res3)
     31    bulk collect into l_rec
     32    from (select decode(param, l_ReqIDs, res) res1
     33               , decode(param, l_ItemIDs,res) res2
     34               , decode(param, l_Qtys,   res) res3
     35               , rn
     36            from ( select param, regexp_substr(param, '[^;]+', 1, o.oc) res
     37                        , row_number() over(partition by param order by param) rn
     38                     from parameters p
     39                    cross join occurrences o
     40                  )
     41          )
     42  group by rn;
     43  
     44    for i in l_rec.first..l_rec.last
     45    loop
     46       dbms_output.put_line(l_rec(i).r_ReqIDs || '  ' || l_rec(i).r_ItemIDs || '  ' || l_rec(i).r_Qtys);
     47    end loop;
     48  end;
     49  /
    
    
    
    56   2   200
    56   1   300
    56   3   400
    
    PL/SQL procedure successfully completed
    

    如果您只需要将处理后的数据插入表中,则只需要 insert into 语句和查询(bulk collect into l_rec 必须删除):

    insert into your_table(<<columns>>)
      with Parameters(param) as(
         select l_ReqIDs  from dual union all
         select l_ItemIDs from dual union all
         select l_Qtys    from dual
      .... 
      -- the rest of the query from the above pl/sql block.
    

    您还可以将整条记录插入到表中(如果您需要在插入之前对提取的元素进行额外处理),如下所示:

    • 如果表中的列数等于插入的元素数

      for i in l_rec.first..l_rec.last
      loop
         insert into your_table
           values l_rec(i);
      end loop;
      
    • 如果表中的列数大于插入的值数

      for i in l_rec.first..l_rec.last
      loop
         insert into (select column1, .. ,columnn from your_table)
           values l_rec(i);
      end loop;
      

    【讨论】:

      【解决方案2】:

      我确实喜欢这个 :) 简短而甜蜜。

      create or replace procedure proc1(p_ReqID varchar2,p_ItemID varchar2,p_ItemQty varchar2)
      is
      begin
       insert into test(req_id,item_id,itemqty)
       select regexp_substr(req_id,'[^;]+',1,level),
               regexp_substr(item_id,'[^;]+',1,level),
               regexp_substr(item_qty,'[^;]+',1,level)
        from  (
            select p_ReqID Req_ID,p_ItemID item_id,p_ItemQty item_qty
            from dual
            )
        connect by regexp_substr(req_id,'[^;]+',1,level) is not null;
      end;
      

      【讨论】:

      • 是的,它更短。您只需要在connect by 子句中为每个参数添加OR 条件,以防第二个或第三个等参数具有比第一个更多的元素。否则你可能会丢失有价值的信息:)
      • Nicholas 在我的情况下它永远不会发生,因为我正在提取相同 REQ_ID 的详细记录并传递给 Oracle 的 .NET Web 服务。所以所有的列总是有相同的值:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多