3

I am trying to declare a variable and accessing it again to update same table for a particular id.(Updating STATUS from 'E' to 'R')

create or replace trigger resume_trgr
before update on temp_jobs

DECLARE
job_status varchar(2);

begin
  select STATUS into :job_status from temp_jobs where id=6120;
  if :job_status='E'
  then
    update temp_jobs set STATUS='R' where id=6120;
  end if;
end;
/

But it returning error while executing above code. Error code is below:

Trigger resume_trgr compiled

 Errors: check compiler log

 Error(5,27): PLS-00049: bad bind variable 'STATUS'
1
  • 2
    It seems odd to have a statement level trigger that hits a specific row on the same table (it'll fire again for the internal update, for a start); but in any case the error doesn't see to match the code. In what you have posted, job_status is a local variable not a bind variable, so that should not have have a colon prefix. But it's not clear what you are really doing or seeing... Commented Oct 22, 2018 at 11:36

2 Answers 2

3

In the question you said that the error refers to STATUS, but that doesn't match your posted code You shoudl be getting two errors referring to JOB_STATUS.

That's because it's defined as a local variable, and you're trying to refer to it as a bind variable. It should not have the colon prefix; so this compiles:

create or replace trigger resume_trgr
before update on temp_jobs
declare
  job_status temp_jobs.status%type;
begin
  select STATUS into job_status from temp_jobs where id=6120;
  if job_status='E'
  then
    update temp_jobs set STATUS='R' where id=6120;
  end if;
end;
/

as does this, which skips the variable completely:

create or replace trigger resume_trgr
before update on temp_jobs
begin
  update temp_jobs set STATUS='R' where id=6120 and status = 'E';
end;
/

Whether that's a useful, valid or sensible thing to be doing inside a trigger is another matter. It seems like a separate update you should be doing manually before your 'real' update, possibly in a procedure - if you really want to always update the row for that specific ID regardless of whatever else you are actually doing in your 'real' (triggering) update.

If what you are really trying to do is make sure the status changes to R even if the caller doesn't explicitly do that, then you probably want a row-level trigger that sets the pseudorow value, rather than a statement-level trigger with a hard-coded ID.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Alex. I tried your suggestion. But it giving two different errors. One is table is mutating, trigger/function may not see it Another is (after I done few changes) It firing trigger in loop undefined times.
Yes. I still think you really want a row-level trigger, but it's unclear - particularly why you have a hard-coded ID.
2

Error you got is ... well, strange. A few comments:

  • There's no variable STATUS in your code.
  • When selecting into a variable, you don't need a colon (i.e. it is not into :job_status but into job_status).
  • You should rather use VARCHAR2 datatype, not VARCHAR.
  • That should, probably, be a row-level trigger (so you miss the FOR EACH ROW) and, once you fix everything, you'll hit the mutating table error
  • Why did you hardcode ID? Is this really going to do something only for that ID?

What you might do is this: first, test case:

SQL> create table temp_jobs
  2    (id number,
  3     status varchar2(10));

Table created.

SQL> insert into temp_jobs values (1, 'E');

1 row created.

SQL> insert into temp_jobs values (6120, 'E');

1 row created.

SQL> select * from temp_jobs;

        ID STATUS
---------- ----------
         1 E
      6120 E

Trigger: note the differences between your and my code.

SQL> create or replace trigger resume_trgr
  2    before update on temp_jobs
  3    for each row
  4  DECLARE
  5    JOB_STATUS VARCHAR2(2);
  6  begin
  7    :new.status := case when :old.status = 'E' then 'R'
  8                        else :new.status
  9                   end;
 10  end;
 11  /

Trigger created.

Testing:

SQL> update temp_jobs set status = 'Y' where id = 6120;

1 row updated.

SQL> select * from temp_jobs;

        ID STATUS
---------- ----------
         1 E
      6120 R

SQL> update temp_jobs set status = 'Y' where id = 6120;

1 row updated.

SQL> select * from temp_jobs;

        ID STATUS
---------- ----------
         1 E
      6120 Y

SQL>

2 Comments

I am trying to reset(From E to R) the value for specific row by using where clause. I hope above code will consider all rows whose values are updating.
It should (including ID = 6120).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.