繁体   English   中英

从同一列交换值

[英]Swap values from the same column

我的表看起来像这样:

id_device    name_device     os     env

dev1         dev1_name       2K12   PR
dev2         dev2_name       2k3    PR

我想要实现的是交换设备的ID和名称:

id_device    name_device     os     env

dev2         dev2_name       2K12   PR
dev1         dev1_name       2k3    PR

是否可以在一个查询中执行此操作? 我们需要一个临时变量吗? 编辑 :dev1和dev2将由用户设置(通过php公式)。

使用单个查询,您可以在内部CTE中创建交换数据。

完整查询:

SQL小提琴演示

update test1 t set 
(name_device, id_device) = (select s.target_name, s.target_id
                            from  (SELECT 
                                        t1.id_device source_id, 
                                        t2.name_device target_name,
                                        t2.id_device target_id
                                   FROM 
                                       test1 t1 inner join 
                                       test1 t2 on t1.id_device <> t2.id_device
                                   WHERE 
                                       t1.id_device in ('dev1', 'dev2')
                                   and t2.id_device in ('dev1', 'dev2')) s
                            where s.source_id = t.id_device
                            )
where id_device in ('dev1', 'dev2');

我必须更新我的查询,因为oracle不接受cte update

这是使用MERGE的替代方案。 但它假设id_device是唯一的。

create table test1
as
select 'dev1' id_device, 'dev1_name' name_device, '2K12' os, 'PR' env from dual union all
select 'dev2' id_device, 'dev2_name' name_device, '2k3' os, 'PR' env from dual union all
select 'dev3' id_device, 'dev3_name' name_device, '2P4' os, 'PR' env from dual union all
select 'dev4' id_device, 'dev4_name' name_device, '2Q7' os, 'PR' env from dual;

select * from test1;

ID_DEVICE NAME_DEVICE OS   ENV
--------- ----------- ---- ---
dev1      dev1_name   2K12 PR 
dev2      dev2_name   2k3  PR 
dev3      dev3_name   2P4  PR 
dev4      dev4_name   2Q7  PR 

merge into test1 tgt
using (select rowid ri,
              id_device old_id_device,
              case when id_device = 'dev1' then lead(id_device) over (order by case when id_device = 'dev1' then 1 when id_device = 'dev2' then 2 end)
                   when id_device = 'dev2' then lag(id_device) over (order by case when id_device = 'dev1' then 1 when id_device = 'dev2' then 2 end)
              end new_id_device,
              name_device old_name_device,
              case when id_device = 'dev1' then lead(name_device) over (order by case when id_device = 'dev1' then 1 when id_device = 'dev2' then 2 end)
                   when id_device = 'dev2' then lag(name_device) over (order by case when id_device = 'dev1' then 1 when id_device = 'dev2' then 2 end)
              end new_name_device,
              os,
              env
       from   test1 t1
       where  t1.id_device in ('dev1', 'dev2')) src
  on (tgt.rowid = src.ri)
when matched then
  update set tgt.id_device = src.new_id_device,
             tgt.name_device = src.new_name_device;

commit;

select * from test1;

ID_DEVICE NAME_DEVICE OS   ENV
--------- ----------- ---- ---
dev2      dev2_name   2K12 PR 
dev1      dev1_name   2k3  PR 
dev3      dev3_name   2P4  PR 
dev4      dev4_name   2Q7  PR 

显然,对于dev1和dev2是参数的情况,你的MERGE看起来像:

merge into test1 tgt
using (select rowid ri,
              id_device old_id_device,
              case when id_device = p_device_id1 then lead(id_device) over (order by case when id_device = p_device_id1 then 1 when id_device = p_device_id2 then 2 end)
                   when id_device = p_device_id2 then lag(id_device) over (order by case when id_device = p_device_id1 then 1 when id_device = p_device_id2 then 2 end)
              end new_id_device,
              name_device old_name_device,
              case when id_device = p_device_id1 then lead(name_device) over (order by case when id_device = p_device_id1 then 1 when id_device = p_device_id2 then 2 end)
                   when id_device = p_device_id2 then lag(name_device) over (order by case when id_device = p_device_id1 then 1 when id_device = p_device_id2 then 2 end)
              end new_name_device,
              os,
              env
       from   test1 t1
       where  t1.id_device in (p_device_id1, p_device_id2)) src
  on (tgt.rowid = src.ri)
when matched then
  update set tgt.id_device = src.new_id_device,
             tgt.name_device = src.new_name_device;

其中p_device_id1p_device_id2是被交换的两个设备ID的参数。

-----------------

作为我对@ goliardico答案的评论的补充,这是测试用例:

create table test1
as
select 'dev1' id_device, 'dev1_name' name_device, '2K12' os, 'PR' env from dual union all
select 'dev2' id_device, 'dev2_name' name_device, '2k3' os, 'PR' env from dual union all
select 'dev3' id_device, 'dev3_name' name_device, '2P4' os, 'PR' env from dual union all
select 'dev4' id_device, 'dev4_name' name_device, '2Q7' os, 'PR' env from dual;

DECLARE
  device1    varchar2(50);
  device2    varchar2(50);
  dev_rec1   test1%rowtype;
  dev_rec2   test1%rowtype;
BEGIN
  device1 := 'dev1';
  device2 := 'dev2';

  select * INTO dev_rec1 from test1 where id_device = device1;
  select * INTO dev_rec2 from test1 where id_device = device2;

  update test1
  set    id_device = case when id_device = dev_rec1.id_device then dev_rec2.id_device
                          when id_device = dev_rec2.id_device then dev_rec1.id_device
                     end,
         name_device = case when id_device = dev_rec1.id_device then dev_rec2.name_device
                            when id_device = dev_rec2.id_device then dev_rec1.name_device
                       end
  where  id_device in (dev_rec1.id_device, dev_rec2.id_device);

  commit;
END;
/

select * from test1;

ID_DEVICE NAME_DEVICE OS   ENV
--------- ----------- ---- ---
dev2      dev2_name   2K12 PR 
dev1      dev1_name   2k3  PR 
dev3      dev3_name   2P4  PR 
dev4      dev4_name   2Q7  PR

不是单个查询而是PL / SQL。 您可以使用多个记录的参数创建一个过程:

DECLARE
  device1    varchar2(50);
  device2    varchar2(50);
  dev_rec1   devs_tablename%rowtype;
  dev_rec2   devs_tablename%rowtype;
BEGIN
  device1 := 'dev1';
  device2 := 'dev2';

  select * INTO dev_rec1 from devs_tablename where id_device = device1;
  select * INTO dev_rec2 from devs_tablename where id_device = device2;
  update devs_tablename set id_device = dev_rec2.id_device || 'TMP',
     name_device = dev_rec2.name_device where id_device = device1;
  update devs_tablename set id_device = dev_rec1.id_device,
    name_device = dev_rec1.name_device where id_device = device2;
  update devs_tablename set id_device = dev_rec2.id_device 
    where id_device = device2 || 'TMP';
END;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM