Two trigger calls calling mutually - mysql

so I have this two tables which both have some trigger, both are AFTER INSERT; I dont exactly know how to call it but I hope the title is not so inaccurate. :)
I'm currently new to triggers in general so bear with me on this one please.
What happens is that for every new episode entry I need to updated the count of episodes per season. And when a new entry in the season table a new episode shall be created (a trailer).
I'm currently using MySQL 5.7.17; This triggers work in DB2 but in MySQL I just couldnt get them to work.
I just keep getting the error that says that I can't update the table from which the statement was called:
Can't update table 'seasons' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
If you can help me, or not, anyways any ideas THANKS IN ADVANCE!
CREATE TABLE episodes (
episodeId INTEGER NOT NULL AUTO_INCREMENT,
seasonId INTEGER NOT NULL,
number INTEGER NOT NULL,
date DATE NOT NULL,
title VARCHAR(256) NOT NULL,
summary TEXT,
PRIMARY KEY(episodeId)
);
CREATE TABLE seasons (
seasonId INTEGER NOT NULL AUTO_INCREMENT,
startDate DATE NOT NULL,
name VARCHAR(128) DEFAULT 'Unknown season',
numberOfEpisodes SMALLINT NOT NULL DEFAULT 0,
PRIMARY KEY(seasonId)
);
/* TRIGGERS */
/* trigger to increment the numberOfEpisodes in seasons */
CREATE TRIGGER newEpisode
AFTER INSERT ON episodes
FOR EACH ROW
BEGIN -- I also tried without the Begin-End statement
UPDATE seasons SET numberOfEpisodes = numberOfEpisodes + 1
WHERE seasons.seasonId = NEW.seasonId;
END;
;
/* Each season has a trailer as episode 0 */
CREATE TRIGGER newSeason
AFTER INSERT ON seasons
FOR EACH ROW
BEGIN -- I also tried without the Begin-End statement
INSERT INTO episodes (seasonId, number, date, title, summary)
VALUES (NEW.seasonId, 0, CURRENT_TIMESTAMP, 'Trailer', 'Episode 0 = Trialer');
END;
;

Related

How to automatically load values from one table column to another in MYSQL

I am using Mysql 8.0
I have 2 tables given below:
Table 1:
I_VendorID INT NOT NULL PRIMARY KEY,
V_Code VARCHAR(50) NULL,
V_Name VARCHAR(250) NULL,
V_Address VARCHAR(500) NULL,
N_Mobile NUMERIC(10, 0) NULL,
N_Phone NUMERIC(11, 0) NULL,
V_Email VARCHAR(100) NULL,
Table 2:
I_POID INT NOT NULL PRIMARY KEY,
I_VendorID INT NULL,
V_PODetails VARCHAR(50) NULL
I wish to know if there is any way, either through query code or through mysql workbench that whatever value is in table 1 under I_VendorID is automatically copied to I_VendorID in table 2.
I will always be taking the values from the user for the 2 tables at the same time. Also declared I_VendorID in table 2 as a foreign key. I thought, rather than passing values manually for I_VendorID from table 2 everytime, I could just copy the value from table 1. Is there any query or method that would automatically ensure this?
You can use mysql triggers to make sure that for each row inserted in your first table, another row is inserted in the second table
MySql documentation on triggers
CREATE TRIGGER ins_to_table_2 BEFORE INSERT ON table_1
FOR EACH ROW
BEGIN
insert into table_2('I_VendorID') values(New.I_VendorID)
END;//
I have not executed the above yet, but it's something very similar.
Truth be told though, since you will eventually add a row in the second table, you can insert it when needed and query with a left join instead of inner join so that you can return the values from the first table, even if the second one has no values yet.

MYSQL - TRIGGER insert into another table values from a table when a tinyint is updated to TRUE

I have 2 tables bid and job
CREATE TABLE test.bid_ (
ID INT NOT NULL AUTO_INCREMENT,
bid_name VARCHAR(45) NULL,
bid_won TINYINT(1) NULL,
job_ID INT NULL,
con_ID INT NULL,
PRIMARY KEY (ID));
And,
CREATE TABLE test.job_ (
ID INT NOT NULL AUTO_INCREMENT,
job_name VARCHAR(45) NULL,
con_ID INT NULL,
PRIMARY KEY (ID));
What I am trying to do is, insert bid.bid_name into job.job_name after bid_won is updated to TRUE. I just cannot wrap my head around the trigger or procedures needed. I am very new to triggers and procedures.
I would think a trigger like this would work:
CREATE DEFINER = CURRENT_USER TRIGGER `test`.`bid_AFTER_UPDATE` AFTER UPDATE ON `bid` FOR EACH ROW
BEGIN
INSERT INTO job (job_name,con_ID)
SELECT bid_name,con_ID FROM bid WHERE OLD.bid_won <=> NEW.bid_won AND job_ID IS NULL
END
But I guess the AND clause is no good. Also, I would need to update the bid table with the new job_ID from job.ID that is created when the bid is made into a job. Any help would be appreciated.
**
Does it always seem that when you find the answer to your question you hit your forehead and say "Of Course!!!", I think I have the answer to my problem #P.Salmon asked the question that really helped me with a more elegant solution.
'update the bid table with the new job_ID from job.ID that is created ' - is impossible,mysql will not allow you to action the table which fired the trigger. Why do you need the job table at all - it contains everything that bid has
I will just put in a column that would indicate whether it is a job or abid. However,the following trigger is producing the results I was looking for.
BEGIN
IF NEW.bid_won = TRUE
THEN
INSERT INTO test.job (job_conID,job_name) SELECT
bid_conID,bid_name,bid_desc,bidID FROM bid WHERE ID = NEW.ID;
ELSEIF NEW.bid_won = FALSE
THEN
DELETE FROM job WHERE job_name = NEW.bid_name;
END IF;
END
I realize this may be a bit redundant, however, it demonstrates the fact that I hit my forehead on the 'NEW.' and 'OLD.' parts of the update. Basically, it is a switch.

MySQL Table Create

Following up to see if there is a way, know this might be simple for you guys:
I need to create a table with 5 columns where columns(CostPrice) and columns(SellPrice) need to add a value into columns(Difference) in MySQL. In the example let's say I have items I wish to load and upon selling them I want that Difference calculated in the database not through a view because I'd like to reference that "Difference" value in another table when I'll at a later stage be doing a view.
What I'm trying to achieve:
itemAdd/itemName/costPrice/sellPrice/difference
2019-08-22/Table/100/150/50
CREATE TABLE Results (
itemAdd Timestamp,
itemName varchar(255) NOT NULL,
costPrice int(11) NOT NULL,
sellPrice int(11) NOT NULL,
(costPrice - sellPrice) as 'difference'
)
Reason why I want to do this through table create is because I'd update the costPrice and sellPrice of the items and would like to keep track of how the difference changed, but at the same time I'd like to reference the difference column from another table so that value shouldn't stay statically the same. Hope this makes sense. . .
If you set up insert/update triggers, you can determine the difference any time there is a change.
(live sandbox example: https://www.db-fiddle.com/f/8DVeXFdsrEBwHg168GZU2o/22)
Update your table to define the difference column.
CREATE TABLE Results (
itemAdd Timestamp,
itemName varchar(255) NOT NULL,
costPrice int(11) NOT NULL,
sellPrice int(11) NOT NULL,
difference int(11) NOT NULL
);
Then define triggers to handle the insert/updates:
-- handle inserts
DELIMITER $$
CREATE TRIGGER trg_insert_price_diff
BEFORE INSERT ON Results
FOR EACH ROW
BEGIN
SET NEW.difference = NEW.sellPrice - NEW.costPrice;
END$$
DELIMITER ;
-- handle updates
DELIMITER $$
CREATE TRIGGER trg_update_price_diff
BEFORE UPDATE ON Results
FOR EACH ROW
BEGIN
SET NEW.difference = NEW.sellPrice - NEW.costPrice;
END$$
DELIMITER ;

MySQL trigger - Trigger table name interpreted as field

I am having an issue with a trigger I have put in a database I am building. It is the only trigger in the database. Here are the two tables being used.
Client Table
create table client (
clientNum INT(5) not null auto_increment,
clientName TEXT(30) not null,
clientEmail VARCHAR(64) not null,
clientGender CHAR(1) not null,
clientDOB DATE not null,
clientAddress TEXT(50),
clientPhone VARCHAR(12) not null,
hasInsurance CHAR(1) not null,
clientBalanceOwed DECIMAL(10,2),
clientLastDateVisited DATE,
clientNextVisitDate DATE,
primary key (clientNum));
Insurance Table
create table insurance(
insuranceNum INT(5) not null auto_increment,
cardNum INT(16),
policyNum INT(6),
policyHolder TEXT(30),
clientNum INT(5),
primary key (insuranceNum),
foreign key (clientNum) references client(clientNum));
The idea for the following trigger is to only create an insurance row when a client is added to the database that has the 'hasInsurance' field set to 'y'. Then, once that client has been added, create a new insurance row with the clientNum set to the clientNum that was just added.
The Trigger
delimiter $$
create trigger New_Insurance_Row after insert on client
for each row
begin
if(client.hasInsurance = 'y') then
insert into insurance (clientNum) values (NEW.clientNum);
end if;
end$$
Everything up to this point works as intended, until you try to insert a new client into the table and call the trigger. Once I try and add the following line of code:
The Insert Statement
insert into client(clientName, clientEmail, clientGender, clientDOB,
clientAddress,
clientPhone, hasInsurance, clientBalanceOwed, clientLastDateVisited,
clientNextVisitDate)
values
('Darcy Watts','dwatts#email.com','m','1996-5-9','Belfast, Charlottetown
PEI','123-222-3333','y','400.77','2017-8-12','2019-9-6');
When I try and run this I am met with this error:
#1109 - Unknown table 'client' in field list
So from what I've learned over the last few hours is that this error usually happens when you put the '`' (backtick) on a variable or table name, MySQL thinks that entry is part of a field list or something along that line. So I changed the trigger to just be 'client' by itself and I still got an error. Dropped the old database and everything. One more thing, the insert statement does work by itself if the trigger has not been entered yet.
Any help would be appreciated! Thanks!
I guess your hasInsurance should be from the new record.
...
if(new.hasInsurance = 'y') then
insert into insurance (clientNum) values (NEW.clientNum);
end if;
...
--
DB Fiddle (provided by GMB)

How to reset autoincrement value in mysql?

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!