Oracle-基于动态选定列将数据从一行复制到另一行

Oracle-基于动态选定列将数据从一行复制到另一行,oracle,dynamic-sql,Oracle,Dynamic Sql,我有一个有两行的表,我需要将a行中的一些数据复制到B行。 这里我最担心的是,所涉及的列在名称或数字表中不是静态的,列的数量可能会增加或减少 我想出了一个我一点都不喜欢的解决方案 创建或替换 程序Z_复制_任务_附件 瓦查尔的帕鲁·奥德鲁维德, 瓦查尔的帕鲁·纽罗维德2 是 var_更新VARCHAR24000字节; var_crr_col_value_old VARCHAR210字节; var_crr_选择VARCHAR24000字节; 开始 var_update:=“更新规划_实体集”; 因为

我有一个有两行的表,我需要将a行中的一些数据复制到B行。 这里我最担心的是,所涉及的列在名称或数字表中不是静态的,列的数量可能会增加或减少

我想出了一个我一点都不喜欢的解决方案

创建或替换 程序Z_复制_任务_附件 瓦查尔的帕鲁·奥德鲁维德, 瓦查尔的帕鲁·纽罗维德2 是 var_更新VARCHAR24000字节; var_crr_col_value_old VARCHAR210字节; var_crr_选择VARCHAR24000字节; 开始 var_update:=“更新规划_实体集”; 因为我在 选择列名称 从用户选项卡列 其中表\u name='PLANNING\u ENTITY' 和较低的列名称,如“代码%” 环 var_crr_select:=“选择”|| i.column_name ||'来自规划实体,其中规划代码=' ||老罗维德公园; 执行即时var\u crr\u select 转换为var_crr_col_value_old; var|u update:=var|u update | i.column|u name |'='| var|u crr_col|u value|u old | |','; 端环; 变量更新:=子变量更新,0,长度变量更新-2; var_update:=var_update | |'其中规划代码='| | par|u newRowId | |; 执行即时var_更新; 犯罪 终止 对于我来说,这里的主要问题至少是,我需要为循环的每个迭代进行选择。如果我可以选择一个返回类似column | name的内容,然后只需要i.column和i.value,那就太好了

你觉得怎么样

====Marmite轰炸机回答后的解决方案=====

这个怎么样

begin
  for i in (select * from PLANNING_ENTITY where planning_code = newrow) loop   
    update PLANNING_ENTITY set row = i where planning_code = oldrow;   
  end loop;
end;
对于下层选民:

SQL> select version from v$instance;

VERSION
-----------------
11.2.0.4.0

SQL> create table it_works_in_oracle (n1 number, n2 number, n3 number);

Table created.

SQL> insert into it_works_in_oracle values(1, 1, 1);

1 row created.

SQL> insert into it_works_in_oracle values(2, 2, 2);

1 row created.

SQL> insert into it_works_in_oracle values(3, 3, 3);

1 row created.

SQL> commit;

Commit complete.

SQL> select * from it_works_in_oracle;

        N1         N2         N3
---------- ---------- ----------
         1          1          1
         2          2          2
         3          3          3

SQL> set serveroutput on
SQL> declare
  oldrow number:=1;
  newrow number:=3;
begin
  for i in (select * from it_works_in_oracle where n1 = newrow) loop
    update it_works_in_oracle set row = i where n1 = oldrow;
  end loop;
end;  2    3    4    5    6    7    8
  9  /

PL/SQL procedure successfully completed.

SQL> select * from it_works_in_oracle;

        N1         N2         N3
---------- ---------- ----------
         3          3          3
         2          2          2
         3          3          3
基于此更新

 UPDATE t1 a
 SET (code1, code2) = (
   SELECT code1,code2
   FROM t1 b
   WHERE b.planning_code = 'new')
 where a.planning_code = 'old';

只需生成应更新的列名的逗号分隔列表,并在语句中应用它两次。在示例代码1、代码2中,您可以执行与未测试类似的操作:

var_update := 'UPDATE PLANNING_ENTITY a SET (';

  FOR i IN (
            SELECT COLUMN_NAME 
            FROM USER_TAB_COLUMNS 
            WHERE table_name='PLANNING_ENTITY' 
            AND LOWER(COLUMN_NAME) LIKE 'code%'
            )
  LOOP
        var_update := var_update || i.column_name ||',';
  END LOOP;
  var_update := REGEXP_REPLACE(var_update, ',$', ')');
  var_update := var_update ||' = (SELECT ';
  FOR i IN (
            SELECT COLUMN_NAME 
            FROM USER_TAB_COLUMNS 
            WHERE table_name='PLANNING_ENTITY' 
            AND LOWER(COLUMN_NAME) LIKE 'code%'
            )
  LOOP
        var_update := var_update || i.column_name ||',';
  END LOOP;
  var_update := REGEXP_REPLACE(var_update, ',$');
  var_update := var_update || ' FROM PLANNING_ENTITY b WHERE planning_code = :newRowId) ';
  var_update := var_update || ' WHERE a.planning_code = :oldRowId';

  EXECUTE IMMEDIATE var_update USING par_newRowId, par_oldRowId;

使现代化设置行=。。。更新每一列,但TO只想更新名称类似于代码%的列。更糟糕的是,它还将更新列规划代码,即它将newRowId行加倍。好的,你是对的,我理解的问题是错误的。但TO仍然不必为每一列运行查询。嗨@Marmite Bomber,我不敢相信我错过了这一列。。。这肯定会更好:嗨@Wernfried。我不得不选择Marmite Bomber答案,因为它简单,避免了循环和所有问题,而且很可能是性能问题。我的解决方案与Marmite Bomber的解决方案相同。唯一的区别是UPDATE语句是动态生成的,而不是静态生成的。但是,使用listag可以避免一个循环。
var_update := 'UPDATE PLANNING_ENTITY a SET (';

  FOR i IN (
            SELECT COLUMN_NAME 
            FROM USER_TAB_COLUMNS 
            WHERE table_name='PLANNING_ENTITY' 
            AND LOWER(COLUMN_NAME) LIKE 'code%'
            )
  LOOP
        var_update := var_update || i.column_name ||',';
  END LOOP;
  var_update := REGEXP_REPLACE(var_update, ',$', ')');
  var_update := var_update ||' = (SELECT ';
  FOR i IN (
            SELECT COLUMN_NAME 
            FROM USER_TAB_COLUMNS 
            WHERE table_name='PLANNING_ENTITY' 
            AND LOWER(COLUMN_NAME) LIKE 'code%'
            )
  LOOP
        var_update := var_update || i.column_name ||',';
  END LOOP;
  var_update := REGEXP_REPLACE(var_update, ',$');
  var_update := var_update || ' FROM PLANNING_ENTITY b WHERE planning_code = :newRowId) ';
  var_update := var_update || ' WHERE a.planning_code = :oldRowId';

  EXECUTE IMMEDIATE var_update USING par_newRowId, par_oldRowId;