Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在oracle中使用游标插入和更新记录_Sql_Oracle_Cursor - Fatal编程技术网

Sql 在oracle中使用游标插入和更新记录

Sql 在oracle中使用游标插入和更新记录,sql,oracle,cursor,Sql,Oracle,Cursor,我有两个表-student和studLoad都有两个字段studID和studName。我想将数据从student表加载到stuLoad表中。 如果studLoad表中已存在数据,则应更新该数据,否则应插入该数据。以下是我执行此操作的代码: create or replace procedure studentLoad is v_id student.studID%type; v_name student.studName%type; v_sn studLoad.studName%typ

我有两个表-student和studLoad都有两个字段studID和studName。我想将数据从student表加载到stuLoad表中。 如果studLoad表中已存在数据,则应更新该数据,否则应插入该数据。以下是我执行此操作的代码:

    create or replace procedure studentLoad is
v_id student.studID%type;
v_name student.studName%type;
v_sn studLoad.studName%type;
cursor cur_load is
select * from student;


begin
  open cur_load;
  loop
   fetch cur_load into v_id,v_name;

   exit when cur_load%notfound;
   select studName into v_sn from studLoad where studID = v_id;
   if(v_sn!= v_name) then
      update studLoad set studName= v_name where studID= v_id;
   else
      insert into studLoad values(v_id,v_name);
   dbms_output.put_line(v_id || ' ' || v_name);
   end if;
  end loop;
      close cur_load;
end;

它不起作用了。studLoad表中的行不会更新。我如何解决这个问题?在SQL server中,我们使用IF exists select…from stuLoad。。要检查表中是否存在该记录,有没有办法在Oracle中执行相同的操作?如果是,请告诉我同样的情况。

这是一种效率极低的方法。您可以使用该语句,这样就不需要使用游标、循环或不使用PL/SQL

MERGE INTO studLoad l
USING ( SELECT studId, studName FROM student ) s
ON (l.studId = s.studId)
WHEN MATCHED THEN
  UPDATE SET l.studName = s.studName
   WHERE l.studName != s.studName
WHEN NOT MATCHED THEN 
INSERT (l.studID, l.studName)
VALUES (s.studId, s.studName)
确保在完成后提交,以便能够在数据库中看到这一点

为了回答你的问题,我会这样做。这样做的好处是,大部分工作都是在SQL中完成的,并且只基于rowid(表中的唯一地址)进行更新

它声明了一个类型,您可以将数据批量放置在其中,每次10000行。然后分别处理这些行

然而,正如我所说,这将不会像合并那样有效


您的代码的可能副本无法正常工作,因为它没有执行您所说的操作。我很惊讶为什么它不抛出异常。在记录不匹配的情况下,未发现异常。用于评估是否需要插入记录的IF条件是错误的,因为它只会插入新的副本。如果studId在studLoad和student表中都是唯一的,Ben建议的解决方案可以很好地工作。为了限制更改的数量,从而减少撤消空间、重做日志和执行时间,我建议为new_studName!=在l.studName=s.studName的两个merge语句中的更新中,旧的\u studName和PL/SQL块中的更新可以以不同的方式完成,最好添加a.studName!=b、 游标的外部联接子句中的studName条件。@AlessandroRossi,您当然是正确的。我已经更新了。请查看线程。我希望承担建设性的责任。我该如何使用merge?如何调用插入到过程中的合并代码?开始进程名;终止我不在这里工作
declare

   cursor c_data is
    select b.rowid as rid, a.studId, a.studName
      from student a
      left outer join studLoad b
        on a.studId = b.studId
       and a.studName <> b.studName
           ;

   type t__data is table of c_data%rowtype index by binary_integer;
   t_data t__data;

begin

   open c_data;
   loop
      fetch c_data bulk collect into t_data limit 10000;

      exit when t_data.count = 0;

      for idx in t_data.first .. t_data.last loop
         if t_data(idx).rid is null then
            insert into studLoad (studId, studName)
            values (t_data(idx).studId, t_data(idx).studName);
         else
            update studLoad
               set studName = t_data(idx).studName
             where rowid = t_data(idx).rid
                   ;
         end if;
      end loop;

   end loop;
   close c_data;

end;
/