【问题标题】:How do I split a single row into multiple rows and Insert into a table in Oracle?如何将单行拆分为多行并插入到 Oracle 中的表中?
【发布时间】:2015-08-18 05:02:54
【问题描述】:

我使用以下查询从表 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 块或任何其他具有性能的简单方法来实现这一点?

【问题讨论】:

  • 请提供创建和插入语句。在这种情况下,您可以使用 UNION

标签: sql oracle


【解决方案1】:

您可以使用 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 将上述行拆分为多行。只是额外的努力是使用 SUBSTRINSTR 从 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...

【讨论】:

  • 所以,就像您给出的示例一样,我选择必要的列并使用 insert from select 将其插入。对吗?
  • @SqlNerd 是的。 INSERT INTO hist_table SELECT...
【解决方案2】:
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
;

【讨论】:

    【解决方案3】:

    作为拉利特答案的变体:

    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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-18
      • 2015-02-28
      • 2013-09-17
      • 1970-01-01
      • 2018-03-26
      相关资源
      最近更新 更多