So I'm trying to insert information into a table upon deletion in another table, but I want to gather information also from other tables again which will also be deleted under a cascade. I mean best way to explain it is:
DELIMITER $$
CREATE TRIGGER before_student_delete
BEFORE DELETE
ON students FOR EACH ROW
BEGIN
INSERT INTO student_deletion(student_ID, course_code, department_code)
VALUES(OLD.student_ID,select course_code
from enrolled
where student_ID = OLD.student_ID,
select department_code
from course_dept_key
where course_code = select course_code
from enrolled
where student_ID = OLD.student_ID);
END$$
You know I'm trying to use the old information to find that info in other tables, but...
I'm totally new at this, thanks for any help.
Use for the Selects session variables and insert them into the table.
Like
DELIMITER $$
CREATE TRIGGER before_student_delete
BEFORE DELETE
ON students FOR EACH ROW
BEGIN
SELECT course_code INTO #course_code
FROM enrolled
WHERE student_ID = OLD.student_ID;
SELECT department_code INTO #department_code
FROM course_dept_key
WHERE course_code = #course_code;
INSERT INTO student_deletion(student_ID, course_code, department_code)
VALUES(OLD.student_ID,#course_code,#department_code);
END$$
DELIMITER ;
Related
Essentially I am trying to create a 'Retired' SQL table which will get its values from an already existing 'Staff' SQL table.
If the staff has more than 5 YearsOfService, then he/she will be added to the retired table.
I am sharing the code that I have tried.
CREATE TABLE Retired(
StaffID INT
);
DELIMITER #
CREATE TRIGGER RetiredTrigger after insert on Staff
FOR EACH ROW
BEGIN
INSERT INTO ALUMNI(StaffID) VALUES(new.StaffID);
IF Staff.YearsOfService > 5
END #
The result should ideally be a table(i.e. Retired Table) that should have StaffID's of only those teachers who have YearsOfService greater than 5.
I hope I was able to articulate my doubts clearly.
Thanks in advance.
CREATE TABLE Retired(
StaffID INT
);
DELIMITER #
CREATE TRIGGER RetiredTrigger after insert on Staff
FOR EACH ROW
BEGIN
IF (NEW.YearsOfService > 5) THEN
INSERT INTO Retired(StaffID) VALUES(new.StaffID);
END IF;
END #
DELIMITER ;
I need to clean up the users table and several related tables. So I create a variable that contains the userids and I want to use those values instead of using a sub-query for each delete statement.
I get a syntax error with this. What am I doing wrong?
DELIMITER $$
CREATE PROCEDURE `DBNAME`.`SP_PURGE_DISABLED_USERS` ()
BEGIN
select userid into #disabled_users from USERS where disabled=1;
delete from USER_ACTIVITY where userid in SELECT userid FROM #disabled_users;
delete from USER_PREFS where userid in SELECT userid FROM #disabled_users;
-- <snip> several other related tables to be cleaned up
delete from USERS where userid in SELECT userid FROM #disabled_users;
END
For one thing, at the end of your procedure you need to put your delimiter:
END$$
Then reset you're delimiter back to ;
DELIMITER ;
In the procedure, your delete statements don't make sense. I'd stop using the parameter to store the results of the select and an inner select:
delete from USER_ACTIVITY
WHERE userid in ( select userid from users where disabled=1 );
If you only have a realatively small set of disabled users to delete, you could use group concat and find in set:
DELIMITER $$
CREATE PROCEDURE `DBNAME`.`SP_PURGE_DISABLED_USERS` ()
BEGIN
select GROUP_CONCAT(userid) into #disabled_users from USERS where disabled=1;
delete from USER_ACTIVITY where FIND_IN_SET(userid, #disabled_users);
delete from USER_PREFS where FIND_IN_SET(userid, #disabled_users);
-- <snip> several other related tables to be cleaned up
delete from USERS where FIND_IN_SET(userid, #disabled_users);
END$$
DELIMITER ;
I wouldn't do this with many thousands of userid's though... there may be a limit to string length in a variable.
I decided to go with a temporary table. It cut the stored procedure execution time in half.
CREATE PROCEDURE `DBNAME`.`SP_PURGE_DISABLED_USERS` ()
BEGIN
create temporary table disabled_users
as (select userid from USERS where disabled=1);
delete from USER_ACTIVITY where userid in SELECT userid FROM disabled_users;
delete from USER_PREFS where userid in SELECT userid FROM disabled_users;
-- <snip> several other related tables to be cleaned up
delete from USERS where userid in SELECT userid FROM disabled_users;
drop table disabled_users;
END
Thanks to all who helped on this question.
I'm trying to create a trigger, however I keep getting back a syntax error.
Here's the statement:
DELIMITER $$
CREATE TRIGGER `swtalentbank`.`after_candidate_insert`
AFTER INSERT ON `Candidates` FOR EACH ROW
BEGIN
INSERT INTO useradmin (username, talent)
VALUES (NEW.email, 1);
UPDATE `Candidates` SET UserID = useradmin.userid where useradmin.username = NEW.email;
END
DELIMITER ;
I have a registration form on my site. When a person registers it populates the Candidates table with their profile information.
In the Candidates table, there are various fields, two of them being 'email' and 'UserID'.
UserID is also the PK in 'useradmin', so I'm linking the two up.
So when a user registers, I need to insert a record into 'useradmin' with the email address that's just been used to register, and then update the 'Candidates' table, with UserID that's just been created in 'useradmin'.
I hope this makes sense?
NB. I am changing the delimiter before running the statement.
Besides properly using DELIMITER when creating a trigger you have at least two fundamental issues with your current code:
In MySQL you can't use issue a DML statement (in your case UPDATE) against a table (candidates) on which you defined a trigger (also candidates). Your only option is to use BEFORE trigger and set a value of userid column of a row being inserted to a proper value.
You can't arbitrarily reference a column (useradmin.userid) of a table out of the context like you did in your UPDATE. You didn't joined useradmin table or used it in a subquery.
That being said and assuming that userid in useradmin table is an auto_increment column your trigger might look like this
DELIMITER $$
CREATE TRIGGER after_candidate_insert
BEFORE INSERT ON candidates
FOR EACH ROW
BEGIN
INSERT INTO useradmin (`username`, `talent`) VALUES (NEW.email, 1);
SET NEW.userid = LAST_INSERT_ID();
END$$
DELIMITER ;
Here is SQLFiddle demo
You should use semicolon after end your insert query.
You can use INSERT ... ON DUPLICATE KEY UPDATE syntax for your purpose
try out this...
DELIMITER $$
CREATE TRIGGER `swtalentbank`.`after_candidate_insert`
AFTER INSERT ON `Candidates` FOR EACH ROW
BEGIN
INSERT INTO useradmin (username, talent)
VALUES (NEW.email, 1);
UPDATE `Candidates` SET UserID = useradmin.userid where useradmin.username = NEW.email;
END $$
DELIMITER ;
I have a table warehouse where I have information about articles in my store (article id as foreign key and quantity). Then, I have another table, shoppinglist where I have a clients id, article id and quantity. Lets say, that client wants to buy 3 articles but theres only one article available. How to write a trigger which help me to prevent from buying too much?
I tried this:
DELIMITER $$ CREATE TRIGGER check BEFORE INSERT ON shoppinglist FOR EACH ROW BEGIN IF warehouse.quantity < shoppinglist.quantity THEN CALL fail('You cant buy that much'); END IF; END $$ DELIMITER;
but this seems not to work. I mean, when I do:
INSERT INTO shoppinlist (clients_id, article_id, quantity) VALUES (1, 2, 100);
having only 2 articles with id = 2 on warehouse its ok, its possible. What did I do wrong?
What specific article would warehouse.quantity or shoppingList.quantity refer to in your code?
Also, check is a reserved keyword.
Try this:
DELIMITER $$
CREATE TRIGGER qtyCheck BEFORE INSERT ON shoppinglist
FOR EACH ROW
BEGIN
SET #qty = (SELECT quantity FROM warehouse WHERE article_id = NEW.article_id);
IF #qty < NEW.quantity THEN
CALL fail('You cant buy that much');
END IF;
END $$
DELIMITER ;
Note that I renamed the trigger, I'm guessing the name of the article_id column on the warehouse table, I used the NEW variable instead of shoppingList within the body of the trigger, and you need a space before the semicolon in DELIMITER ;, though this might've been a typo when posting.
Finally, you may get the following error if the fail function isn't defined. It doesn't exist on my system...
ERROR 1305: PROCEDURE testing.fail does not exist
I need to do trigger after Inserting on a table called jos_jquarks_quizzes, I need to create a course name which will have the same name as the quizz name , but its own id,
Tables
jos_jquarks_quizzes
id
title
description
course_id
jos_jquarks_users_training
id
quiz_id
user_id
agree
current approach
BEGIN
INSERT INTO jos_users_trainings
(jos_users_trainings.quiz_id) VALUES
SELECT jos_jquarks_quizzes.id FROM jos_jquarks_quizzes
END
Can you please help. Thanks in Advance
DELIMITER $$
CREATE TRIGGER ai_jos_jquarks_quizzes_each AFTER INSERT ON jos_jquarks_quizzes
FOR EACH ROW
BEGIN
INSERT INTO jos_users_trainings
(quiz_id) VALUES (new.id);
END $$
DELIMITER ;
In a trigger the virtual table new holds the newly inserted values.
In an update or delete trigger the virtual table old holds the values before the change.