I have this trigger, and I am getting an arror message when I run it; "bad bind variable".
I can't seem to see where the problem lies. Any help would be appreciated.
create or replace TRIGGER trg_placed AFTER UPDATE
OF STATUS_ID ON STATUS
FOR EACH ROW
BEGIN
IF :new.STATUS_ID = 7
THEN
UPDATE STUDENT
SET PLACED_Y_N = 'Y'
WHERE RECORD_NUMBER = :NEW.record_number;
END IF;
END;
try like this:
create or replace TRIGGER trg_placed AFTER UPDATE
OF STATUS_ID ON STATUS
REFERENCING OLD AS o NEW AS n
FOR EACH ROW
BEGIN
IF n.STATUS_ID = 7
THEN
UPDATE STUDENT
SET PLACED_Y_N = 'Y'
WHERE RECORD_NUMBER = n.record_number;
END IF;
END;
If you use lowercase for Oracle objects, you'll have to surround object names with quotes (") and match the case exactly to get it to work.
like this
create or replace TRIGGER trg_placed AFTER UPDATE
OF STATUS_ID ON STATUS
FOR EACH ROW
BEGIN
IF :new.STATUS_ID = 7
THEN
UPDATE STUDENT
SET PLACED_Y_N = 'Y'
WHERE RECORD_NUMBER = :NEW."record_number"; --quotes (") required for column name.
END IF;
END;
Related
I'm trying to make a trigger to avoid inserting data in the table for this reason:
If a patient is dead he can't make a visit.
I made a function that return a 1 if the patient is dead and I call it on the trigger. That's the code:
CREATE OR REPLACE FUNCTION check_d (pd INTEGER)
RETURN INTEGER
IS
d Patient.d_date%TYPE;
BEGIN
SELECT P.d_Date INTO d
FROM Patient P
WHERE P.idP=pd;
IF d <> NULL THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
CREATE OR REPLACE TRIGGER bad_insert
BEFORE INSERT ON Visit
FOR EACH ROW
DECLARE
idd INTEGER;
dp Visit.id_PV%TYPE;
BEGIN
SELECT V.id_PV INTO dp
FROM Visit V
WHERE id_PV=:NEW.id_PV;
idd := check_d(dp);
IF idd = 1 THEN
RAISE_APPLICATION_ERROR(-20014,'Error. Patient Deceased.');
END IF;
END;
/
The function should be ok, the problem is in thet trigger.
Visit.id_PV is a Foreign Key to Patient.idP(PRIMARY KEY) anyway. How should I modify the code? Thanks.
Your function is not correct
d <> NULL
Will always return UNKNOWN, instead you have to check for nulls like:
d is not null
Once you've fixed that, you still have to work around the mutating table error you'd receive when you try an insert statement (did you not receive this when you tried it?). You are referencing the same table you are inserting into within your trigger. You can't do that. Instead you should reference the column you want using :new.id_PV .
I think the problem is located here :
IF d <> NULL THEN
Change it to :
IF d IS NOT NULL THEN
In the current case, you'll get no_data_found exception because of the query within the trigger. Moreover, you do not need to return the value for id_PV column that you already have as :NEW.id_PV, and such attempt mostly end with mutating trigger error. So , rearrange your trigger as
CREATE OR REPLACE TRIGGER bad_insert
BEFORE INSERT ON Visit
FOR EACH ROW
BEGIN
IF check_d(:NEW.id_PV) = 1 THEN
RAISE_APPLICATION_ERROR(-20014, 'Error. Patient Deceased.');
END IF;
END;
/
while getting rid of redundant local variables.
The function might also be made brief such as
CREATE OR REPLACE FUNCTION check_d (pd Visit.id_PV%type) RETURN INT IS
val INT;
BEGIN
SELECT NVL(SUM(NVL2(P.d_Date,1,0)),0)
INTO val
FROM Patient P
WHERE P.idP=pd;
RETURN val;
END;
/
Demo
I have a requirement of which I want to create a trigger in Oracle.
So what I want is: I have a table called XXCUS.XXACL_PN_PROSPECT_TRL in which there is a column called ACTION whose default value is set as RELEASE, EXTEND and CANCEL.
So my trigger would be on the table XXCUS.XXACL_PN_PROSPECT_TRL as
whenever the column ACTION has values as
RELEASE then the other table column should get UPDATED as R with the same matching ID
EXTEND then the other table column should get UPDATED as O with the same matching ID
CANCEL then the other table column should get UPDATED as C with the same matching ID
The other table name is xxcus.xxacl_pn_leases_all whose column needs to be updated. Also the column name is CLOSE_FLAG.
I m trying like below
CREATE [ OR REPLACE ] TRIGGER XXACL_PN_PROSPECT_T
BEFORE INSERT
ON XXCUS.XXACL_PN_PROSPECT_TRL
[FOR EACH ROW]
DECLARE
-- variable declaration
BEGIN
-- trigger code
Insert into XXCUS.XXACL_PN_PROSPECT_TRL -- values for ACTION here
then
update xxcus.xxacl_pn_leases_all if 'RELEASE' then 'R', if 'EXTEND' then 'O' where mkey = dynamic
EXCEPTION
WHEN ...
-- exception handling
END;
but it is not working as I am not champ in creating Triggers. Kindly help me with this
There are some obvious syntax errors
You don't need square brackets. Those are in the documentation to indicate optional parts.
Your insert/update statements are wrong, need to correct them.
It should look on the lines of :
CREATE OR REPLACE TRIGGER XXACL_PN_PROSPECT_T
BEFORE INSERT
ON XXCUS.XXACL_PN_PROSPECT_TRL
DECLARE
-- variable declaration
BEGIN
UPDATE xxcus.xxacl_pn_leases_all
SET CLOSE_FLAG = DECODE(:NEW.ACTION, 'RELEASE','R','EXTEND','O', 'CANCEL','C')
WHERE ID = :NEW.ID
END;
This trigger will update CLOSE_FLAG column of xxcus.xxacl_pn_leases_all based on what value comes in Action column of XXACL_PN_PROSPECT_TRL table.
While going through the links and documentation, I tried my self and figured out the solution.
There were many syntax errors in the starting. But I guess, I was the only one to apply the exact logic and took help of the syntax online.
So here it was my TRIGGER which I wrote and it worked perfectly.
CREATE OR REPLACE TRIGGER xxcus.xxacl_pn_prospect_trl_trg
AFTER INSERT OR UPDATE
ON xxcus.xxacl_pn_prospect_trl
FOR EACH ROW
DECLARE
sql_error VARCHAR (10000);
v_mkey NUMBER;
v_action VARCHAR (10);
BEGIN
v_action := :NEW.action;
IF (v_action = 'Extend')
THEN
UPDATE xxcus.xxacl_pn_leases_all
SET no_of_days = :NEW.current_action_days
WHERE lease_num = :NEW.lease_no;
ELSIF (v_action = 'Release')
THEN
UPDATE xxcus.xxacl_pn_leases_all
SET no_of_days = 0,
close_flag = 'R'
WHERE lease_num = :NEW.lease_no;
ELSE
UPDATE xxcus.xxacl_pn_leases_all
SET no_of_days = 0,
close_flag = 'C'
WHERE lease_num = :NEW.lease_no;
END IF;
EXCEPTION
WHEN OTHERS
THEN
sql_error := SQLERRM; END;/
This is my SQL trigger and it is suppose to change the reorder value to Y or N depending if ON_HAND is less than or greater than the MINIMUM. The problem is it's ignoring the set statement completely. Do I have to arrange these differently?
CREATE OR REPLACE TRIGGER TRG_REORDER
AFTER UPDATE OF ON_HAND, MINIMUM ON PART
BEGIN
IF ON_HAND <= MINIMUM THEN
SET REORDER = 'Y';
ELSE ON_HAND > MINIMUM
SET REORDER = 'N';
END IF;
END;
Trigger bodies use PL/SQL syntax, not SQL. So for assignment you need := not set.
Your code has some other syntax errors.
You need to refer to the :new values of the columns.
You don't need a condition in the ELSE clause.
In order to modify the values of columns in a trigger, it must be a BEFORE trigger and fire FOR EACH ROW.
So fixing all that, this should now work for you (caveat: untested code).
CREATE OR REPLACE TRIGGER TRG_REORDER
before UPDATE OF ON_HAND, MINIMUM ON PART
for each row
BEGIN
IF :new.ON_HAND <= :new.MINIMUM THEN
:new.REORDER = 'Y';
ELSE
:new.REORDER = 'N';
END IF;
END;
I don't know Oracle triggers but I suspect you want a BEFORE trigger and an assignment that looks something like this.
:new.REORDER := case when :new.ON_HAND <= :new.MINIMUM then 'Y' else 'N' end;
Check here to get started:
http://www.techonthenet.com/oracle/triggers/before_update.php
I'm very new in SQL and PostgreSQl, and I need a desperate answer for the following question:
I have the next two tables with the following information:
MATCH_STATISTICS
MATCH
With these two tables I need make a TRIGGER wich adds the player from MATCH_STATISTICS to MATCH with the MAX value from 'mvp_score'.
In other words, I want to add the most valuable player from MATCH_STATISTICS to MATCH but with one condition:
* If there are two players with the same mvp_score, the most valuable player stored will be that one with the MAX minutes played.
I am capable to do the first TRIGGER with the max value but when I have two duplicate values the code adds the last modified.
Anyone knows how to do that? The TRIGGER should act after INSERT, UPDATE or DELETE
Thanks so much and sorry for my bad english...
Finally I found a way to make a TRIGGER wich solves my problem, the code is...
CREATE OR REPLACE FUNCTION mvp_player_equal()
RETURNS trigger AS $$
DECLARE
max_points INTEGER;
BEGIN
SELECT MAX(mvp_score)
INTO max_points
FROM MATCH_STATISTICS;
IF (TG_OP = 'INSERT') THEN
IF max_points = NEW.mvp_score THEN
UPDATE match SET mvp_player = (SELECT player FROM MATCH_STATISTICS WHERE minutes_played =
(SELECT MAX(minutes_played) FROM MATCH_STATISTICS WHERE mvp_score = NEW.mvp_score)
AND mvp_score = NEW.mvp_score) WHERE home_team = NEW.home_team AND visitor_team = NEW.visitor_team;
END IF;
RETURN NULL;
ELSIF (TG_OP = 'UPDATE') THEN
IF max_points = NEW.mvp_score THEN
UPDATE match SET mvp_player = (SELECT player FROM MATCH_STATISTICS WHERE minutes_played =
(SELECT MAX(minutes_played) FROM MATCH_STATISTICS WHERE mvp_score = NEW.mvp_score)
AND mvp_score = NEW.mvp_score) WHERE home_team = NEW.home_team AND visitor_team = NEW.visitor_team;
END IF;
RETURN NULL;
END IF;
END;
$$LANGUAGE plpgsql;
CREATE TRIGGER mvp_player_equal AFTER INSERT OR DELETE OR UPDATE OF
mvp_score ON MATCH_STATISTICS
FOR EACH ROW
EXECUTE PROCEDURE mvp_player_equal();
But as in the previous comments is talked, that's not the better way to fix this issue. There are better ways like Gordon Linoff and a_horse_with_no_name said.
I have a table in oracle database that has two fields: status and notes. There are only 3 actual values for status field: active, not-active, removed.
When status is active, by default notes field has nothing in it.
If status is changed to not-active, notes will have value entered.
by the user
If status is changed back to active, I need notes field value removed.
I've never used triggers before so for me it's a bit complicated but here is what I have:
CREATE TRIGGER update_notes
AFTER UPDATE ON table1
FOR EACH ROW
BEGIN
IF status = 'Active' THEN UPDATE table1 SET notes = '';
END IF;
END;
But it fails.. What have I missed?
Don't use an update statement, just assign the value:
CREATE TRIGGER update_notes
BEFORE UPDATE ON table1
FOR EACH ROW
BEGIN
IF :new.status = 'Active' THEN
:new.notes = null;
END IF;
END;
Btw: tables have columns, not "fields"
Could you please try below..
CREATE TRIGGER update_notes
AFTER UPDATE ON table1
FOR EACH ROW
BEING
IF :NEW.status = 'Active' THEN
:NEW.notes = '';
END IF;
END;
/