I have a database of 600 bottles (bottiglia), where I manage the sale to the public and the orders to supply the cellar.
I want each bottle to always have an availability (qta_disponibile) >= 2. Then, when I make a sale and the availability of the sold bottle drops to 2, an order of this bottle must automatically start.
Also if I sell to a new customer, this must be inserted in the 'Customer' (Cliente) table.
Finally, when I make an order, the availability of the bottle just ordered must be updated, adding the quantity ordered (qta_ordine).
This is the structure of my database:
-------------------------------------
-- Creazione della tabella Produttore
-------------------------------------
create table Produttore(
p_iva bigint(11) unsigned not null,
indirizzo varchar(40),
num_telefono varchar(20),
primary key(p_iva)
)
ENGINE=InnoDB;
-------------------------------------
-- Creazione della tabella Dipendente
-------------------------------------
create table Dipendente(
cf varchar(16) not null,
nome varchar(100) not null,
cognome varchar(100) not null,
indirizzo varchar(200),
num_telefono varchar(20),
primary key(cf)
)
ENGINE=InnoDB;
----------------------------------
-- Creazione della tabella Cliente
----------------------------------
create table Cliente(
cf varchar(16) not null,
nome varchar(100) not null,
cognome varchar(100) not null,
indirizzo varchar(40),
num_telefono varchar(20),
primary key(cf)
)
ENGINE=InnoDB;
------------------------------------
-- Creazione della tabella Bottiglia
------------------------------------
create table Bottiglia(
codice bigint(8) unsigned not null,
tipo_bottiglia varchar(20) not null,
produttore bigint(11) unsigned not null,
annata year not null,
qta_disponibile int not null,
costo decimal(5, 2) not null,
primary key(codice),
foreign key(produttore) references Produttore(p_iva)
on delete cascade
on update cascade
)
ENGINE=InnoDB;
-------------------------------
-- Creazione della tabella Vino
-------------------------------
create table Vino(
codice bigint(8) unsigned,
tipo_vino enum('rosso', 'bianco') not null,
vitigno varchar(40) not null,
gradazione_alcolica decimal (5, 2) not null,
foreign key(codice) references Bottiglia(codice)
on delete cascade
on update cascade
)
ENGINE=InnoDB;
-----------------------------------
-- Creazione della tabella Spumante
-----------------------------------
create table Spumante(
codice bigint(8) unsigned,
metodo varchar(20) not null,
vitigno varchar(40) not null,
gradazione_alcolica decimal (5, 2) not null,
foreign key(codice) references Bottiglia(codice)
on delete cascade
on update cascade
)
ENGINE=InnoDB;
-------------------------------------
-- Creazione della tabella Distillato
-------------------------------------
create table Distillato(
codice bigint(8) unsigned,
tipologia varchar(10) not null,
composizione varchar(20) not null,
gradazione_alcolica decimal (5, 2) not null,
foreign key(codice) references Bottiglia(codice)
on delete cascade
on update cascade
)
ENGINE=InnoDB;
---------------------------------
-- Creazione della tabella Ordine
---------------------------------
create table Ordine(
ID int(4) auto_increment,
dipendente varchar(16),
produttore bigint(11) unsigned,
bottiglia bigint(8) unsigned,
qta_ordine int,
data date not null,
primary key(ID),
foreign key(dipendente) references Dipendente(cf)
on delete cascade
on update cascade,
foreign key(produttore) references Produttore(p_iva)
on delete cascade
on update cascade,
foreign key(bottiglia) references Bottiglia(codice)
on delete cascade
on update cascade
)
ENGINE=InnoDB;
----------------------------------
-- Creazione della tabella Vendita
----------------------------------
create table Vendita(
ID_vendita int(4) auto_increment,
bottiglia bigint(8) unsigned,
cliente varchar(16),
data date,
qta_venduta int,
costo_tot decimal (6, 2),
primary key(ID_vendita),
foreign key(bottiglia) references Bottiglia(codice)
on delete cascade
on update cascade,
foreign key(cliente) references Cliente(cf)
on delete cascade
on update cascade
)
ENGINE=InnoDB;
COMMIT;
I tried using triggers and stored procedures, like this:
drop procedure if exists update_qtaDisponibile;
delimiter $$
create procedure update_qtaDisponibile(in bottigliaCod bigint(8), in qtaVenduta int)
begin
update bottiglia
set qta_disponibile = greatest(qta_disponibile - qtaVenduta, 0)
where codice = bottigliaCod;
if (select qta_disponibile from bottiglia where codice = bottigliaCod) < 2 then
insert into ordine(dipendente, produttore, bottiglia, qta_ordine, data)
values(
(select cf from dipendente where cf = 'auto_order'),
(select produttore from bottiglia where codice = bottigliaCod),
bottigliaCod,
1,
current_date());
end if;
end $$
delimiter ;
Trigger for the sales:
drop trigger if exists Before_Vendita;
delimiter $$
create trigger Before_Vendita
before insert on vendita
for each row
begin
declare var int;
set var = round((rand() * (20 - 1)) + 1);
call update_qtaDisponibile(new.bottiglia, new.qta_venduta);
if not exists (select 1 from cliente where cf = new.cliente) then
insert into cliente(cf, nome, cognome, indirizzo, num_telefono)
values (new.cliente, concat('nome_cliente_', var), concat('cognome_cliente_', var), concat('via_cliente_', var), concat('+39 ', lpad(floor(rand() * 10000000000), 10, '3')));
end if;
end $$
delimiter ;
Trigger for the orders:
drop trigger if exists After_Ordine;
delimiter $$
create trigger After_Ordine
after insert on Ordine
for each row
begin
update bottiglia
set qta_disponibile = qta_disponibile + new.qta_ordine
where codice = new.bottiglia;
end $$
delimiter ;
But when I try to sell a bottle that has qta_disponibilita = 2, I get this error:
Error Code: 1442. Can't update table 'bottiglia' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
How can I do it?