how to create trigger on derived table? - sql

I have created two tables customer and orders and I have already inserted some data in customer table but nothing is in orders table. Now I want to create a trigger on orders table that would copy only the id column ( which is defined in customer table as primary key) in orders table of o_id ( which is defined as foreign key in orders table ).
I want to check my created trigger and fix it if you find any error in it.
My trigger for orders table :
CREATE OR REPLACE TRIGGER tri_order
BEFORE INSERT
ON orders
FOR EACH ROW
BEGIN
SELECT ID
INTO :NEW.o_id
FROM customer;
END;
Thanks.

I want to create a trigger on orders table that would copy only the
id column
you can start doing like this , (by the way I didnt understand where you want to use your derived table ? what is the query)
CREATE OR REPLACE TRIGGER tri_order
BEFORE INSERT
ON orders
FOR EACH ROW
declare cnt number (3);
BEGIN
select count(1) into cnt from customer where id=:new.id; // its is checking
if cnt=0 then
insert into customer (id) values (:new.id);
end if;
// you can add raise error here
END;
/

you want to copy a value from customer table to orders table with help of trigger so firstly you will be needing to create the trigger on customertable not on orderstable ,since for every insert done in the customer table the trigger will be fired once which will insert a value in orders table.
CREATE OR REPLACE TRIGGER tri_order
AFTER INSERT
ON customer
FOR EACH ROW
BEGIN
INSERT INTO orders
(o_id)
SELECT :NEW.ID
FROM customer;
END;

You must specify a rule for finding the customer.
For example:
CREATE OR REPLACE TRIGGER tri_order
BEFORE INSERT
ON orders
FOR EACH ROW
BEGIN
SELECT c.ID
INTO :NEW.o_id
FROM customer c
WHERE c.customer_code = :NEW.customer_code;
END;

Related

How do I update table A while adding rows on table B?

My table A is about item records in the stock and table B is about purchase record.
https://ibb.co/KyJzXZm
When customer makes a purchase, table B will be updated, showing the purchase_id, item_id and item_quantity. At the same time, the same item in table A will be updated and reduced by the quantity in table B. Therefore the item quantity in table A should be (4 - 3 = 1). Table A should be updated whenever I update table B. Does anyone know how to do it? Thank you!!!
I have figured out a way to do so.
Just create a log table for table B. Then create a trigger on "After Insert"
on table B, update the log table. By doing so, you will get a New.item_id and New.item_quantity. Then create another trigger, "After Insert" on table B, then update table A,
SET item_quantity = item_quantity - New.item_quantity WHERE item_id = New.item_id
Below is my original code,
DELIMITER //
CREATE TRIGGER purchase_log_insert
AFTER INSERT ON purchase
FOR EACH ROW
BEGIN
INSERT INTO log_purchase (action, purchase_id_new, item_id_new, purchase_quantity_new, timestamp)
VALUES ('insert', NEW.purchase_id, NEW.item_id, NEW.purchase_quantity, NOW());
END; //
DELIMITER ;
DELIMITER //
CREATE TRIGGER change_item
AFTER INSERT ON purchase
FOR EACH ROW
BEGIN
UPDATE item
SET item_quantity = item_quantity - NEW.purchase_quantity WHERE item_id = NEW.item_id;
END; //
DELIMITER ;

Get table does not exist error, when trying to insert into table from a trigger

I'm attempting to use a trigger to fill values of another table. The trigger watches for insert on table ratings and updates the values of another table, top5restaurants. I haven't figured out how to maintain only the top 5 in top5restaurants, I don't know how to limit a table to a certain number of entries. But right now I can't seem to do anything to top5restaurants from within the trigger.
drop view top_rest;
create view top_rest (rid, rat)
as
(select distinct rid, max(stars)
from rating
group by rid);
drop table top5restaurants;
create table top5restaurants(rid int);
insert into top5restaurants(rid)
select rid from top_rest
where rownum <= 5
order by rat asc;
create or replace trigger top5_trigger
after insert on ratings
for each row
declare top5 top5restaurants%rowtype;
cursor top5_cursor is
select rid from top_rest
where rownum <=5
order by rat;
begin
for record in top5_cursor
loop
fetch top5_cursor into top5;
insert into top5restaurants values(top5);
end loop;
end;
/
--
--
begin
update_reviews('Jade Court','Sarah M.', 4, '08/17/2017');
update_reviews('Shanghai Terrace','Cameron J.', 5, '08/17/2017');
update_reviews('Rangoli','Vivek T.',3,'09/17/2017');
update_reviews('Shanghai Inn','Audrey M.',2,'07/08/2017');
update_reviews('Cumin','Cameron J.', 2, '09/17/2017');
end;
/
select * from top5restaurants;
insert into top5restaurants values(184);
However, the table does exist and I can run queries on it and it returns the data I inserted when I created the table. I can also insert values. Not sure why I get table not found error when using a trigger.
Apart from the difference in table names(answer by Littlefoot) in the trigger and view, You have not used the rowtype collection properly while inserting the data.
you must remove the brackets:
replace
insert into top5restaurants values(top5);
with
insert into top5restaurants values top5;
Cheers!!
You didn't post all tables involved, but - what is obvious, is that view is created as
create view top_rest ... from rating
------
while trigger is created as
after insert on ratings
-------
^
s?
Which one is it? rating or ratings?

INSERT TRIGGER AFTER UPDATE ANOTHER TABLE

There are 2 tables orders and pizza. I have to create trigger update_order_pizza which will insert row in table order_pizza after new row is inserted in table order ( or when row is updated).
Code under trigger work when I launch in SQL, but I don't see what changes in table order_pizza after I inserted row in order.
CREATE DEFINER=`root`#`localhost` TRIGGER `update_order_pizza` AFTER INSERT ON `orders` FOR EACH ROW BEGIN
set #orderid = (select max(order_id) from orders);
set #pizzaid = (select max(pizza_id) from pizza);
insert into order_pizza(order_id,pizza_id)
values(#orderid,#pizzaid);
END
I expect to see next
If I insert new order , let;s say order id=36 in table order_pizza should be inserted new record (36,64)
Your code should be using the new variable to reference rows. In addition, your tables should be defining the ids as auto-increment.
So, the code should look more like this:
create trigger `update_order_pizza` after update on `orders`
for each row
begin
insert into order_pizza (order_id)
values (new.order_id);
end;
Alternatively, the pizza_id might be in the orders table, and you may intend:
insert into order_pizza (order_id, pizza_id)
values (new.order_id, new.pizza_id);

Creating Oracle SQL Trigger Error

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;

Oracle SQL Creating Trigger to Increment a Sequence Number For Each Row

I'm trying to create a trigger but I have learned I can not design it as in my first attempt, which I'm showing below. This will cause a 'mutating table' error due to selecting from the table as it is being modified. It actually didn't cause this error when inserting only one record at a time, but when I insert multiple records at once it does.
The purpose of the trigger is to count the number of records in the table where the customer is equal to the customer about to be inserted, and to set the new order_num value as count+1. I also have a public key value set by the trigger which draws from a sequence. This part works ok once I remove the order_num part of the trigger and the associated SELECT. How can I achieve what I am trying to do here? Thanks in advance.
CREATE OR REPLACE TRIGGER t_trg
BEFORE INSERT ON t
FOR EACH ROW
DECLARE
rec_count NUMBER(2,0);
BEGIN
SELECT COUNT(*) INTO rec_count
FROM t
WHERE customer_id = :NEW.customer_id;
:NEW.order_num:= rec_count+1;
:NEW.order_pk_id:= table_seq.NEXTVAL;
END;
Two triggers and temp table approach can provide solution to you seek, preventing mutating table error. However performance will most likely suffer.
create global temporary table cust_temp(customer_id number, cust_cnt number);
create or replace trigger t_trig1
before insert on t
declare
begin
insert into cust_temp select customer_id, count(*) from t group by customer_id;
end;
/
CREATE OR REPLACE TRIGGER t_trg2
BEFORE INSERT ON t
FOR EACH ROW
DECLARE
rec_count number;
BEGIN
BEGIN
SELECT cust_cnt INTO rec_count
FROM cust_temp
WHERE customer_id = :NEW.customer_id;
EXCEPTION when no_data_found then rec_count := 0;
END;
:NEW.order_num:= rec_count+1;
:NEW.order_pk_id:= table_seq.NEXTVAL;
update cust_temp set cust_cnt = rec_count + 1
where customer_id = :NEW.customer_id;
END;
/