2 problems when trying to create a trigger in MySQL - mysql

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);

Related

I can't use trigger to update info from two tables, MYSQL

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.

MYSQL Trigger To Populate New Table

Hey all so I have created a table named products that looks like so:
`CREATE TABLE products
(
Prod_ID int(10),
Prod_name varchar(20),
Prod_qty varchar(20),
Prod_price int(20)
);`
Product_log table is nearly identical to another table called products:
`CREATE TABLE product_log
(
Prod_ID int(10),
Prod_name varchar(20),
Action_Date date,
Updated_by varchar(30),
Action varchar(30)
);`
Next I have created a trigger called products_after_insert which should insert data into the product_log table after a row in products is inserted.
The requirement for after insert trigger is that action date should be inserted in the product_log table and the user name should be inserted like who inserted the data ex: data operator,
and on last the action should be inserted in the product_log table automatically like action here is insertion.
here is my trigger:
`DELIMITER //
CREATE TRIGGER products_after_insert
AFTER INSERT
ON products
FOR EACH ROW
BEGIN
DECLARE data_operator int(10);
DECLARE action_per varchar(200);
SET data_operator = 1;
SET action_per = 'INSERTION';
IF data_operator=1 THEN
INSERT INTO product_log(prod_id,prod_name,Action_date,Updated_by,Action)
VALUES(NEW.prod_id,NEW.prod_name,SYSDATE(),'data_operator','action_per');
END IF;
END;
//DELIMITER;`
Now, I assume I am constructing my trigger incorrectly because it appears to not be working.
Does anyone know what I am doing wrong? Any help would be greatly appreciated! Thanks!
There's at least this you are doing wrong :
VALUES(NEW.prod_id,NEW.prod_name,SYSDATE(),'data_operator','action_per');
You have properly defined the variables data_operator and action_per previously:
SET data_operator = 1;
SET action_per = 'INSERTION';
But in your INSERT instruction you surrounded them with quotes, which turned them into strings. Your instruction should be :
VALUES(NEW.prod_id,NEW.prod_name,SYSDATE(),data_operator,action_per);

Why isn't the primary key incrementing ON DUPLICATE?

I have the following TEACHER table that has the following schema:
create table TEACHER
(
TEACHERID int not null auto_increment,
FIRST_NAME varchar(20) not null,
SURNAME varchar(20) not null,
primary key (TEACHERID)
);
I have multiple inserts with the same first name and surname of teacher that I wish to omit. The schema is given and I don't plan on modifying it.
I try to execute dynamically in my program the following query but the TEACHERID is not incrementing, actually no new fields with new first name and last name are added, there is only one field that is constantly being updated.
Here is my query:
INSERT INTO TEACHER set ? ON DUPLICATE KEY UPDATE FirstName = ?, LastName = ?'
with the ? are defined as follows: values: [set, professor.name, professor.sname ]
where a set is defined as follows:
set = {
FirstName: professor.name,
LastName: professor.sname
}
How do I get the primary key to increment on each duplicate, without actually adding that duplicate?
Thank you
You are getting that behavior cause you are using ON DUPLICATE KEY UPDATE. If you really want to insert the duplicate record then just perform a INSERT statement like
INSERT INTO TEACHER VALUES('test','test')
How do I get the primary key to increment on each duplicate, without
actually adding that duplicate?
Sorry that's not possible at-least with auto increment. You will then have to have your own primary key and on every insert do some manipulation through a before insert trigger. Something like
create table TEACHER
(
TEACHERID int not null primary key,
create trigger trg_binsert
on TEACHER before insert
for each row
begin
if(new.FIRST_NAME = FIRST_NAME and new.SURNAME = SURNAME)
update TEACHER
SET TEACHERID = TEACHERID + 1
WHERE new.FIRST_NAME = FIRST_NAME
and new.SURNAME = SURNAME;
end if
end
Though, not sure why you want to do that and won't recommend as well.

Suggestions on how to convert my t-sql code to mysql

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.

SQL Server throwing errors on Drop

I am trying to create a database in SQL Server but it keeps throwing errors. Could you look at the script and see if I am messing it up somehow?
drop database if exists cptc;
create database cptc;
use cptc;
drop table if exists staff;
create table staff (
staffID int not null auto_increment,
fname varchar(25),
lname varchar(25),
title varchar(50),
phone varchar(10),
building varchar(10),
room varchar(10),
PRIMARY KEY(staffID),
FULLTEXT (fname,lname)
)ENGINE = MYISAM;
INSERT INTO staff VALUES ('','michael','herrera','doctor','2539703420','B14','122');
INSERT INTO staff VALUES ('','holly','herrera','teacher','2534667896','B35','116');
INSERT INTO staff VALUES ('','jesse','kirsch','professor','2534567890','B12','112');
INSERT INTO staff VALUES ('','mark','wahlberg','professor','5552345678','B01','112');
INSERT INTO staff VALUES ('','philip','spears','technician','2065672345','B12','123');
INSERT INTO staff VALUES ('','andrew','jackson','teacher','2061234567','B32','101');
INSERT INTO staff VALUES ('','annie','smith','mechanic','2533345609','B23','102');
INSERT INTO staff VALUES ('','alfred','hills','teacher','2535821513','B14','103');
INSERT INTO staff VALUES ('','bobby','jones','nurse','5559876056','B10','104');
INSERT INTO staff VALUES ('','tiffany','jones','janitor','2539981265','B02','108');
UPDATE: I think I was having Errors because it is MySQL and NOT SQL. Thanks everyone For Your (Really Quick) Answers!
This part is MYSQL not SQL Server ENGINE = MYISAM;
here is what the table would look like in SQL Server (sans the fulltext index, you first need to enable fulltext search in order to create a full text index))
create table staff (
staffID int not null identity,
fname varchar(25),
lname varchar(25),
title varchar(50),
phone varchar(10),
building varchar(10),
room varchar(10),
PRIMARY KEY(staffID)
)
The drop and create database will look like this
USE [master]
GO
IF EXISTS (SELECT name FROM sys.databases
WHERE name = N'cptc')
DROP DATABASE cptc
GO
CREATE DATABASE [cptc]
The drop table will look like this
IF EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'staff') AND type in (N'U'))
DROP TABLE staff
GO
Finally, you need to ommit the column for the identity while inserting, example
INSERT INTO staff VALUES ('michael','herrera','doctor','2539703420','B14','122');
If you don't ommit the column, you will get the following error
Msg 8101, Level 16, State 1, Line 1
An explicit value for the identity column in table 'staff' can only be specified when a column list is used and IDENTITY_INSERT is ON.
auto_increment should be identity(1,1)
ENGINE = MYISAM; doesnt exist what do you expect with it?
FULLTEXT (fname, lname) is not correct. What do you want, implement full text serach?
The question was not clear. You were creating a table not database.
It would be helpful if you provide the actual error detail.
BTW, you shouldn't put any value for the autoincrement column which will be assigned by server automatically. I guess this was causing the issue.