PL/SQL 切换两个表中的两列

PL/SQL Switching two columns from two tables

假设我有两个 table(tblA 和 tblB)并且想要切换每个 table(tblA.Grade 和 tblB.Grade)的第二列,如下所示:

+-------------------------------------+
|    table a               table b    |
+-------------------------------------+
| name  grade           name    grade |
| a     60              f       50    |
| b     45              g       70    |
| c     30              h       90    |
+-------------------------------------+

现在,我想将成绩栏从 table a 切换到 table b,并将成绩栏从 table b 切换到 table a。结果应如下所示:

+-----------------------------------------+
|      table a               table b      |
+-----------------------------------------+
|     name  grade           name    grade |
|     a     50              f       60    |
|     b     70              g       45    |
|     c     90              h       30    |
+-----------------------------------------+

我创建了 tables,使用批量收集将它们加载到游标中,并使用以下代码完成转换:

insert into tblA values('a',60);
insert into tblA values('b',45);
insert into tblA values('c',30);
insert into tblb values('f',70);
insert into tblb values('g',80);
insert into tblb values('h',90);

.

DECLARE
    TYPE tbla_type IS TABLE OF tbla%ROWTYPE;
    l_tbla tbla_type;
    TYPE tblb_type IS TABLE OF tblb%ROWTYPE;
    l_tblb tblb_type;

BEGIN
-- All rows at once...
SELECT *
BULK COLLECT INTO l_tbla
FROM tbla;

SELECT *
BULK COLLECT INTO l_tblb
FROM tblb;

    DBMS_OUTPUT.put_line (l_tblb.COUNT);

    FOR indx IN 1 .. l_tbla.COUNT
  LOOP
    DBMS_OUTPUT.put_line (l_tbla(indx).lname);
        update tbla set grade = l_tblb(indx).grade 
          where l_tbla(indx).lname= tbla.lname;

              update tblb set grade = l_tbla(indx).grade 
          where l_tblb(indx).lname= tblb.lname;
  END LOOP;
END;

所以,虽然我完成了任务,但我想知道是否有更简单的解决方案我没有想到?

如果有人知道是否有更简单的解决方案,请告诉我?

请注意,数据库中没有名为 firstsecond 的记录,因为无法保证第一个输入的记录将是第一个返回的记录。所以应该总是有一个 order by 来决定 first/second 等等

因此假设您希望记录按 name 排序,然后将第一个名字最小的等级 table 与第二个最小名字的等级 table,[=21 交换=]

现在假设您修复了现有代码中的顺序问题,并且如果它正常工作,我相信它会比我在下面执行的方法更快。像

  1. 创建一个临时文件 table 并按姓名顺序放置姓名和成绩。

之所以使用临时table主要是因为以后如果我想更正或还原数据,我可以使用相同的临时table来反转合并。

    create table tmp1 as
    with ta as
    (select t.* ,
    row_number() over (order by name) as rnk
    from tblA t)
    ,tb as
    (select t.* ,
    row_number() over (order by name) as rnk
    from tblb t)
    select ta.name as ta_name,ta.grade as ta_grade,
    tb.name as tb_name,tb.grade as tb_grade
    from ta inner join tb
    on ta.rnk=tb.rnk

tmp1

的输出
+---------+----------+---------+----------+
| TA_NAME | TA_GRADE | TB_NAME | TB_GRADE |
+---------+----------+---------+----------+
| a       |       60 | f       |       70 |
| b       |       45 | g       |       80 |
| c       |       30 | h       |       90 |
+---------+----------+---------+----------+

然后使用merge交换tmp1的值。

merge  into tbla t1
using  tmp1 t
on (t1.name=t.ta_name)
when matched then update
set t1.grade=t.tb_grade;

merge  into tblb t1
using  tmp1 t
on (t1.name=t.tb_name)
when matched then update
set t1.grade=t.ta_grade;

如果对结果满意,稍后再降低温度table

drop table tmp1;