如何将单行拆分为多行并插入Oracle中的表?

时间:2015-08-18 05:02:54

标签: sql oracle

我使用以下查询

从表Employee_Master中选择数据
SELECT EMP_ID
, EMP_NAME
, EMP_LOC1
, EMP_LOC2
, EMP_LOC3
, EMP_DESG
, EMP_ADDR1
, EMP_ADDR2
, EMP_ADDR3
, EMP_PHNO
, EMP_STATUS
FROM Employee_Master
WHERE EMP_STATUS = 'A'

结果集如下所示。

    EMP_ID          EMP_NAME         EMP_LOC1      EMP_LOC2    EMP_LOC3   EMP_DESG  EMP_ADDR1   EMP_ADDR2   EMP_ADDR3   EMP_PHNO    EMP_STATUS
     23       Covey, Stephen J, Mr       1            2            4       Writer       3         3            3          11          A
     24       Jhon, Abraham A, Mr        1            2            4       Actor        1         1            1          22          A

现在我必须将一条记录拆分为三条记录,然后像这样插入Emp_history表。 EMP_SAL_ID是从我可以处理的不同表格中提取的。

    EMP_SAL_ID  First_Name  Middle_Initial  Last_Name   Title   Designation Location    Address Phone_No    Status
       3456      Stephen          J           Covey      Mr       Writer       1           3        11         A
       3456      Stephen          J           Covey      Mr       Writer       2           3        11         A
       3456      Stephen          J           Covey      Mr       Writer       4           3        11         A

是否可以使用PL / SQL块或任何其他具有性能的简单方法来实现此目的。?

3 个答案:

答案 0 :(得分:2)

您可以使用 UNION 为每个地址值分别设置行。

例如,假设您在with子句中有一行:

SQL> WITH DATA(EMP_NAME,EMP_ADDR1,EMP_ADDR2,EMP_ADDR3) AS(
  2  SELECT 'Covey, Stephen J, Mr', 1, 2, 4 FROM DUAL UNION ALL
  3  SELECT 'Jhon, Abraham A, Mr ', 1, 2, 4 FROM DUAL
  4  )
  5  SELECT * FROM DATA;

EMP_NAME              EMP_ADDR1  EMP_ADDR2  EMP_ADDR3
-------------------- ---------- ---------- ----------
Covey, Stephen J, Mr          1          2          4
Jhon, Abraham A, Mr           1          2          4

SQL>

现在,您可以使用 UNION 将上面的行拆分为多行。只需另外一项工作就是使用 SUBSTR INSTR 从emp_name中提取名称。

例如,

SQL> WITH DATA(EMP_NAME,EMP_ADDR1,EMP_ADDR2,EMP_ADDR3) AS(
  2  SELECT 'Covey, Stephen J, Mr', 1, 2, 4 FROM DUAL UNION ALL
  3  SELECT 'Jhon, Abraham A, Mr ', 1, 2, 4 FROM DUAL
  4  )
  5  SELECT SUBSTR(emp_name, instr(emp_name, ',', 1, 1)+1, instr(emp_name, ' ', 1, 2) - instr(emp_name, ',', 1, 1)) AS "ename",
  6    emp_addr1                                                                                                  AS "addr"
  7  FROM DATA
  8  UNION ALL
  9  SELECT SUBSTR(emp_name, instr(emp_name, ',', 1, 1)+1, instr(emp_name, ' ', 1, 2) - instr(emp_name, ',', 1, 1)),
 10    emp_addr2
 11  FROM DATA
 12  UNION ALL
 13  SELECT SUBSTR(emp_name, instr(emp_name, ',', 1, 1)+1, instr(emp_name, ' ', 1, 2) - instr(emp_name, ',', 1, 1)),
 14    emp_addr3
 15  FROM DATA
 16  /

ename                      addr
-------------------- ----------
 Stephen                      1
 Abraham                      1
 Stephen                      2
 Abraham                      2
 Stephen                      4
 Abraham                      4

6 rows selected.

SQL>

注意

WITH 子句仅用于构建示例数据以用于演示目的。在实际情况中,您只需要在表格上使用 SELECT 语句。

INSERT INTO hist_table SELECT statement as shown above...

答案 1 :(得分:0)

create table adress_test(ename varchar2(30), addr number);


insert all 
   into adress_test values(SUBSTR(emp_name, instr(emp_name, ',', 1, 1)+1, instr(emp_name, ' ', 1, 2) - instr(emp_name, ',', 1, 1)), emp_addr1)
   into adress_test  values(SUBSTR(emp_name, instr(emp_name, ',', 1, 1)+1, instr(emp_name, ' ', 1, 2) - instr(emp_name, ',', 1, 1)),emp_addr2)
   into adress_test values(SUBSTR(emp_name, instr(emp_name, ',', 1, 1)+1, instr(emp_name, ' ', 1, 2) - instr(emp_name, ',', 1, 1)),emp_addr3)

   SELECT 'Covey, Stephen J, Mr' EMP_NAME , 1 EMP_ADDR1, 2 EMP_ADDR2, 4 EMP_ADDR3 FROM DUAL UNION ALL
    SELECT 'Jhon, Abraham A, Mr ', 1, 2, 4 FROM DUAL
;

答案 2 :(得分:0)

作为Lalit答案的变体:

WITH DATA(EMP_NAME,EMP_ADDR1,EMP_ADDR2,EMP_ADDR3) AS(
  SELECT 'Covey, Stephen J, Mr', 1, 2, 4 FROM DUAL UNION ALL
  SELECT 'Jhon, Abraham A, Mr ', 1, 2, 4 FROM DUAL
 ),
 a as (select 1 as n from dual
     union all select 2 as n from dual 
     union all select 3 as n from dual)
 select emp_name, case a.n 
                  when 1 then emp_addr1 
                  when 2 then emp_addr2 
                  when 3 then emp_addr3 end as emp_addr
from data inner join a on 1=1

对于大型表,这可能更有效。大表(数据)只需要扫描一次。