0

下面提到的程序旨在:

  1. 从 cpTemplateWorkCard 中存在的 cp_work_card 获取 jobid
  2. 从 cp_work_card 中获取 jobid 的第一条记录
  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 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 的变量命名为该变量jobId也恰好是 table 中列的名称cptemplateworkcard。因此,当您执行更新时,它默认认为您的WHERE子句正在将表列与其自身进行比较,从而用 的值更新每一行bHours。过程完成后,显然是bHours从游标返回的最终值的最后一个值,因此您会看到表中的所有值都设置为该最终值。

如果您将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 回答