I'm trying to create a trigger on SQLITE to automatically add tuples to another table when something is added to a certain table, but firstly, I want to check if what I'm adding belongs to another third table.
This is my trigger:
DROP TRIGGER IF EXISTS atualizaBibliotecas;
CREATE TRIGGER atualizaBibliotecas
AFTER INSERT ON FoiComprado
FOR EACH ROW
BEGIN
SELECT CASE
WHEN
(
SELECT count(*)
FROM Album
WHERE idItem = NEW.idItem
) <> 0
THEN INSERT INTO Possui(idItem, email, dataAquisicao) VALUES(11,'aaaa#bbbb.com', '2019-05-14');
END;
This is the error I'm receiving:
Error: near line 8: near "INSERT": syntax error
LINE 8:
CREATE TRIGGER atualizaBibliotecas
I believe that you want :-
CREATE TRIGGER atualizaBibliotecas
AFTER INSERT ON FoiComprado
FOR EACH ROW
WHEN
(
SELECT count(*)
FROM Album
WHERE idItem = NEW.idItem
) <> 0
BEGIN
INSERT INTO Possui(idItem, email, dataAquisicao) VALUES(11,'aaaa#bbbb.com', '2019-05-14');
END;
SQLite doesn't support control-flow logic in its triggers. You can express this as a conditional insert:
INSERT INTO Possui (idItem, email, dataAquisicao)
SELECT 11, 'aaaa#bbbb.com', '2019-05-14'
WHERE NOT EXISTS (SELECT 1 FROM Album a WHERE a.idItem = NEW.idItem);
I find it surprising that you are hardcoding 11 for the insert. I would expect NEW.idITEM.
Related
I have subscription data that is being appended to a table in real-time (via kafka). i have set up a trigger such that once the data is added it is checked for consistency. If checks pass some of the data should be added to other tables (that have master information on the customer profile etc.). The checks function i wrote works fine but i keep getting errors on the function used in the trigger. The function for the trigger is:
CREATE OR REPLACE FUNCTION update_tables()
RETURNS TRIGGER
LANGUAGE plpgsql
AS
$$
BEGIN
CASE (SELECT check_incoming_data()) WHEN 0
THEN INSERT INTO
sub_master(sub_id, sub_date, customer_id, product_id)
VALUES(
(SELECT sub_id::int FROM sub_realtime WHERE CTID = (SELECT MAX(CTID) FROM sub_realtime)),
(SELECT sub_date::date FROM sub_realtime WHERE CTID = (SELECT MAX(CTID) FROM sub_realtime)),
(SELECT customer_id::int FROM sub_realtime WHERE CTID = (SELECT MAX(CTID) FROM sub_realtime)),
(SELECT product_id::int FROM sub_realtime WHERE CTID = (SELECT MAX(CTID) FROM sub_realtime))
);
RETURN sub_master;
END CASE;
RETURN sub_master;
END;
$$
The trigger is then:
CREATE TRIGGER incoming_data
AFTER INSERT
ON claims_realtime_3
FOR EACH ROW
EXECUTE PROCEDURE update_tables();
What I am saying is 'if checks pass then select data from the last added row and add them to the master table'. What is the best way to structure this query?
Thanks a lot!
The trigger functions are executed for each row and you must use a record type variable called "NEW" which is automatically created by the database in the trigger functions. "NEW" gets only inserted records. For example, I want to insert data to users_log table when inserting records to users table.
CREATE OR REPLACE FUNCTION users_insert()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
insert into users_log
(
username,
first_name,
last_name
)
select
new.username,
new.first_name,
new.last_name;
return new;
END;
$function$;
create trigger store_data_to_history_insert
before insert
on users for each row execute function users_insert();
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?
I'm working with SQLite,I am using XOR single table inheritance, I want to create a trigger that enables me to:
Check before insertion if the InstructionRefs.id is already created in the table RideHeightRefs
Ckeck before insertion that the InstructionRefs.id does not exist in the other inherited table StrappingRefs.
I took some oracle PL/SQL code and changed it, I guess I am writing it wrong starting from IF NOT EXISTS (SELECT id...):
CREATE TRIGGER IF NOT EXISTS insert_instructionRefs_trigger BEFORE INSERT ON InstructionRefs
BEGIN
IF NOT EXISTS (SELECT id FROM RideHeightRefs AS RHR INNER JOIN InstructionRefs
IR ON RHR.id = IR.id)
BEGIN
SELECT RAISE(FAIL, '"RideHeightRefs" key is unknown. Insertion in
"instructionRefs" is impossible.')
END'
IF NOT EXISTS (SELECT *
FROM (SELECT RideHeightRefs
FROM StrappingRefs
UNION ALL
SELECT RideHeightRefs
FROM InstructionRefs) T
WHERE RideHeightRefs IN (SELECT RideHeightRefs
FROM NEW))
BEGIN
SELECT RAISE(FAIL, '"RideHeightRefs" key is used in another table. Insertion in "StrappingRefs" is impossible.')
END
END
How can I modify the code to make it compatible with sqlite syntax ?
To check that the corresponding row in the base table exists, just use a foreign key constraint.
SQLite has no IF statement. To check for something, add a WHERE clause to the SELECT FAIL, or use the trigger's WHEN clause:
CREATE TRIGGER IF NOT EXISTS insert_instructionRefs_trigger
BEFORE INSERT ON InstructionRefs
WHEN EXISTS (SELECT *
FROM StrappingRefs
WHERE id = NEW.id)
BEGIN
SELECT RAISE(FAIL, '"RideHeightRefs" key is used in another table. Insertion in "StrappingRefs" is impossible.');
END;
I am using MariaDB as my database and I am running into some issues creating a trigger. The code is below:
CREATE TRIGGER `trigger` BEFORE INSERT ON `table_1` FOR EACH ROW
BEGIN
IF NOT CONTAINS(`db`.`table_2`.`item`, NEW.item) THEN
INSERT INTO `db`.`table_2` (`item`, `item_2`, `item_3`) VALUES (NEW.item, "foo",
"bar");
END IF;
END
The issue is that table_2 is in the database "db" along with table_1 but when this code is run, it gives me the error below:
SQL Error (1109): Unknown table 'table_2' in field list
I am very confused by this because it seems like I should be able to do this by everything I am reading. All I am trying to do is force an insert in one table to cause an insert into another table if the condition is not met.
I am guessing that you intend:
CREATE TRIGGER `trigger` BEFORE INSERT ON `table_1` FOR EACH ROW
BEGIN
IF NOT EXISTS (SELECT 1 FROM db.table_2 t2 WHERE CONTAINS(t2.item, NEW.item) THEN
INSERT INTO `db`.`table_2` (`item`, `item_2`, `item_3`)
VALUES (NEW.item, 'foo', 'bar');
END IF;
END;
This is my sql code:
CREATE OR REPLACE TRIGGER PLACE_NO_TRIGGER
BEFORE INSERT or UPDATE ON UHA_LEASE
FOR EACH ROW BEGIN
INSERT INTO UHA_TEMPVAL SELECT PLACE_NO FROM UHA_RESHALL;
INSERT INTO UHA_TEMPVAL SELECT PLACE_NO FROM UHA_GENERAL;
IF(:NEW.PLACE_NO NOT IN UHA_TEMPVAL.TEMP_VALUE AND :NEW.PLACE_NO IS NOT NULL) THEN
RAISE_APPLICATION_ERROR(-10001, 'PLACE_NO MUST BE IN UHA_RESHALL OR IN UHA_GENERAL OR NULL');
END IF;
DELETE FROM UHA_TEMPVAL;
END;
This is giving these errors:
Error(4,27): PLS-00103: Encountered the symbol "UHA_TEMPVAL" when expecting one of the following: ( The symbol "(" was substituted for "UHA_TEMPVAL" to continue.
Error(4,69): PLS-00103: Encountered the symbol "THEN" when expecting one of the following: ) , and or as The symbol ")" was substituted for "THEN" to continue.
Can someone help me understand why these errors are occurring? It's especially odd because row 4 ends at column 60.
Thanks!
It looks like you're trying to enforce referential integrity from a child table to either of two parent tables. You don't really need to insert and delete from a temporary table; you can count how many rows match in either table:
CREATE OR REPLACE TRIGGER PLACE_NO_TRIGGER
BEFORE INSERT or UPDATE ON UHA_LEASE
FOR EACH ROW
DECLARE
CNT NUMBER;
BEGIN
SELECT COUNT(*)
INTO CNT
FROM (
SELECT PLACE_NO FROM UHA_RESHALL
WHERE PLACE_NO = :NEW.PLACE_NO
UNION ALL
SELECT PLACE_NO FROM UHA_GENERAL
WHERE PLACE_NO = :NEW.PLACE_NO
);
IF :NEW.PLACE_NO IS NOT NULL AND CNT = 0 THEN
RAISE_APPLICATION_ERROR(-10001,
'PLACE_NO MUST BE IN UHA_RESHALL OR IN UHA_GENERAL OR NULL');
END IF;
END;
/
You could choose to only run the query if the :NEW.PLACE_NO is not null but it probably won't make much difference if the columns are indexed.