Oracle 过程中的更新查询更新为错误值

发布于 2024-12-14 18:36:08 字数 1165 浏览 5 评论 0原文

下面提到的过程旨在:

  1. 从 cpTemplateWorkCard 中存在的 cp_work_card 中获取 jobid
  2. 从 cp_work_card 中获取该 jobid 的第一条 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;

The below mentioned procedure is intended to:

  1. fetch jobids from cp_work_card which exist in cpTemplateWorkCard
  2. Fetch the first record of bhours for the jobid from the cp_work_card
  3. update the same to cpTemplateworkCard

Hwoever, all the rows of cpTemplateworkCard are updated with the value of bHours found in last row. But, the values in the variable are stored correctly while execution

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

掩耳倾听 2024-12-21 18:36:12

如果您的语句/条件全部正确,则执行以下语句而不是存储过程应该完全符合您的要求:

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);

IF your statements/conditions are all correct then executing the following statement instead of your stored procedure should do exactly what you want:

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);
自我难过 2024-12-21 18:36:11

难道不能用一条 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,这也恰好是表 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;

Couldn't you achieve the same with a single SQL update statement?

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);

I haven't tested this but the principle is the same...

EDIT: Given your constraints and if you must use a procedure then could you not:

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;

EDIT:
FYI, your current procedure isn't working because you have named your variable holding the job ID as jobId which also happens to be the name of a column in the table cptemplateworkcard. Therefore when you perform your update it defaults to thinking your WHERE clause is comparing the table column with itself thereby updating every row with whatever the value of bHours is. When the procedure has finished, obviously the last value of bHours what the final value returned from the cursor hence you are seeing all the values in the table set to this final value.

If you rename your jobId variable to something like v_jobid then it should solve the problem.

Hope it helps...

If the only constraint is that it must be in a PL/SQL procedureal block then this will be the most efficient procedure:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文