TRIGGER to INCREMENT after INSERT - mysql

I'm trying to create a trigger that increments the cardcount in faction table after an INSERT into card if a row'sfaction.factionname matches cards.faction of the INSERT.
so far I have tried a couple of different methods but the code below is my closest guess
create table cards(
cardid int not null,
faction varchar(255) not null,
primary key(cardid)
);
create table faction(
factionname varchar(255) not null,
cardcount int not null,
primary key(factionname)
);
create trigger updatecountinsert
after insert on cards
for each row
begin
update faction
set cardcount=carcount+1
where last_insert_id().faction=faction.factionname
end;
Basically if I insert values(11,'x') x being the faction if a row of faction has factionname=x
the trigger should
increase that row's "cardcount" by 1

DELIMITER $$
CREATE TRIGGER updatecountinsert
AFTER INSERT ON cards
FOR EACH ROW
BEGIN
-- NEW is used to qualify references values of the row that was just inserted
-- e.g. NEW.faction is a reference to the value in the faction column
UPDATE faction f
SET f.cardcount = f.cardcount + 1
WHERE f.factionname = NEW.faction ;
END;
$$
DELIMITER ;

Related

After Creating after update trigger i cant update any

DROP TABLE IF EXISTS Sales;
CREATE TABLE Sales (
id INT AUTO_INCREMENT,
product VARCHAR(100) NOT NULL,
quantity INT NOT NULL DEFAULT 0,
fiscalYear SMALLINT NOT NULL,
fiscalMonth TINYINT NOT NULL,
CHECK(fiscalMonth >= 1 AND fiscalMonth <= 12),
CHECK(fiscalYear BETWEEN 2000 and 2050),
CHECK (quantity >=0),
UNIQUE(product, fiscalYear, fiscalMonth),
PRIMARY KEY(id)
);
DROP TABLE IF EXISTS log;
CREATE TABLE log (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
text VARCHAR(100)
);
Triggers
CREATE DEFINER=`root`#`localhost` TRIGGER `sales_AFTER_UPDATE` AFTER UPDATE ON `sales`
FOR EACH ROW
BEGIN
INSERT INTO log VALUES(NOW(),CONCAT('Update Student Record ', OLD.quantity));
END
UPDATE test for.sales SET quantity = 36
WHERE (id = 1);
ERROR 1136: 1136: Column count doesn't match value count at row 1
Iam new in mySQL Please help
You should specify columns in INSERT statement in your trigger explicitly, as you do not set all values in a row (auto incremented column excluded).
So it would be
INSERT INTO log(timestamp, text) VALUES (NOW(),CONCAT('Update Student Record ', OLD.quantity));
You have some errors.
First based on your trigger you need another column on log table which is as following
quantity INT NOT NULL DEFAULT 0
Second , do not use Keywords and Reserved Words like text and timestamp, it is a bad practice. If you do please put it inside backticks
Third your insert statement should be
INSERT INTO log(`timestamp`,`text`,quantity) VALUES(NOW(),'Update Student Record', OLD.quantity);
there is no need for CONCAT.
Fourth,
`sales`
table is not the same as Sales table, because you have used backticks.
Full working trigger below:
DELIMITER //
CREATE TRIGGER `sales_AFTER_UPDATE` AFTER UPDATE ON Sales
FOR EACH ROW
BEGIN
INSERT INTO log(`timestamp`,`text`,quantity) VALUES(NOW(),'Update Student Record', OLD.quantity);
END//
DELIMITER ;
Check working demo:
https://www.db-fiddle.com/f/iqwShcHK3AGJvU4MDbxDku/0

MySQL Update Trigger is updating every single record on the table

I'm working on a trigger for an audit table in MySQL. There's 2 tables and 2 separate triggers:
clients and aud_clients
One trigger is an AFTER INSERT ON clients and the other one is AFTER UPDATE ON clients.
Basically every time a record is inserted into clients, a record should also be inserted into aud_clients, and if its an UPDATE on clients, the update on aud_clients should put the old data into old_[Whatever] fields and new one into new_[Whatever] fields.
The operations themselves are working, the problem is that, upon having an UPDATE on clients, every single record on aud_clients becomes the newly updated record.
Output example of what's going on
code old_name old_date old_credit new_name new_date new_credit
10 jello 2019-11-28 19:38:09 2342 100234.20 jam 2019-11-28 19:41:23 11145580
10 jello 2019-11-28 19:38:09 2342 100234.20 jam 2019-11-28 19:41:23 11145580
10 jello 2019-11-28 19:38:09 2342 100234.20 jam 2019-11-28 19:41:23 11145580
This is the update trigger
DELIMITER //
CREATE TRIGGER aud_upd AFTER UPDATE ON clientes
FOR EACH ROW
BEGIN
UPDATE aud_clientes SET
aud_clientes.cod_cliente = NEW.Cod_cliente,
aud_clientes.nombre_antes = OLD.nombre_cliente,
aud_clientes.nombre_despues = NEW.nombre_cliente,
aud_clientes.telefono_antes = OLD.telefono,
aud_clientes.telefono_despues = NEW.telefono,
aud_clientes.credito_antes = OLD.credito_max,
aud_clientes.credito_despues = NEW.credito_max,
aud_clientes.fecha_creacion_antes = OLD.fecha_creacion,
aud_clientes.fecha_creacion_despues = NEW.fecha_creacion,
aud_clientes.tipo_transaccion = 'UPD',
aud_clientes.modificado_por = current_user(),
aud_clientes.fecha = current_timestamp();
END//
DELIMITER ;
The INSERT trigger is working as intended, but in case you want to see it:
DELIMITER //
CREATE TRIGGER aud_ins AFTER INSERT ON clientes
FOR EACH ROW
BEGIN
INSERT INTO aud_clientes (
aud_clientes.cod_cliente,
aud_clientes.nombre_antes,
aud_clientes.nombre_despues,
aud_clientes.telefono_antes,
aud_clientes.telefono_despues,
aud_clientes.credito_antes,
aud_clientes.credito_despues,
aud_clientes.fecha_creacion_antes,
aud_clientes.fecha_creacion_despues,
aud_clientes.tipo_transaccion,
aud_clientes.modificado_por,
aud_clientes.fecha
) VALUES (
NEW.cod_cliente,
null,
NEW.nombre_cliente,
null,
NEW.telefono,
null,
NEW.credito_max,
null,
NEW.fecha_creacion,
'INS',
current_user(),
current_timestamp()
);
END//
DELIMITER ;
Lastly, if you want to look at the table structure:
CREATE TABLE clientes (
cod_cliente INT NOT NULL,
nombre_cliente VARCHAR(100) NOT NULL,
fecha_creacion datetime not null,
telefono VARCHAR(100) NOT NULL,
credito_max DOUBLE(10, 2),
PRIMARY KEY (cod_cliente)
);
commit;
CREATE TABLE aud_clientes (
cod_cliente INT,
nombre_antes VARCHAR(100),
fecha_creacion_antes datetime,
telefono_antes VARCHAR(100),
credito_antes DOUBLE(10,2),
nombre_despues VARCHAR(100),
fecha_creacion_despues datetime,
telefono_despues VARCHAR(100),
credito_despues DOUBLE(10,2),
modificado_por varchar(100),
fecha datetime,
tipo_transaccion varchar(100)
);
commit;
Notice that there's no need to establish relationships or keys on the aud_clientes table. I used to have the cod_cliente as its primary on not null auto_increment, but no record was being updated (and that was probably because it was running into an error when it tried to give the same code to multiple records) so I deleted it.

reset auto-increment each year with new prefix

I have an auto incremented field in my table. It should reset every new year 01/01 and then the prefix part should increment.
For example in 2016 my auto incremented field was A1,A2,A3..... etc but on 12:00 AM 2017 it should reset to B1 and go from there `(B1,B2,B3... etc), until Z when prefix should stop incrementing.
I created two tables... one for integer and one for varchar
CREATE TABLE t1
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE t2
(
id VARCHAR(1) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
);
and am creating a trigger
DELIMITER $$
CREATE TRIGGER tg1
BEFORE INSERT ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 VALUES (NULL);
SET NEW.id = CONCAT('A', LPAD(LAST_INSERT_ID(), 3, '0'));
END$$
DELIMITER ;
but am not sure how to involve date.
My db is mysql

Insert using LAST_INSERT_ID

How would I go about inserting while incrementing and using LAST_INSERT_ID? I have a table and trigger as such:
CREATE TABLE A(
id int NOT NULL AUTO_INCREMENT,
name char(15),
PRIMARY KEY(id)
);
CREATE TABLE B(
id int NOT NULL,
name char(15),
FOREIGN KEY(id) REFERENCES A(id)
);
delimiter //
CREATE TRIGGER T
AFTER INSERT ON B
FOR EACH ROW
BEGIN
IF (NEW.name LIKE 'A') THEN
INSERT INTO A VALUES(LAST_INSERT_ID() + 1, 'A');
END IF;
END//
delimiter ;
I know that INSERT INTO B VALUES(LAST_INSERT_ID() + 1, 'A'); doesn't work if I have multiple inserts into B because LAST_INSERT_ID() when doing multiple-row inserts, LAST_INSERT_ID() will return the value of the first row inserted (not the last). How would I go about incrementing the ID so that LAST_INSERT_ID() returns the most recent ID from the inserts`
If you want to insert the id from B, then use the id column:
CREATE TRIGGER T
AFTER INSERT ON B
FOR EACH ROW
BEGIN
IF (NEW.name LIKE 'A') THEN
INSERT INTO A VALUES(B.ID + 1, 'A');
END IF;
END//
This seems like a curious expression. Perhaps your real intention is simply to have an auto incremented id on both tables.
I realized that I could insert into A without id since its auto-incremented.

MySQL: Custom row validation

I have such example:
CREATE TABLE a(
id INT PRIMARY KEY AUTO_INCREMENT,
parent_id INT,
FOREIGN KEY (parent_id) REFERENCES a(id)
);
DELIMITER ;;
CREATE TRIGGER a_insert BEFORE INSERT ON a
FOR EACH ROW
BEGIN
SIGNAL SQLSTATE '01431' SET MESSAGE_TEXT = 'The foreign data source you are trying to reference does not exist.';
END;;
DELIMITER ;
INSERT INTO a(parent_id) VALUES (NULL);
INSERT INTO a(parent_id) VALUES (1);
INSERT INTO a(parent_id) VALUES (2);
INSERT INTO a(parent_id) VALUES (4);
INSERT INTO a(parent_id) VALUES (999);
SELECT * FROM a
This end up with 4 recods:
----------------
id parent_id
----------------
1 NULL
2 1
3 2
4 4
I found post online that MySQL does not support rollbacks in triggers. That is a problem because I want such hierarchy where no row points to it self and inserts like the one with ID=4 works just fine. How do I ensure there are no such records in database?
Well, the problem is with auto_increment, because you in BEFORE INSERT event you don't have that value assigned yet. On the other hand in AFTER INSERT event you can't do anything with it.
If you want to use auto_increment id column a possible solution is to use separate table for sequencing.
Your schema would look like
CREATE TABLE a_seq(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE a(
id INT NOT NULL PRIMARY KEY DEFAULT 0,
parent_id INT,
FOREIGN KEY (parent_id) REFERENCES a(id)
);
And your trigger
DELIMITER $$
CREATE TRIGGER a_insert
BEFORE INSERT ON a
FOR EACH ROW
BEGIN
INSERT INTO a_seq VALUES(NULL);
SET NEW.id = LAST_INSERT_ID();
IF NEW.id = NEW.parent_id THEN
SET NEW.id = NULL;
END IF;
END$$
DELIMITER ;
If id=parent_id the trigger deliberately violates NOT NULL constraint assigning NULL value. Therefore this record won't be inserted.
Here is SQLFiddle demo. Uncomment last insert statement. It won't allow you to make such insert.