Oracle:update_set_clause可以是子查询吗?

时间:2017-09-28 11:42:36

标签: oracle

我在Oracle中有一个源表,看起来像这样:

包含数据的来源表

Id   | Attr_list
--   ---------              
1    | col1,col2            
2    | col3,col4            
3    | col1,col4

包含数据的目标表

Id   | col1 | col2 | col3 | col4
--     -----  ----- -----  -----
1    | aaa  | bbb  | ccc  | ddd  
2    | eee  | fff  | ggg  | hhh  
3    | iii  | jjj  | kkk  | lll 

带有数据的预期目标表

Id   |col1  | col2| col3 | col4
--    ---    -----  -----  -----  
1    | NULL | NULL| ccc  | ddd  
2    | eee  | fff | NULL | NULL 
3    | NULL | jjj | kkk  | NULL 

目标表的列名称在源表中作为值提及 现在,我想通过加入NULL来更新目标表,将所有列添加到ID作为源表中的属性列表(attr_list)。 你能指导我一下吗?

1 个答案:

答案 0 :(得分:0)

您可以使用动态SQL更新特定列.for循环内部的查询将“,”分隔的值拆分为行。

编辑:好的,我想继续按照评论中的预期进行更改。

DECLARE
   v_query   VARCHAR2 (200);
BEGIN
   FOR cur IN (  SELECT b.id, b.column_name, a.DATA_TYPE
                   FROM ALL_TAB_COLUMNS a
                        JOIN (    SELECT DISTINCT id,
                                                  TRIM (REGEXP_SUBSTR (attr_list,
                                                                       '[^,]+',
                                                                       1,
                                                                       LEVEL))
                                                     column_name
                                    FROM source_table
                              CONNECT BY INSTR (attr_list,
                                                ',',
                                                1,
                                                LEVEL - 1) > 0) b
                           ON A.COLUMN_NAME = UPPER (b.column_name)
                  WHERE a.table_name = 'TARGET_TABLE'
               ORDER BY id)
   LOOP
      --EXECUTE IMMEDIATE
      v_query :=
            'UPDATE target_table SET '
         || cur.column_name
         || ' = '
         || CASE
               WHEN cur.data_type LIKE 'VARCHAR%'
               THEN
                  'NULL'
               WHEN cur.data_type = 'NUMBER'
               THEN
                  '0'
               WHEN cur.data_type = 'DATE'
               THEN
                  'TO_DATE(''1900-01-01'',''yyyy-mm-dd'')'
            END
         || ' WHERE id = '
         || cur.id;

      EXECUTE IMMEDIATE v_query;
   END LOOP;
END;
/