as I'm working on a small app for managing metadata and I was wondering if it is possible to insert row in another table if conditions are met.
Let me follow with example: So, let's say we have table ispu_plan
CREATE TABLE `ispu_plan` (
`id` int(11) NOT NULL,
`id_jls` int(11) NOT NULL,
`id_razina_plan` int(11) NOT NULL,
`id_revizija` int(11) NOT NULL,
`naziv_plan` varchar(150) NOT NULL,
`ispu_naziv` varchar(100) NOT NULL,
`id_mjerilo` int(11) NOT NULL,
`datum_donosenja_plana` date DEFAULT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and as I'm updating table ispu_plan I want to update another table (e.g. ispu_plan_updated) if certain conditions are met in ispu_plan with same rows from table ispu_plan
Using this query:
SELECT * FROM ispu_plan WHERE datum_donosenja_plana BETWEEN '2014-01-01' AND CURDATE()
I want to insert row in table ispu_plan_updated. Is something like this possible and can I insert rows in ispu_plan_updated using views?
Thank you
You can use a trigger to achieve that:
DROP TRIGGER IF EXISTS ispu_plan_trigger;
DELIMITER |
CREATE TRIGGER ispu_plan_trigger AFTER UPDATE ON ispu_plan
FOR EACH ROW BEGIN
-- example condition with update:
IF NEW.datum_donosenja_plana >= '2017-01-01' THEN
UPDATE ispu_plan_updated SET naziv_plan = 'some_value' WHERE id = NEW.id
LIMIT 1;
END IF;
END;
DELIMITER ;
Related
I'll start by explaining how the db should work:
In this example I have a table that stores work orders, this table has 5 total fields: ID, Number, Worker, temperature, humidity.
And another table that stores sensor data with 4 fields: ID, Device ID, Temp, Hum.
We built an APP that allows workers to submit work order data, My problem comes here The app generates the ID, Number and Worker field, and we want to add the sensor data (Temperature and humidity) to that table every time an insert is made. I tried doing this with a trigger but i get "Error Code: 1442. Can't update table 'ordenes' in stored function/trigger because it is already used by statement which invoked this stored function/trigger."
I tried multiple ways of doing it but I either get no change on the table or that error message.
Im looking for a way to do this:
trigger after insert
> insert into "new created line"(temperature, humidity) values
(select temp,humidity from sensors order by id desc limit 1)
Thanks in advance
EDIT:
Create Scheme and table:
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
CREATE SCHEMA IF NOT EXISTS `Cegasa` DEFAULT CHARACTER SET utf8 ;
USE `Cegasa` ;
DROP TABLE IF EXISTS `Cegasa`.`ORDENES` ;
CREATE TABLE IF NOT EXISTS `Cegasa`.`ORDENES` (
`idORDENES` INT NOT NULL AUTO_INCREMENT,
`NumOrden` VARCHAR(45) NULL,
`Empleado` VARCHAR(45) NULL,
`Temperatura` VARCHAR(45) NULL,
`Humedad` VARCHAR(45) NULL,
PRIMARY KEY (`idORDENES`))
ENGINE = InnoDB;
DROP TABLE IF EXISTS `Cegasa`.`sensores` ;
CREATE TABLE IF NOT EXISTS `Cegasa`.`sensores` (
`id` INT NOT NULL AUTO_INCREMENT,
`EUI` VARCHAR(45) NULL,
`Temp` VARCHAR(45) NULL,
`Hum` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
USE `Cegasa`;
DELIMITER $$
USE `Cegasa`$$
DROP TRIGGER IF EXISTS `Cegasa`.`ORDENES_AFTER_INSERT` $$
USE `Cegasa`$$
CREATE DEFINER = CURRENT_USER TRIGGER `Cegasa`.`ORDENES_AFTER_INSERT` AFTER INSERT ON `ORDENES` FOR EACH ROW
BEGIN
insert into `cegasa`.`Ordenes` (
`temp`,
`hum`
) SELECT temp,hum FROM sensores ORDER BY ID DESC LIMIT 1;
END$$
DELIMITER ;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
Insert for example sensor data:
INSERT INTO `cegasa`.`sensores`
(`id`,
`EUI`,
`Temp`,
`Hum`)
VALUES
(default,
"th312322aa",
"10",
"33"),(
default,
"daedaf12392",
"30",
"70"
);
Similar insert to the one the app makes
INSERT INTO `cegasa`.`ordenes`
(`idORDENES`,
`NumOrden`,
`Empleado`)
VALUES
(default,
1,
"123a");
Desired outcome after this insert
CREATE TABLE IF NOT EXISTS `sensores` (
`id` INT NOT NULL AUTO_INCREMENT,
`EUI` VARCHAR(45) NULL,
`Temp` VARCHAR(45) NULL,
`Hum` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
INSERT INTO `sensores` (`id`,`EUI`,`Temp`,`Hum`) VALUES
(default, "th312322aa", "10", "33"),
(default, "daedaf12392", "30", "70");
SELECT * FROM sensores;
id
EUI
Temp
Hum
1
th312322aa
10
33
2
daedaf12392
30
70
CREATE TABLE IF NOT EXISTS `ordenes` (
`idORDENES` INT NOT NULL AUTO_INCREMENT,
`NumOrden` VARCHAR(45) NULL,
`Empleado` VARCHAR(45) NULL,
`Temperatura` VARCHAR(45) NULL,
`Humedad` VARCHAR(45) NULL,
PRIMARY KEY (`idORDENES`))
ENGINE = InnoDB;
CREATE TRIGGER get_last_Temp_Hum
BEFORE INSERT ON ordenes
FOR EACH ROW
BEGIN
DECLARE new_temp VARCHAR(45); -- declare intermediate variables
DECLARE new_hum VARCHAR(45);
SELECT Temp, Hum INTO new_temp, new_hum -- select vast values into it
FROM sensores
ORDER BY id DESC LIMIT 1;
SET NEW.Temperatura = new_temp, -- set columns values in newly inserted row
NEW.Humedad = new_hum; -- to the values stored in the variables
END
INSERT INTO `ordenes` (`idORDENES`,`NumOrden`,`Empleado`) VALUES
(default, 1, "123a");
SELECT * FROM ordenes;
idORDENES
NumOrden
Empleado
Temperatura
Humedad
1
1
123a
30
70
fiddle
Trigger fires on INSERT statement but before the values are inserted into the table (i.e. the insertion is an intention yet). The query in the trigger retrieves needed values into the variables, then SET statement copies these values into the columns in the row which will be inserted. And after the trigger finishes the row contains needed values in the columns, and these values are saved into the table.
I have two tables:
CREATE TABLE `class` (
`id` int(11) NOT NULL,
`class_no` int(11) NOT NULL,
`class_title` varchar(11) NOT NULL,
`no_of_students` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `enrolment` (
`id` int(11) NOT NULL,
`ssn` varchar(11) NOT NULL,
`class_no` int(11) NOT NULL,
`grade` varchar(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
What I am trying to do is when someone enters into 'Enrolment', if the class number entered matches an entry in 'Class', e.g. class number 2 - then i want what is typed into grade on 'Enrolment' (i.e 5) to add to whatever is already in number of students (Say if it's 10). In this case, the number of students would then say 15. This is the current trigger i have, however is not adding:
DELIMITER $$
CREATE TRIGGER `after_insert_add_one` AFTER INSERT ON `enrolment` FOR EACH ROW UPDATE class
SET class.no_of_students = class.no_of_students + enrolment.grade WHERE class_no = NEW.class_no
$$
DELIMITER ;
If anyone knows i'd be grateful for the help.
You must use the NEW key instead of the name of table enrolment, try this
CREATE TRIGGER `after_insert_enrolment` AFTER INSERT ON `enrolment`
FOR EACH ROW BEGIN
UPDATE class c
SET
c.no_of_students = c.no_of_students + NEW.grade
WHERE c.class_no = NEW.class_no;
END
You’re not making changes with SET class.no_of_students = class.no_of_students + enrolment.grade if you’re not using enrolment.class_no to compare using where clause. Update it with NEW in place of enrolment if you’re using it:
DELIMITER $
CREATE TRIGGER `after_insert_add_one` AFTER INSERT ON `enrolment` FOR EACH ROW UPDATE class
SET class.no_of_students = class.no_of_students + NEW.grade WHERE class_no = NEW.class_no
$
DELIMITER ;
Can anyone help me understand what this code does?
CREATE TABLE `exams` (
`id` int(11) NOT NULL, `score` int(2) NOT NULL, `class` int(11) NOT NULL, `date` date NOT NULL, PRIMARY KEY (`class`,`date`,`id`));
CREATE TRIGGER `trig3` BEFORE INSERT ON `exams` FOR EACH ROW SET #xxx = #xxx + 1;
SET #xxx = 0;
INSERT INTO `exams` VALUES (10001,24,1,'2013-09-16'), (10005,30,1,'2013-09-16'), (10083,30,1,'2014-03-21'), (10120,26,1,'2014-03-21'), (10035,23,1,'2014-07-22'), (10005,28,2,'2014-01-23'), (10001,27,2,'2014-06-30'), (10001,25,4,'2014-01-23'), (10083,22,4,'2014-01-23'), (10120,30,4,'2014-01-23'), (10005,22,4,'2014-03-21');
SELECT #xxx;
I understand the creation of the table and the insertion of values but i don't get the rest of it.
The code seams to be a workaround way to count or check if the multi insert inserted all records or not.
SELECT #xxx;
| #xxx |
| ---- |
| 11 |
But MySQL doesn't have a native way to find that out.
see demo
A more easy MySQL code to do the same without needing the TRIGGER code and SET.
But it will require a new table structure to function.
CREATE TABLE `esami` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, `id_studente` int(11) NOT NULL
, `voto` int(2) NOT NULL
, `id_corso` int(11) NOT NULL
, `data` date NOT NULL
, UNIQUE KEY (`id_corso`,`data`,`id_studente`)
);
And the query to test if all records where inserted by the multi insert.
SELECT
COUNT(*)
FROM
esami
WHERE
id BETWEEN LAST_INSERT_ID() AND LAST_INSERT_ID() + 11;
see demo
i have a problem in after insert trigger. when i am inserting the data in the table it should automatically update the date and it should be the current date. but when i am executing the following query it is not working properly in my table.
first i created a table:
DROP TABLE IF EXISTS `ignite`.`products`;
CREATE TABLE `ignite`.`products`(
`products_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`products_model` varchar(30) NOT NULL,
`model_hash` bigint(20) unsigned NOT NULL,
`Product_name` varchar(45) NOT NULL,
`created` datetime NOT NULL,
PRIMARY KEY (`products_id`)
) ENGINE=MyISAM AUTO_INCREMENT=977 DEFAULT CHARSET=latin1;
Then i created this trigger:
use ignite;
CREATE TRIGGER created_date BEFORE INSERT ON products
FOR EACH ROW
SET NEW.created = NOW();
but when i am inserting the data in this table:
use ignite;
INSERT INTO products
(products_id, products_model, model_hash, Product_name)
values
(123, "456645", 457567, "awetert");
This is showing the following error:
field 'created' does not have default value. error-1364
It's because on your INSERT statement does not include the created values. You need to include it for example with zero datetime value:
INSERT INTO products
(products_id, products_model, model_hash, Product_name, created)
values
(123, "456645", 457567, "awetert", "0000-00-00 00:00:00");
I'm trying out stored procedures for the first time, and I can't figure out what I'm doing wrong.
Here's the table definition:
CREATE TABLE `answers` (
`anid` int(11) unsigned NOT NULL auto_increment,
`uid` int(11) NOT NULL,
`dtid` int(11) NOT NULL,
`answer` text NOT NULL,
PRIMARY KEY (`anid`),
KEY `uid` (`uid`),
KEY `dtid` (`dtid`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
anid is the primary key, uid is user id, dtid is datum id, and answer is the answer provided.
Whenever I get a new answer for a given datum (question) and user id, I want to first delete any old answer to that same question by that same user, and then insert the new one.
Here's the procedure declaration:
DELIMITER //
CREATE PROCEDURE new_answer(uid INT(11),dtid INT(11),answer TEXT)
BEGIN
DELETE FROM `answers` WHERE `uid` = uid AND `dtid` = dtid;
INSERT INTO `answers` SET `uid` = uid, `dtid` = dtid, `answer` = answer;
END//
However, whenever I CALL new_answer ALL existing rows are deleted, and that one new answer is now the only row in the table.
Hope it's something simple, thanks for your help.
Rename your parameters:
DELIMITER //
CREATE PROCEDURE new_answer(p_uid INT(11),p_dtid INT(11),p_answer TEXT)
BEGIN
DELETE FROM `answers` WHERE `uid` = p_uid AND `dtid` = p_dtid;
INSERT INTO `answers` SET `uid` = p_uid, `dtid` = p_dtid, `answer` = p_answer;
END//
You should probably try naming procedure arguments different than table columns.
Anyway, it looks like all you need is a single INSERT ... ON DUPLICATE KEY UPDATE query.
I'm not familiar with stored procedures, but what about renaming your function parameters to x and y instead of the very same as the column names?