简体   繁体   中英

PL/SQL Trigger to update another table from INSERT on one table

I'm using SQL and an Oracle database and need some help - triggers are something I struggle to understand.

I need a trigger for when I insert a row into Table A so that it updates a row on Table B: specifically the row whose primary key matches the corresponding foreign key of the row that just been added to Table A.

So for example column X in Table A is a foreign key that references column Y in Table B (the primary key). When I add a row to Table AI need column Z of Table B to have 1 added to its numeric value in the row where column X = column Y.

This is what I have been able to get so far in SQL based on my limited understanding of triggers, in case it helps (I realise it's not very good, treat it as pseudocode):

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR UPDATE ON tableA
FOR EACH ROW

BEGIN
  UPDATE tableB
  SET columnZ = columnZ + 1
  WHERE tableA.columnX = tableB.columnY;
END test_trig;
/

Thanks

try this :

Syntax will be

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR UPDATE ON tableA
FOR EACH ROW

BEGIN
  UPDATE tableB
  SET columnZ = columnZ + 1
  WHERE tableB.columnX = :NEW.columnX;
END test_trig; 
/

:new.columnX reference the table A columnX.

good enough start.

first - let's get this out of the way - this is not well normalized - the value you describe seems like it should be calculated at runtime not at data manipulation time.

consider the following:

insert = +1 to the column - ok

update = ? not always +1 to the column i suppose - probably only when certain other data is modified. for example - what if i update table a set col1=col1. maybe what you want maybe not.

delete = ? does delete mean -1 to the column?

for syntax:

WHERE tableA.columnX = tableB.columnY;

should be

WHERE :new.columnX = tableB.columnY;

If tableB.columnZ represents the count of the referenced tableA records, there's no meaning triggering on tableA's UPDATE unless tableA's reference column can change.

First Ocasion: tableA.ReferenceColumn does not change:

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT ON tableA
FOR EACH ROW
BEGIN

  UPDATE tableB
  SET columnZ = columnZ + 1
  WHERE tableB.columnX = :NEW.columnX;
END test_trig;
/

Second Ocasion: tableA.ReferenceColumn does change:

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR UPDATE OF columnX ON tableA
FOR EACH ROW

BEGIN

  IF UPDATING AND nvl(:OLD.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ - 1
      WHERE tableB.columnX = :OLD.columnX;
  END IF:

  IF nvl(:NEW.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ + 1
      WHERE tableB.columnX = :NEW.columnX;  
  END IF;

END test_trig;
/

Third Ocasion: tablaA records can be deleted:

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR DELETE OR UPDATE OF columnX ON tableA
FOR EACH ROW

BEGIN
  IF (UPDATING OR DELETING) AND nvl(:OLD.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ - 1
      WHERE tableB.columnX = :OLD.columnX;
  END IF:

  IF nvl(:NEW.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ + 1
      WHERE tableB.columnX = :NEW.columnX;  
  END IF;
END test_trig;
/

I'm guessing you are implementing some mechanism for (A) keeping history (B) counter or (C) data integrity issue. if this is the case i would suggest performing the update using a pl/sql package that would handle all necessary updates/other DML operations. it's a best practice for the application to update data via pl/sql packages. this way you can control the process internally and it's much more easy to maintain. plus, you can save your self problems in the future when after you forget you have a trigger on that table.

one tip i can provide you about triggers - before you decide to use triggers make sure you've exhausted every other possibility .

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