запрос на обновление в процедуре Oracle обновлен с неверным значением - PullRequest
0 голосов
/ 09 ноября 2011

Следующая процедура предназначена для:

  1. выборки заданий из карты cp_work_card, существующей в cpTemplateWorkCard
  2. выборка первой записи bhours для задания из карты cp_work_card
  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;

Ответы [ 2 ]

1 голос
/ 09 ноября 2011

Не могли бы вы добиться того же с помощью одного оператора обновления 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;

РЕДАКТИРОВАТЬ: К вашему сведению, ваша текущая процедура не работает, потому что вы назвали свою переменную, содержащую идентификатор задания, как 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;
0 голосов
/ 09 ноября 2011

Если все ваши утверждения / условия верны, то выполнение следующего утверждения вместо хранимой процедуры должно делать именно то, что вы хотите:

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