0

以下の手順は、次のことを目的としています。

  1. cpTemplateWorkCard に存在する cp_work_card からジョブ ID を取得します
  2. cp_work_card からジョブ ID の bhours の最初のレコードを取得します
  3. 同じものを cpTemplateworkCard に更新します

ただし、cpTemplateworkCard のすべての行は、最後の行で見つかった bHours の値で更新されます。ただし、変数の値は実行中に正しく保存されます

DECLARE
     jobId       VARCHAR2(30);
     bHours      float;
     idx         NUMBER(4,0);
     CURSOR         c1 
     IS
        select distinct 
               cp.job_id 
          from cp_work_card cp,
               cptemplateworkcard temp 
         where cp.job_id = temp.JOBID;
BEGIN
   idx:=1;
   DBMS_OUTPUT.PUT_LINE('id : jobId  :  bHours');
   OPEN c1;
   LOOP
      FETCH c1 INTO jobId;
      EXIT WHEN C1%NOTFOUND;
      select cpw.BUDGET_HOUR 
        into bHours 
        from cp_work_card cpw 
       where cpw.job_id=jobId 
         AND rownum<2;
      /*DBMS_OUTPUT.PUT_LINE('Budget Hours: '||bHours);

      UPDATE TO CPTEMPLATE*/

      UPDATE cptemplateworkcard tmpCard 
         SET tmpCard.BUDGET_HOUR=bHours 
       where tmpCard.JOBID=jobId;

      DBMS_OUTPUT.PUT_LINE(idx || ' : ' || jobId || ' : ' || bHours);
      idx:= idx+1;

   END LOOP;

   CLOSE c1;
END;
4

2 に答える 2

1

単一の SQL update ステートメントで同じことを達成できませんでしたか?

UPDATE cptemplateworkcard tmpcard
   SET tmpcard.budget_hour = (SELECT budget_hour
                                FROM cp_work_card cp
                               WHERE cp.job_id = tmpcard.jobid
                                 AND rownum < 2)
 WHERE EXISTS
      (SELECT 1 
         FROM cp_work_card cp
        WHERE cp.job_id = tmpcard.jobid);

私はこれをテストしていませんが、原理は同じです...

編集:制約があり、プロシージャを使用する必要がある場合は、次のことはできません:

DECLARE
   CURSOR c1
   IS
      SELECT DISTINCT
             cp.job_id,
             cp.budget_hour
        FROM cp_work_card cp
       INNER JOIN cptemplateworkcard temp
          ON (cp.job_id = temp.jobid)
       WHERE rownum < 2;
BEGIN
   DBMS_OUTPUT.put_line( 'job_id  :  budget_hour' );

   FOR c_rec IN c1
   LOOP
      UPDATE cptemplateworkcard tmpcard
         SET tmpcard.budget_hour = c_rec.budget_hour
       WHERE tmpcard.jobid = c_rec.job_id;

      DBMS_OUTPUT.put_line( c_rec.job_id || ' : ' || c_rec.budget_hour );
   END LOOP;
END;

編集: 参考までに、テーブル内の列の名前でもあるジョブ ID を保持する変数に名前を付けたため、現在の手順は機能していません。したがって、更新を実行すると、デフォルトで、句がテーブルの列をそれ自体と比較していると考えられ、それによってすべての行が値が何であれ更新されます。プロシージャが終了すると、明らかに最終値がカーソルから返された最後の値であるため、テーブル内のすべての値がこの最終値に設定されていることがわかります。jobIdcptemplateworkcardWHEREbHoursbHours

jobId変数の名前を次のように変更するv_jobidと、問題が解決するはずです。

それが役に立てば幸い...

PL/SQLプロシージャ・ブロック内に存在する必要があるという唯一の制約がある場合、これが最も効率的なプロシージャになります。

BEGIN
   UPDATE cptemplateworkcard tmpcard
      SET tmpcard.budget_hour = (SELECT budget_hour
                                   FROM cp_work_card cp
                                  WHERE cp.job_id = tmpcard.jobid
                                    AND rownum < 2)
    WHERE EXISTS
         (SELECT 1 
            FROM cp_work_card cp
           WHERE cp.job_id = tmpcard.jobid);

   DBMS_OUTPUT.put_line(SQL%rowcount||' record(s) updated');
END;
于 2011-11-09T11:10:54.483 に答える
0

ステートメント/条件がすべて正しい場合は、ストアド プロシージャの代わりに次のステートメントを実行すると、必要なことが正確に実行されます。

UPDATE cptemplateworkcard tc 
SET tc.BUDGET_HOUR=(SELECT cpw.BUDGET_HOUR FROM cp_work_card cpw where cpw.job_id=tc.JOBID AND rownum<2)
WHERE tc.JOBID IN (select cp.job_id from cp_work_card cp);
于 2011-11-09T11:10:03.897 に答える