Hello i have this problem:
I have 2 tables :
Create table Student(
Num int Auto_increment,
Name varchar(100),
Age int,
Gpa int default 2,
primary key(Num)
);
Create table Grades(
Num int,
Grade_BG int default 2,
Grade_Math int default 2,
Grade_SUBD int default 2,
Primary key (Num)
);
And i want to make a trigger to update the GPA with the three grades from the other table but i'm having hard time doing it.
Your trigger code :-
create trigger stud_marks after INSERT on Grades
for each row
update Student
set Gpa = (Grades.Grade_BG+Grades.Grade_Math+Grades.Grade_SUBD)/3;
The for each row means for each row inserted to grades so the grades. qualifier is unnecessary and should be replaced with NEW. 'Within the trigger body, the OLD and NEW keywords enable you to access columns in the rows affected by a trigger.' - https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html
Also the update needs to know which student to update so a where clause would be useful
so
create trigger stud_marks after INSERT on Grades
for each row
update Student
set Gpa = (new.Grade_BG+new.Grade_Math+new.Grade_SUBD)/3
where student.num = new.num;
Assuming num in grades actually relates to num in student. If not then you need to create a relationship.
You may also need to create UPDATE and DELETE triggers.
Related
I am trying to understand triggers in MySQL, but am having a few problems.
I'm trying to implement a trigger which on every UPDATE/INSERT in the table Grades it updates the column "gpa" in another table called Student, but cannot do it properly.
Code:
CREATE TABLE Student
(
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30),
age TINYINT,
gpa NUMERIC(3, 2) DEFAULT 2
);
CREATE TABLE Grades
(
StudentId INT PRIMARY KEY,
grade_bg INT,
grade_math INT,
grade_subd INT,
FOREIGN KEY(StudentId) references Student(Id)
);
delimiter |
CREATE TRIGGER update_gpa
AFTER INSERT
ON Grades
FOR EACH ROW
BEGIN
UPDATE Student SET gpa = ((grade_bg + grade_math + grade_subd)/3) WHERE StudentId = Id;
END;
|
After this when I try to insert in the table Student I get:
"Error 1054: Unknown column 'StudentId' in where clause".
For example:
INSERT INTO Student(name, age)
VALUES ('Joshua', 17);
Also when I try writing "AFTER INSERT, UPDATE" I get a syntax error from the MySQL Workbench and don't know how to make the trigger activate on INSERT AND UPDATE in the table Grades.
Any help is appreciated! Thanks in advance!
I don't know much about Triggers but I tried just running the update statement and noticed you hadn't defined the join:-
UPDATE Student
INNER JOIN Grades ON Grades.StudentId = Student.Id
SET Student.gpa = ((Grades.grade_bg + Grades.grade_math + Grades.grade_subd)/3);
So I made a change from 'Chemistry' to 'Physic' on 'major' column but as soon I executed it nothing changes and shows the same result. Why? (I used MySql Workbench)
Here's the original code:
CREATE TABLE people_data1 (
id INT,
username VARCHAR(20),
major VARCHAR(20) UNIQUE,
PRIMARY KEY(id)
);
# Insert some data into the table
INSERT INTO people_data1(id,username) VALUES(3,'Clara'); # Person with no major
INSERT INTO people_data1 VALUES(51,'Mr Bald','Chemistry'); # Change to 'Physic'
SELECT * FROM people_data1;
The new one:
CREATE TABLE people_data1 (
id INT,
username VARCHAR(20),
major VARCHAR(20) UNIQUE,
PRIMARY KEY(id)
);
# Insert some data into the table
INSERT INTO people_data1(id,username) VALUES(3,'Clara'); # Person with no major
INSERT INTO people_data1 VALUES(51,'Mr Bald','Physic');
SELECT * FROM people_data1;
Inserts add new records; you want an update here:
UPDATE people_data1
SET major = 'Physics'
WHERE id = 51;
Run this update after your first two insert statements to get your desired results.
I need a solution for copy the auto increment value to userid column when insert the record.
I have two column like id(AI),userid. Here I have used a trigger
CREATE TRIGGER adduserid BEFORE INSERT ON user
FOR EACH ROW SET NEW.userid = NEW.id
The problems is triggers invoke before insert,so it will get id as 0.
Suggest me how can I modify the trigger?
Sample:
Table definition:
CREATE TABLE departments (
ID NUMBER(10) NOT NULL,
DESCRIPTION VARCHAR2(50) NOT NULL);
ALTER TABLE departments ADD (
CONSTRAINT dept_pk PRIMARY KEY (ID));
CREATE SEQUENCE dept_seq;
Trigger definition:
CREATE OR REPLACE TRIGGER dept_bir
BEFORE INSERT ON departments
FOR EACH ROW
BEGIN
SELECT dept_seq.NEXTVAL
INTO :new.id
FROM dual;
END;
Syntax Link1:https://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
My company has different type of invoices.
Example:
H00001/2013
.
.
.
H99999/2013
and
T00001/2013
.
.
.
T99999/2013
The problem is, the numbering is increasing for new year.
How can I make auto increment value reset for each new year?
This is my current code:
CREATE TABLE `invoices` (
`invoicenumber` mediumint unsigned NOT NULL auto_increment,
`invoicetype` enum('A','B') NOT NULL,
`date` date NOT NULL,
`client` varchar(100) NOT NULL,
PRIMARY KEY (invoicetype,invoicenumber)
) COMMENT='' ENGINE='MyISAM';
Hey if you are using any client application for database like MysqlWorkBench or MYSQL Query Browser
then you can do below steps to set AutoIncrement no -
Right click on Table and go to Alter Table
Select Options tab
Under that you can find Auto Increment label there you can reset the number.
You can reset auto increment value by using the ALTER TABLE statement. The syntax of the ALTER TABLE statement to reset auto increment value is as follows:
ALTER TABLE table_name AUTO_INCREMENT = VALUE;
EDITED:
If you don't want to run this query every year then you have other two option to do such thing as I am aware of this two.
Create cron job/windows scheduled job
As you are using MySql then there is Event Scheduler (Keep in mind this is added in MySql 5.1.6 not in previous versions of MySql)
In your DB table, you can reset the counter with the following code:
ALTER TABLE tablename AUTO_INCREMENT = 1
Perhaps you already found a solution and the answer I'm giving may not be useful, since it's been seven months. Returning to the topic, I noticed that you have a composed primary key with two columns (invoicetype,invoicenumber). So there can be no duplicates of pairs invoicetype,invoicenumber . If you reset the auto_increment every year there might be possible to have duplicate pairs like 'A',1 for two rows, one invoice from year 2013 and the other from year 2014. So you can eliminate that primary key to prevent the violation of the primary key constraint. You can instead define a primary key (any decent table has one) with an auto_incremented column to make every row unique. Then you can define an auto incrementation mechanism for the invoicenumber column (I will shall return to this issue). First I would define the invoice table like this:
CREATE TABLE `invoices` (
`id` int unsigned NOT NULL auto_increment,
`invoicenumber` mediumint unsigned NOT NULL,
`invoicetype` enum('A','B') NOT NULL,
`invoicedate` date NOT NULL, -- not recomended to use reserved words for column names like date
`client` varchar(100) NOT NULL,
PRIMARY KEY (id)
) COMMENT='' ENGINE='MyISAM';
Then I would define another table list_id :
CREATE TABLE `list_id` (
`id` int unsigned NOT NULL auto_increment,
`id_inc` int unsigned NOT NULL, -- number of invoice
`the_year` date NOT NULL, -- year corresponding to the number of invoice
PRIMARY KEY (id)
) COMMENT='' ENGINE='MyISAM';
The above table can be used to set the value of invoicenumber for the current row inserted in invoice table (1 if it is the first invoice of the year of invoicedate, the maximum value of id_inc (coresponding to the year of invoicedate) plus one, otherwise). The rows are completed using a trigger of type before insert for the invoice table. So, before I insert a new invoice, I have to determine the value of invoicenumber. It will be 1, if there are no records in table list_id with column the_year having the value equal to the year of the new invoice. In this case I can insert in table list_id a new record with the values (1,2014) (id_inc,year). It will be the maximum value of id_inc plus 1, if there are record(s) in table list_id with column the_year having the value equal to the year of the new invoice. In this case I can insert in table list_id a new record with the values (7,2014) (id_inc,year). The trigger looks like this:
CREATE TRIGGER `increment_or_reset_new_year`
BEFORE INSERT ON `invoices`
FOR EACH ROW
thisTrigger : begin
declare new_id_year int(11);
declare nr_invoices_year int(11);
declare new_invoice_begin int(11);
declare current_year_row int(11);
set current_year_row = year(new.invoice_date);
set nr_invoices_year = get_nr_invoices_year(current_year_row);
if(get_nr_invoices_year(current_year_row) < 1) then
set new.invoicenumber = 1;
insert into list_id(id_inc,the_year) values (1,current_year_row);
leave thisTrigger;
end if;
if(get_nr_invoices_year(current_year_row) >= 1) then
set new.invoicenumber = get_max_id(year(new.invoice_date)) + 1;
set new_id_year = get_max_id(year(new.invoice_date)) + 1;
insert into list_id(id_inc,the_year) values(new_id_year,year(new.invoice_date));
end if;
end;
There are 2 functions in the trigger. The first one determines the number of rows from the list_id table having the_year equal with the current invoice year (given as parameter):
create function get_nr_invoices_year(invoice_year int) returns int
begin
declare nr_invoices_year int(11);
select count(*) into nr_invoices_year from lista_id where the_year = invoice_year;
return nr_invoices_year;
end;
The second one determines the maximum value of id_inc from table list_id which has the coresponding value of the_year equal with the year of current invoice (given as parameter):
create function get_max_id(year_invoice int) returns int
begin
declare max_id_year int(11);
select max(id_inc) into max_id_year from invoices.lista_id where the_year =year_invoice;
return max_id_year;
end;
So I can have one trigger, two functions and one table which controls the incrementation of invoicenumber.
Hope this helps! It worked for me!
I'm a T-SQL coder and I'm starting to code in MySQL Workbench.
I'm trying to apply triggers and function in MySQL but am having difficulties with the syntax.
Basically my code below wants to use the StudentID (incrementing) as basis for my Studentnumber code
having max value of 5 zero digits. liek this----> 13-00001 (where 13 is the last digit of the year and 1 is the StudentID value.) So if I insert 291 records, my last record will be 13-00291.
In T-SQL I have the following code:
create table Student
( StudentID int identity not null primary key,
Name varchar(100),
StudentNumber varchar(10)
)
create function StudentNumber (#id int)
returns char(9)
as
begin
return (SELECT SUBSTRING((CONVERT(VARCHAR(10),GETDATE(),112)),3,2)) + '-' + right('000000' + convert(varchar(10), #id), 6)
end
create trigger Student_insert on Student
after insert as
update
Student
set
Student.StudentNumber = dbo.StudentNumber(Student.StudentID)
from
Student
inner join
inserted on Student.StudentID= inserted.StudentID
When I started coding in MySQL creating tables is basic, but when I created my triggers and function,
it seems there is a big difference with how mysql works.
I've read that Identity's equivalent in MYSQL is AutoIncrement PK,
but I've also read that when a trigger is fired, it can't get the value of my PK because the record hasnt been committed yet (or something along those lines) I've read that the only way to do the function I want in MySQL is to create a temp table which will store the ID or something. But I'd like to ask the opinion of others here if there's a way to recreate my function in MYSQL without having to resort to creating temp tables.
Thanks
If you want to use an auto_increment field for this in MySql you'll have to have a separate table for sequencing like this.
Your schema
CREATE TABLE student_seq(id INT AUTO_INCREMENT NOT NULL PRIMARY KEY)|
CREATE TABLE student
( StudentID INT NOT NULL PRIMARY KEY,
Name VARCHAR(100),
StudentNumber VARCHAR(8) DEFAULT NULL
);
Function
CREATE FUNCTION student_number (id INT)
RETURNS VARCHAR(8)
RETURN CONCAT(DATE_FORMAT(CURDATE(), '%y'), '-', LPAD(id, 5, '0'));
Now the trigger
DELIMITER $$
CREATE TRIGGER tg_student_insert
BEFORE INSERT ON Student
FOR EACH ROW
BEGIN
DECLARE nextid INT DEFAULT 0;
INSERT INTO student_seq VALUES(NULL);
SET nextid = LAST_INSERT_ID();
SET NEW.studentid = nextid, NEW.studentnumber = student_number(nextid);
END$$
DELIMITER ;
Lets insert a new student
INSERT INTO student (studentid, name) VALUES(0, 'Jhon');
You'll get in student table
| STUDENTID | NAME | STUDENTNUMBER |
------------------------------------
| 1 | Jhon | 13-00001 |
Here is SQLFiddle demo.