MySQL Trigger UPDATE another table - mysql

I use mysql 5.7 and the structure of database is as the picture below.
I want the colum "Course_left1" on table Course to drop by 1 whenever a course log is inserted into the table Course_history,but it's not working.
CREATE TRIGGER Course_reduce
AFTER INSERT ON Course_history
FOR EACH ROW
UPDATE Course SET Course.Course_left1 = (Course.Course_left1 - 1) where NEW.Sid = Course.Sid
Sid stands for the id of Student while Course_left1 and Course_left2 stand for the course remain for the specific student.
Now, if I insert one tuple into table Course_history I want the Course_left1 in the table Course to drop by 1 which makes it 31.

Related

enter data into 2 tables with foriegn key relation based on one attribute of primary table

I have a table 'project' that has attributes:name, UID(PK), section(distinguisher)... and 3 tables A,B,C based on section with specific properties of each section.i want to be able to enter data into project and the section specific data into A/B/C TABLE based on entry in section attribute of project table of that row. all tables have Foreign key with UID as UID_A, UID_B, UID_C...any ideas on how i can do it? all help appreciated as i am quite a novice...thanks! I am working with Mysql workbench.
Well, create a trigger on the table project:
CREATE TRIGGER `fill_abc` AFTER INSERT ON `project`
FOR EACH ROW BEGIN
INSERT INTO A <some specific data...>;
INSERT INTO B <some specific data...>;
INSERT INTO C <some specific data...>;
END;
Probably, you want to handle not only inserts into this table, but updates and deletes as well - it is nearly the same idea. See trigger definition here and examples here

Automatic Update for database rows based on changes in another table

I have a scenario that requires a value in a row of a table to be updated automatically whenever a row has been added or deleted in another table. I'm not sure how to do it.BTW I'm using phpmyadmin in order to manage my database. Thanks in advance.
pages Table
------------
page_no
no_of_choices
choices Table
-------------
page_no
choice_no
When I add a choice with choice number 1 and page_no, then the table page which has the row, page_no=1 should be updated with no_of_choices=no_of_choices+1
You can use triggers.
For example:
CREATE TRIGGER `test1`
AFTER INSERT ON `tbl1`
FOR EACH ROW SET NEW.upd_fld = new_value
Similarly could be done for delete.
You can also create triggers from phpMyAdmin
TABLE A: page_no, no_of_choices
TABLE B: page_no, choice_no...
With a relational database you very rarely want to have duplicate data. If something breaks at some point, you won't know which to trust - the rows in Table B, or the no_of_choices in Table A. A better solution is to do one of the following (depending on which table you are querying):
SELECT COUNT(no_of_choices) FROM B WHERE page_no = 1
or
SELECT A.*, COUNT(choice_no) AS choice_no FROM A LEFT JOIN B USING(page_no)
You get the same result, but now you have one record to go off of, so you won't have inconsistent data.

mysql divide a table into 2 with different column names

I have a mysql table which I need to split into two. Currently the table contains info about two loosely related entities.
For example the entities can be Employee of a firm and the firm's laptop he is tagged to.
The following table explains my example. I have a table employee which has the following columns
employee_id,employee_name,employee_detail,join_date,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make.
I need to split this table into 2 as shown below.
employee table without the laptop columns
employee_id,employee_name,employee_detail,join_date.
A new laptop table with employee_id as the key.
employee_id,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make
The below statements are true for the current database design
The employee table is heavily used by the back end code. The back
end code is written in java and php.
employee table cannot be renamed.Implies I do not want to create 2
new tables.I want to retain the employee table, but remove all the
laptop info from it.
New rows are added/existing rows are updated on a daily basis.
My question is
Is there a design approach which I can follow for a smooth
transition from the current design of a single table to the newly
suggested design?
Are there any best practices to follow to ensure a smooth
transition.
Could you suggest/re-direct me the steps to complete this task.
Backup your existing database:
mysqldump my_db > backup.sql
Create a new, empty table laptop (I'm not defining indexes or foreign key constraints in my example below, but you should do whatever is appropriate to your data structure):
CREATE TABLE laptop
SELECT employee_id,
laptop_id,
laptop_type,
laptop_tagged_date,
laptop_details,
laptop_make
FROM employee
WHERE FALSE;
Define triggers on the original table to forward each type of write operation (insert/update/delete) to the new table:
CREATE TRIGGER employee_insert AFTER INSERT ON employee FOR EACH ROW
INSERT INTO laptop VALUES (
NEW.employee_id,
NEW.laptop_id,
NEW.laptop_type,
NEW.laptop_tagged_date,
NEW.laptop_details,
NEW.laptop_make
);
CREATE TRIGGER employee_update AFTER UPDATE ON employee FOR EACH ROW
UPDATE laptop SET
employee_id = NEW.employee_id,
laptop_id = NEW.laptop_id,
laptop_type = NEW.laptop_type,
laptop_tagged_date = NEW.laptop_tagged_date,
laptop_details = NEW.laptop_details,
laptop_make = NEW.laptop_make
WHERE
employee_id <=> OLD.employee_id,
laptop_id <=> OLD.laptop_id,
laptop_type <=> OLD.laptop_type,
laptop_tagged_date <=> OLD.laptop_tagged_date,
laptop_details <=> OLD.laptop_details,
laptop_make <=> OLD.laptop_make;
CREATE TRIGGER employee_delete AFTER DELETE ON employee FOR EACH ROW
DELETE FROM laptop WHERE
employee_id <=> OLD.employee_id,
laptop_id <=> OLD.laptop_id,
laptop_type <=> OLD.laptop_type,
laptop_tagged_date <=> OLD.laptop_tagged_date,
laptop_details <=> OLD.laptop_details,
laptop_make <=> OLD.laptop_make;
Empty the new table (of anything the trigger has since inserted) and then, within the same transaction, use INSERT ... SELECT to copy into it all incumbent data from the original table:
START TRANSACTION;
DELETE FROM laptop;
INSERT INTO laptop
SELECT employee_id,
laptop_id,
laptop_type,
laptop_tagged_date,
laptop_details,
laptop_make
FROM employee;
COMMIT;
Thoroughly search your codebase (including database-stored programs) for all operations that access the laptop columns in the original table. Note whether each operation:
only reads from those columns;
only writes to those columns; or
both reads from and writes to those columns (e.g. UPDATE employee SET laptop_tagged_date = laptop_tagged_date + INTERVAL 1 WEEK WHERE ...).
Modify read operations to use the new table, splitting operations that both read and write into separate steps (e.g. UPDATE employee JOIN laptop ON ... SET employee.laptop_tagged_date = laptop.laptop_tagged_date + INTERVAL 1 WEEK WHERE ...).
This change does not need to be effected atomically, as the original and new tables will be kept in sync by the triggers: some parts of your application can therefore read from the new table whilst others continue using the original table.
Do not proceed to the next step until you are satisfied that this step has been completed, as the next step will result in the tables becoming desynchronised. You could even use MySQL user permissions to prevent writing to the new table (except by the triggers) until you are satisfied that this step is complete.
Modify write operations to use the new table.
This change does not need to be effected atomically, as any writes to the original table will be forwarded to the new one by the triggers: some parts of your application can therefore write to the new table whilst others continue writing to the original table.
Drop the columns from the original table:
ALTER TABLE employee
DROP COLUMN laptop_id,
DROP COLUMN laptop_type,
DROP COLUMN laptop_tagged_date,
DROP COLUMN laptop_details,
DROP COLUMN laptop_make;
if you want to have 2 physical different tables you can adapt Sebastien M. answer as such :
create a laptop table with corresponding data to externalize them
CREATE TABLE laptop AS
SELECT DISTINCT employee_id,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make
FROM employee
WHERE ...
provide a employee_laptop view to imitate the behaviour of employee and get backward compatibility
create view employee_laptop as
select employee_id, e.employee_name,e.employee_detail,e.join_date,
l.laptop_id,l.laptop_type,l.laptop_tagged_date,l.laptop_details,l.laptop_make
from employee e join laptop l using(employee_id);
then you have all the latitude to drop the unnecessary columns from the employee table
I can suggest you a possible way , when you are creating laptop table use the following query type :-
create table laptop select employee_id,laptop_id,laptop_type,
laptop_tagged_date,laptop_details,laptop_make from
employee;
After creating the laptop table in this above process, you can remove the specified columns from employee table for getting your new employee table with relevant fields.
Delete column from employee table.
alter table employee
drop column laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make;
Now the new employee table has following fields :
employee_id,employee_name,employee_detail,join_date
Now the laptop table has following fields :
mployee_id,laptop_id,laptop_type,
laptop_tagged_date,laptop_details,laptop_make
Hope it will help you.

Update table on condition from another table Trigger

I have a two tables
MovieStar (
name: char(15),
address:varchar(40),
gender:char(1),
birthdate: date,
rating:float
)
StarsIn (
movieTitle:char(25),
movieYear:int,
starname:char(15),
role:varchar(15)
)
starName is foreign key which is related to name of MovieStar.
I want to increment rating by one when Starsin record is inserted and role of the new record is 'main'
What it would do is;
on insert to starsin, check whether role = 'main'
if so, what is starname
increment rating of moviestar name = starname
I would not store the value rating in your table as it can be derived from the other table's data when it is required. And why are you using float for the count?
Create a VIEW which counts the rows in Starsin, based on your condition role = 'main' and then you have no need for the trigger and the count will always be up to date when new rows are added or removed.
With the trigger solution you also have to take account of row deletion to decrement the count.
EDIT: From the comment you made, here's a sample trigger (although the syntax may be wrong as I mainly work with SQL Server). I'm assuming the name field in the MovieStar table is a primary key and therefore unique.
CREATE TRIGGER UpdateRating AFTER INSERT ON StarsIn
FOR EACH ROW
BEGIN
UPDATE MovieStar SET rating =
(SELECT rating FROM MovieStar WHERE name = NEW.starname) + 1
FROM MovieStar INNER JOIN NEW ON MoveStar.name = NEW.starname
WHERE NEW.role = 'main'
END
I'm not familiar with MySQL, I work with SQL Server, where triggers need to be set based. I'm guessing the FOR EACH ROW part of the trigger means the statements are executed for each row inserted, but I may be wrong about that.
You need to create a trigger on insert and do the intended update.

Need help with simple mysql triggers

I have one table (TABLE A) in my mysql database which has the listed fields:
row1_id - PK
row2_id - PK
row3_data
What I would like to do is, every time a record is inserted or updated in table A, I would like to call a trigger to write me the new information of table A in another table, TABLE A_LOG, which has the following fields:
row0-modification-id - PK
row1_id (from table A) - PK
row2_id (from table A) - PK
row3_data (from table A)
the Table A_LOG should then have 3 PKeys, two from the new inserted/updated record of table A and other that indicates me the number of the modification (1, 2, 3..)
Thank you very much for your help.
Create TableA_Log to autoincrement row0-modification-id.
I bet you don't exactly need this table to have row0-modification-id AND row1_id and row2_id all as the PK.
CREATE TRIGGER dbo.trg_TableA_ins_upd
ON dbo.DatabaseName
AFTER INSERT, UPDATE
AS
BEGIN
INSERT INTO TableA_Log (row1_id, row2_id, row3_data)
SELECT row1_id, row2_id, row3_data FROM inserted
END