简体   繁体   中英

PLSQL ORACLE: Errors with triggers

I am trying to make a trigger for a table PET that has a field Invitation and it turns Yes or No based on the value of a field called Phone from a table PEOPLE. If the phone value isn't null and some of the other fields in the PET table have valid values and aren't null, the value in Invitation field should turn to Yes .

I am able to do that but the problem is later on when I try to update my table and set one of the fields to null, it doesn't update the value of invitation field to No . So now I am working on making a trigger for the PET table itself that checks to see if the required fields are not null so that the value of invitation can be changed.

However, the problem is that the user has to enter data into the PET table before going towards the PEOPLE table. So my trigger isn't able to fetch any value when I am inserting data inside my table PET.

Here is what I did for the trigger:

create or replace trigger Phone_check
    before insert or update on PETS
    for each row
DECLARE
    SELECT phone INTO v_phone 
    FROM PEOPLE 
        INNER JOIN Family ON PEOPLE.ID=FAMILY.ID 
        INNER JOIN PETS ON FAMILY.ID=PETS.ID 
    WHERE PETS.ID=:NEW.ID;
    IF :NEW.NAME IS NOT NULL 
    AND :NEW.AGE IS NOT NULL 
    AND v_phone IS NOT NULL THEN
        :NEW.INVITATION:='Yes';
    ELSIF :NEW.NAME IS NULL 
    OR :NEW.AGE IS NULL 
    AND v_phone IS NULL THEN
       :NEW.INVITATION:='No';
    END IF;
END;

I get what the problem with this trigger is: there are no values in the people or family table yet. But the PET table is supposed to be the first table. How should I fix this? Is there a way to activate this trigger only after required values already exist inside other tables? I'm really confused.

"when in the end I change a value in one of the required fields in the PET tables and set it to null, The invitation still stays set to YES."

The condition in your trigger that drives changing the invitation to No is this:

ELSIF :NEW.NAME IS NULL 
OR :NEW.AGE IS NULL 
AND v_phone IS NULL THEN

So if PEOPLE.PHONE is not null the trigger won't go down that branch. It seems like what you want is:

ELSIF :NEW.NAME IS NULL 
OR :NEW.AGE IS NULL 
OR v_phone IS NULL THEN

The trigger will then act if you set PET.NAME or PET.AGE to null.


The business logic here is really confused. The conditions are based on the presence of records in three tables: this is a poor use case for a trigger. A better implementation would be to have a stored procedure to insert the records into all three tables and which manages the business rules such as setting the invitation flag.

Obviously this is a bit vague, but a proper solution will require more details about your scenario. What is you application? How are records are inserted? What is the Unit of Work (transaction)?

I think you are getting an error. Here is an example:

SQL> declare
  2  test number;
  3  begin
  4  select blocks into test from user_segments where segment_name='asdfasdfasdf';
  5  if test is not null then
  6    test := 1;
  7  end if;
  8  end;
  9  /
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 4

You can't test a variable from a select into when the select doesn't return a result without getting the no data found error. I usually just do a count.

SQL> declare
  2  test number;
  3  begin
  4  select count(blocks) into test from user_segments where segment_name='asdfasdfasdf';
  5  if test > 0 then
  6      select blocks into test from user_segments where segment_name='asdfasdfasdf';
  7      test := 1;
  8  end if;
  9  end;
 10  /

PL/SQL procedure successfully completed.

A select count on a table that exists will return a value.

Bobby

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM