当前位置: 代码迷 >> Oracle技术 >> 关于表数据更新的有关问题
  详细解决方案

关于表数据更新的有关问题

热度:196   发布时间:2016-04-24 08:06:36.0
关于表数据更新的问题
有一个总表tb1(mobile,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,inputtime,source),以mobile为主键,可以将col1,col2等列视为mobile的属性,inputtime获取数据更新时的系统时间记录为数据更新时间,source为数据来源,来源可能有多种,不同来源以“,”逗号间隔。

现有一个实际应用是时常有txt格式的新数据过来,在这些新数据中必有mobile与source字段,但是可能只会有(mobile,col1, source);下次的新数据可能只有(mobile,col2,source),新数据中的mobile有些会与tb1中的mobile重复。

现需要将每次过来的新数据导入到tb1中,类似merge into的功能,mobile相同的,update;mobile不同的,insert。同时更新inputtime,source以“,”逗号为间隔继续添加,如“问卷调查,会员信息”,如果有新的来源继续添加。

如果每一次更新都建立一个新表存储新数据,然后执行语句的话,十分繁琐,且容易出错,想问一下大神们有没有什么简洁的办法。我目前想到的是建立一个新表tb2(mobile,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,source),每次将新数据导入到该表中,然后用触发器触发更新tb1。

想知道:1.如果用我想到的方法的话,触发器该怎么写(汗~oracle只对查询熟悉一些,其他地方是小白
                2.如果不用触发器,还有没有更好的办法,有次听到一个前辈说用存储过程也可以,但是存储过程也不知道怎么写~
求教诸位大神 了!
------解决思路----------------------
引用:

你自己先把数据导入TB2,然后用一下的存储过程来实现(自己再稍微改动一下)


create or replace procedure test1 is
  l_count number := 0;
begin
  for c1 in (select mobile, col1,...sysdate inputtime, source from tb2) loop
    select count(*) into l_count from tgp_funds where fnd_id = c1.fnd_id;
    if l_count > 0 then
      update tgp_funds tb1
         set tb1.col1 = nvl(c1.col1, tb1.col1),
             tb1.col2 = nvl(c1.col2, tb1.col2),
             ..       . inputtime = sysdate,
             source   = source 
------解决思路----------------------
 ',' 
------解决思路----------------------
 c1.source
       where tb1.fnd_id = c1.fnd_id;
    else
      insert into tgp_funds values c1;
    end if;
  end loop;
  commit;
exception
  when others then
    dbms_output.put_line('Error happened!!');
end test1;


------解决思路----------------------
有点改动:


create or replace procedure test1 is
  l_count number := 0;
begin
  for c1 in (select mobile, col1,...sysdate inputtime, source from tb2) loop
    select count(*) into l_count from tb1 where mobile = c1.mobile;
    if l_count > 0 then
      update tb1
         set tb1.col1 = nvl(c1.col1, tb1.col1),
             tb1.col2 = nvl(c1.col2, tb1.col2),
             ..       . inputtime = sysdate,
             source   = source 
------解决思路----------------------
 ',' 
------解决思路----------------------
 c1.source
       where tb1.mobile = c1.mobile;
    else
      insert into tb1 values c1;
    end if;
  end loop;
  commit;
exception
  when others then
    dbms_output.put_line('Error happened!!');
end test1;


------解决思路----------------------
引用:
有点改动:


create or replace procedure test1 is
  l_count number := 0;
begin
  for c1 in (select mobile, col1,...sysdate inputtime, source from tb2) loop
    select count(*) into l_count from tb1 where mobile = c1.mobile;
    if l_count > 0 then
      update tb1
         set tb1.col1 = nvl(c1.col1, tb1.col1),
             tb1.col2 = nvl(c1.col2, tb1.col2),
             ..       . inputtime = sysdate,
             source   = source 
------解决思路----------------------
 ',' 
------解决思路----------------------
 c1.source
       where tb1.mobile = c1.mobile;
    else
      insert into tb1 values c1;
    end if;
  end loop;
  commit;
exception
  when others then
    dbms_output.put_line('Error happened!!');
end test1;


为什么不用merge呢?

create?or?replace?procedure?test1?is
??l_count?number?:=?0;
begin
  merge into tb1
  using tb2
  on tb1.mobile = tb2.mobile
  when matched then 
    update set 
      tb1.col1?=?nvl(tb2.col1,?tb1.col1),
??????tb1.col2?=?nvl(tb2.col2,?tb1.col2),
??????..???????.?inputtime?=?sysdate,
??????source???=?source?
------解决思路----------------------
?','?
------解决思路----------------------
?tb2.source
????where?tb1.mobile?=?tb2.mobile
    ;
  when not matched then
    insert (
      mobile,
      col1,
      col2,
      .
      .
      .
     inputtime,
     source
    )
    values(
      mobile,
      col1,
      col2,
      .
      .
      .
     sysdate,
     source
    )
    ;
    commit;
end;


------解决思路----------------------
如果我做的话,也是建一个和tb1结构一样的tb2,然后每次都把txt的数据sqlldr进去,补齐缺失字段。存储过程再用merge ,版主的那种写法作为一个懒人第一眼没看懂就没再 看了
  相关解决方案