declare and call variable in trigger in oracle

Viewed 14414

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'
2 Answers

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.

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>
Related