3

私は2つのテーブルを持っていますstudent-そしてstudLoad両方とも2つのフィールドstudIDとを持っていますstudNamestudentテーブルからテーブルにデータをロードしたい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で同じことを行う方法はありますか?もしそうなら、私に同じことを知らせてください。

4

2 に答える 2

16

これは非常に非効率的な方法です。ステートメントを使用できmerge、カーソル、ループ、または(なしで実行できる場合は)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)

commitこれをデータベースで確認できるようにするには、完了したら必ず確認してください。


実際にあなたの質問に答えるために、私はそれを次のようにします。これには、SQLでほとんどの作業を実行し、テーブル内の一意のアドレスであるROWIDに基づいてのみ更新するという利点があります。

一度に10,000行のデータをまとめて配置する型を宣言します。次に、これらの行を個別に処理します。

ただし、私が言うように、これは。ほど効率的ではありません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;
/
于 2012-08-12T11:50:07.717 に答える
0

手順を使用する場合は、次の行を変更することを検討してください。

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;
        begin
           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;
           end if;
        exception
           when no_data_found then
                insert into studLoad values(v_id,v_name);
        end;
        dbms_output.put_line(v_id || ' ' || v_name);
    end loop;
    close cur_load;
end;

私はそれがうまくいくはずだと思います、それをテストしませんでした。

于 2021-10-22T13:56:33.743 に答える