I have these two tables:
USERS(username, role_id)
COMMISSION_RATES(username, commission_rate)
users.username is the primary key, commission_rates.username is a foreign key.
I want to write a trigger, after an insert on users, check if role_id = 2, then insert into commission_rates the users.username, and 0 for commission rate.
This is what I have so far, it doesn't work though:
create or replace TRIGGER SETCOMISSIONRATE
AFTER INSERT ON USERS
BEGIN
CASE
WHEN users.role_id = 2 THEN
INSERT INTO COMISSION_RATE
(username,
comission_rate)
VALUES (
:NEW.username,
0)
END;
Any help would be appreciated
It should go like this:
CREATE OR REPLACE TRIGGER SETCOMISSIONRATE
AFTER INSERT ON USERS FOR EACH ROW
WHEN (new.role_id = 2)
BEGIN
INSERT INTO COMISSION_RATE (username, comission_rate)
VALUES (:new.username, 0);
END;
WHEN condition must be in the definition part, not in the body. They can only by used for row trigger.
create or replace
TRIGGER SETCOMISSIONRATE
AFTER INSERT ON USERS
FOR EACH ROW
WHEN (NEW.role_id = 2)
BEGIN
INSERT INTO COMISSION_RATE
(username,
comission_rate)
VALUES (
:NEW.username,
0)
END;
Related
I have a postgreSQL trigger for my social media project where once a comment is inserted, the trigger inserts a new row into the commentData table and the subscriptions table as shown below.
create or replace function public.initialize_comment_data_subscribe()
returns trigger as $$
begin
INSERT INTO "commentData" (comment_id, post_id, vote_count, children_count)
VALUES (new.id, new.post_id, 0, 0);
INSERT INTO subscriptions (comment_id, post_id, user_id, email)
VALUES (new.id, new.post_id, new.author_id, (SELECT email from users WHERE user_id = new.author_id));
RETURN NEW;
end;
$$ language plpgsql;
create trigger on_create_comment
after INSERT on comments
for each row execute procedure public.initialize_comment_data_subscribe();
When the email is null in the users table for a specific user_id, the whole thing fails due to the following line
... (SELECT email from users WHERE user_id = new.author_id));
But instead I would like the first insert to continue working and the second one to be skipped if the email is null.
How do I go about doing this? Or is it better to split the insert queries and have 2 triggers instead.
Do a SELECT INSERT instead:
INSERT INTO subscriptions (comment_id, post_id, user_id, email)
SELECT new.id, new.post_id, new.author_id, email
from users WHERE user_id = new.author_id AND email is not null
This is what I need to accomplish: Create a TRIGGER named tgr_customer_insert that will fire AFTER a row is inserted into the customers table.
The trigger can be created after you create the cardholder table, so it can be in the same ps16a.sql file just created. This trigger will insert a row into the cardholder table when a row is inserted into the temp_table_customers table. Here are the columns to insert:
card_number (this is inserted using the seq_cardholder sequence number)
customer_id (this is a bind variable from the temp_table_customer table using the :new.column_name syntax)
credit_limit (this is a bind variable from the temp_table_customer table using the :new.column_name syntax)
This is my code:
`CREATE OR REPLACE TRIGGER tgr_customer_insert
AFTER INSERT
ON customers
FOR EACH ROW
BEGIN
-- Insert record into customers table
INSERT INTO cardholder
( card_number,
customer_id,
credit_limit
)
VALUES
( new.seq_cardholder,
:new.customer_id,
:new.credit_limit
);
END;
`
Error is: ORA-24344: success with compilation error
Line 3 Position 4.
Hair is being torn out. Thank you in advance for you time with this matter.
I think you are missing a ':' in INSERT VALUES for first value binding.
CREATE OR REPLACE TRIGGER tgr_customer_insert
AFTER INSERT
ON customers
FOR EACH ROW
BEGIN
-- Insert record into customers table
INSERT INTO cardholder
( card_number,
customer_id,
credit_limit
)
VALUES
( :new.seq_cardholder,
:new.customer_id,
:new.credit_limit
);
END;
If, "seq_cardholder" is a sequence then you have to use as below:
CREATE OR REPLACE TRIGGER tgr_customer_insert
AFTER INSERT
ON customers
FOR EACH ROW
BEGIN
-- Insert record into customers table
INSERT INTO cardholder
( card_number,
customer_id,
credit_limit
)
VALUES
( seq_cardholder.nextval,
:new.customer_id,
:new.credit_limit
);
END;
When a user creates an application for the table 'application' I want a copy placed into the table 'application_history'. I've tried creating a trigger and get the error that is in the title.
create or replace TRIGGER create_history AFTER INSERT ON application
FOR EACH ROW
DECLARE
BEGIN
insert into application_history values (:new.arn, :new.srn, :new.job_id, :new.application_status);
END;
Any help will be much appreciated.
As Justin suspected, you seem to be having more than 4 columns in application_history. Either provide values for all columns or specify columns lie 'insert into table1 (col1, col2) values (1,2)'
It worked for me after adding extra column 'hist_id'(just to give you an idea) ...
create table application (arn number, srn number, job_id number, application_status char(1) );
create table application_history (hist_id number, arn number, srn number, job_id number, application_status char(1) );
create or replace TRIGGER create_application_history AFTER INSERT ON application
FOR EACH ROW
DECLARE
BEGIN
insert into application_history values (1, :new.arn, :new.srn, :new.job_id, :new.application_status);
END;
/
I think you need a / at the end. So:
create or replace TRIGGER create_history AFTER INSERT ON application
FOR EACH ROW
DECLARE
BEGIN
insert into application_history values (:new.arn, :new.srn, :new.job_id, :new.application_status);
END;
/
Ok , so I know that inserting information in a view based on two joined tables is impossible.
In order to do so , I need to create a trigger to insert the information in both tables , when an insert is made in that view.
For example :
CREATE VIEW myJoinedView AS
SELECT name,g.value from students
JOIN grades g on g.id=students.id;
The trigger is not working :
CREATE TRIGGER myTrigger
INSTEAD OF INSERT ON myJoinedView
BEGIN
INSERT INTO students
(name,value)
SELECT i.myJoinedView
FROM inserted i
INNER JOIN grades
ON i.id = grades.id
END myTrigger;
Then I'm trying to insert :
INSERT INTO myJoinedView VALUES ('Alex',10);
I don't know if the syntax is correct , I did not find any helpful documentation on this specific type of trigger.
I'm getting this error:
Error(10,46): PLS-00103: Encountered the symbol "end-of-file" when
expecting one of the following: ( begin case declare end exception
exit for goto if loop mod null pragma raise return select update
while with
<< continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall merge
pipe purge
Any help will be well received.
Thank you!
You need to either perform the inserts separately with separate single table insert or merge statements or by using a multi table insert (insert all) statement. Assuming you have a sequence to generate the id you are joining on for example this code will work in a very rudimentary way, but has some significant issues:
create table students ( id number primary key
, name varchar2(60));
create table grades( id number not null
, value number
, constraint grades_fk1 foreign key (id) references students(id));
create sequence student_id_seq;
create or replace view studentgrades as
select name, value from students s join grades g on s.id = g.id;
create or replace trigger studentgrades_ii_trg
instead of insert on studentgrades
begin
insert all into students(id, name) values (student_id_seq.nextval, name)
into grades(id, value) values (student_id_seq.nextval, value)
select :new.name name, :new.value value from dual;
end;
/
insert into studentgrades values ('Alex',10);
insert into studentgrades values ('Alex',8);
The BIG issue with the above trigger is that every time a grade is inserted for 'Alex' a new student record for 'Alex' is also created instead of reusing the previous student record for 'Alex'. That's probably not the desired behavior. Instead it should probably just insert a new grade record for Alex. One way to acheive this is for the studentgrades view to include the id column from the students table so you can uniquely identify which student to add the grade to, updating the trigger as needed:
create or replace view studentgrades as
select s.id, name, value from students s join grades g on s.id = g.id;
create or replace trigger studentgrades_ii_trg
instead of insert on studentgrades
declare
newid students.id%type;
begin
if :new.id is null then
newid := student_id_seq.nextval;
else
newid := :new.id;
end if;
insert all when :new.id is null
then into students(id, name) values (id, name)
else into grades(id, value) values (id, value)
select newid id, :new.name name, :new.value value from dual;
end;
/
insert into studentgrades values (null, 'Paul',10);
insert into studentgrades values (student_id_seq.currval, 'Paul',8);
However, now what happens if you try this:
insert into studentgrades values (student_id_seq.currval, 'Mary',10);
In this case the name is effectively ignored and Paul gets a new grade so again this isn't quite right. The question is should Paul's name be updated to Mary, or should a new student record for Mary be created, or should an exception be raised?
I have a trigger that I want to insert the same random value into two tables. How do I do this?
CREATE TRIGGER insertTrigger AFTER INSERT ON TableAB
BEGIN
INSERT INTO TableA(id, num) VALUES(RANDOM(), 1);
INSERT INTO TableB(id, num) VALUES(??, 1);
END;
I am not really using Random, but my own custom sqlite function which essentially does the same thing, but I need to remember that value to insert into TableB. How do I do that?
SQLite has no such thing as variables, but you could read the value from the record that you had just inserted into the first table:
CREATE TRIGGER insertTrigger
AFTER INSERT ON TableAB
BEGIN
INSERT INTO TableA(id, num) VALUES(RANDOM(), 1);
INSERT INTO TableB(id, num) SELECT id, 1
FROM TableA
WHERE rowid = last_insert_rowid();
END;