insert is failing because of my trigger mysql - mysql

I have a problem with my trigger code.
After I wrote my trigger I wrote Insert to test the trigger. But my Insert gets error as
Error Code:1109. Unknown table employees in field list.
If I put the insert before the trigger-everything works perfect. But I want this Insert to test the trigger.
drop database if exists kontrolno;
create database kontrolno;
use kontrolno;
CREATE TABLE departments(
id TINYINT UNSIGNED PRIMARY KEY,
name CHAR(12) NOT NULL,
min_salary SMALLINT UNSIGNED NOT NULL,
max_salary SMALLINT UNSIGNED NOT NULL
) ENGINE=InnoDB;
CREATE TABLE employees(
id SMALLINT UNSIGNED PRIMARY KEY,
name VARCHAR(255) NOT NULL,
salary SMALLINT UNSIGNED NOT NULL,
department_id TINYINT UNSIGNED,
constraint FOREIGN KEY (department_id)
REFERENCES departments(id)
) ENGINE=InnoDB;
insert into departments(id,name,min_salary,max_salary)
values(1,"qa", 800,2000),
(2,"jd",1200,3500);
DROP TRIGGER if exists checkSalary;
delimiter |
create trigger checkSalary before Insert on employees
for each row
begin
if(employees.salary>max_salary OR employees.salary<min_salary)
then signal sqlstate '45000' set MESSAGE_TEXT="the salary is not valide";
end if;
end;
|
delimiter ;
insert into employees(id,name,salary,department_id)
values(1,"ivan", 200,1);

You had mistakes in your trigger code.
The trigger code should be:
DROP TRIGGER if exists checkSalary;
delimiter |
create trigger checkSalary before Insert on employees
for each row
begin
if(new.salary>(select max_salary from departments where id=new.department_id)
OR
new.salary<(select min_salary from departments where id=new.department_id) )
then signal sqlstate '45000' set MESSAGE_TEXT="the salary is not valid";
end if;
end;
|
delimiter ;

Related

Create trigger before insert in table

I created a trigger before inserting into the employee table to calculate its age, but trying to insert into the employee table returns the following erro Error Code: 1442. Can't update table 'employee' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
CREATE TABLE IF NOT EXISTS person (
ssn INT(20) NOT NULL,
name_person VARCHAR(200) NOT NULL,
birth_date DATE NOT NULL,
PRIMARY KEY (ssn))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS employee (
ssn_employee INT(20) NOT NULL,
job_title VARCHAR(100) NOT NULL,
age INT(10) DEFAULT NULL,
PRIMARY KEY(ssn_employee),
FOREIGN KEY (ssn_employee)
REFERENCES person (ssn)
ON UPDATE CASCADE)
ENGINE = InnoDB;
DELIMITER $$
CREATE TRIGGER employeeAge
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
DECLARE dob DATE;
DECLARE ssn_employee1 int;
SELECT new.ssn_employee INTO ssn_employee1;
SELECT person.birth_date into dob FROM person WHERE ssn = ssn_employee1;
UPDATE employee
SET new.age = DATEDIFF(dob, GETDATE());
END
DELIMITER;$$
Thank you guys. I'm a beginner and the tips clarified. I did this:
```lang_sql
DELIMITER $$
CREATE TRIGGER employeeAge
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
DECLARE dob DATE;
DECLARE ssn_employee1 int;
SELECT new.ssn_employee INTO ssn_employee1;
SELECT person.birth_date into dob FROM person WHERE ssn = ssn_employee1;
SET new.age = TIMESTAMPDIFF(YEAR, dob, NOW());
END;
DELIMITER $$

MySQL Use last inserted id from stored procedure

Through phpmyadmin's interface, I created a stored procedure as follows:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_checkin_create`(IN `userid` INT(10), IN `organizationid` INT(10), IN `checkindate` DATETIME(6), IN `checkoutdate` DATETIME(6), IN `checkinid` INT(10))
NO SQL
Insert Into checkin Values(CheckInID, UserID, OrganizationID, CheckInDate, CheckOutDate) ON DUPLICATE
KEY UPDATE CheckInID=CheckInID, UserID=userid, OrganizationID=organizationid, checkindate=checkindate, CheckOutDate=checkoutdate$$
DELIMITER ;
How do I return LAST_INSERT_ID() from this procedure? I know the use-case of:
SELECT LAST_INSERTED_ID();
But i can't find a way to combine this query in the procedure without getting ambiguous errors.
Any help would be appreciated.
EDIT 1
Create table statement:
DROP TABLE IF EXISTS `checkin`;
CREATE TABLE IF NOT EXISTS `checkin` (
`CheckInID` int(11) NOT NULL AUTO_INCREMENT,
`UserID` int(11) NOT NULL,
`OrganizationID` int(11) DEFAULT NULL,
`CheckInDate` datetime DEFAULT NULL,
`CheckOutDate` datetime(6) NOT NULL,
PRIMARY KEY (`CheckInID`),
UNIQUE KEY `CheckInID` (`CheckInID`)
) ENGINE=MyISAM AUTO_INCREMENT=4407 DEFAULT CHARSET=latin1;
Formally:
DELIMITER $$
CREATE
DEFINER=`root`#`localhost`
PROCEDURE `sp_checkin_create` ( IN `userid` INT(10),
IN `organizationid` INT(10),
IN `checkindate` DATETIME(6),
IN `checkoutdate` DATETIME(6),
IN `checkinid` INT(10),
OUT inserted_id BIGINT )
NO SQL
BEGIN
Insert Into checkin
Values (CheckInID, UserID, OrganizationID, CheckInDate, CheckOutDate)
ON DUPLICATE KEY UPDATE
UserID=userid, OrganizationID=organizationid, checkindate=checkindate, CheckOutDate=checkoutdate;
SELECT LAST_INSERT_ID() INTO inserted_id;
END;
$$
DELIMITER ;
and
CALL sp_checkin_create(123, 456, '2021-01-01', '2021-01-01', 789, #last_inserted_id);
SELECT #last_inserted_id;
Really: LAST_INSERT_ID() is used only when autoincrement generates new value - so it makes no sense in both cases (both new row inserted with AI explicit assigning and ODKU fired).

MySQL Non Sequential ID

Challenge:
Create a method to set "auto_increment" values for tables in a non-sequential way.
The goal is to override the "auto_increment" mechanism and allow the function "LAST_INSERT_ID()" to continue working as expected (returning an INT), so that no changes are needed in software side.
My Solution
The method I found is based on an auxiliary table (unique_id), that stores values available to be assigned. Values are then selected randomly, and removed from the tables as used. When the table gets empty, a new set of ID's is created.
This example is working as expected, but with one problem.
Tables for the demo:
CREATE TABLE `unique_id` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=100;
CREATE TABLE `test_unique_id` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
Defined a stored procedure and a function:
DELIMITER $$
DROP PROCEDURE IF EXISTS `UNIQUE_ID_REFILL`$$
CREATE PROCEDURE UNIQUE_ID_REFILL()
BEGIN
DECLARE a INT Default 0 ;
simple_loop: LOOP
SET a=a+1;
INSERT INTO unique_id (id) values(null);
IF a=100 THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
END $$
DROP FUNCTION IF EXISTS `UNIQUE_ID_GET`$$
CREATE FUNCTION UNIQUE_ID_GET()
RETURNS INT(11)
MODIFIES SQL DATA
BEGIN
DECLARE new_id INT(11);
DECLARE unique_id_count INT(11);
SET new_id = 0;
SELECT COUNT(*) INTO unique_id_count FROM unique_id;
IF unique_id_count=0 THEN
CALL UNIQUE_ID_REFILL();
END IF;
SELECT id INTO new_id FROM unique_id ORDER BY RAND() LIMIT 1;
DELETE FROM unique_id WHERE id = new_id;
RETURN new_id;
END $$
Created a Trigger on the destination table (test_unique_id):
CREATE TRIGGER test_unique_id__unique_id BEFORE INSERT ON test_unique_id
FOR EACH ROW
SET NEW.id = UNIQUE_ID_GET();
The solution is getting the random ID's as expected:
INSERT INTO test_unique_id(name) VALUES ('A'),('B'),('C');
Creates the rows:
id name
154 'A'
129 'B'
173 'C'
The Problem
The main problem is that LAST_INSERT_ID() stops working... and the software side is broken:
SELECT LAST_INSERT_ID();
0
Any ideas on how to solve this problem? or any other different approach to the challenge?
Thank you very much.

insert trigger: issue with constraint

I'm trying to create trigger on customer-order database where each customer has several orders and each order has several items.
I'm planning to create a trigger to ensure that
the total number of all orders place by the same customer cannot
exceed 10000
How can create the insert trigger for above constraint.
Here is my SQL file with sample data provided.
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
CREATE TABLE customers
(`id` int not null auto_increment primary key, `first_name` varchar(64), `last_name`varchar(64) );
INSERT INTO customers(`first_name`, `last_name`)VALUES('Jhon', 'Doe');
CREATE TABLE items
(`id` int not null auto_increment primary key,`item` varchar(64),`price` decimal(19,2));
INSERT INTO items(`item`, `price`)VALUES('Item1', 10.5),('Item2', 25);
CREATE TABLE orders
(`id` int not null auto_increment primary key, `date` date, `customer_id` int,`status` int not null default 1, -- 1 new constraint fk_customer_id foreign key (customer_id) references customers (id));
INSERT INTO orders(`date`, `customer_id`, `status`)VALUES(CURDATE(), 1, 1);
CREATE TABLE order_items(`id` int not null auto_increment primary key,
`order_id` int not null, `item_id` int not null, `quantity` decimal(19,3) not null, `price` decimal(19,3) not null,
constraint fk_order_id foreign key (order_id) references orders (id),
constraint fk_item_id foreign key (item_id) references items (id));
INSERT INTO order_items(`order_id`, `item_id`, `quantity`, `price`)VALUES
(1, 1, 2, 10.5),(1, 2, 4, 25);
;
Although Jahul's answer would technically work, here is alternative logic:
DELIMITER $$
CREATE TRIGGER `customer_orders_check`
BEFORE INSERT ON `orders` FOR EACH ROW
BEGIN
IF ((select count(*)
from `orders`
where a.customer_id = NEW.customer_id
) >= 10000 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Too many orders already';
END IF;
END;
$$
DELIMITER ;
That said, I would suggest an alternative approach. Counting up to 10,000 rows for each insert seems like a lot of work. Instead, keep the counter in the customers table, using an after insert trigger (and perhaps after update/delete as well). Then when inserting a new row, you can just check the count in customers.
This trigger will stop insert --
CREATE TRIGGER `customer_orders_check`
BEFORE INSERT ON `orders` FOR EACH ROW
BEGIN
IF exists(select count(*)
from `orders` a
where a.customer_id= NEW.customer_id
having count(*)>=10000 ) THEN
SET NEW.id = 1 ;
END IF;
END;

Mysql trigger #1064 error

I'm trying to write a trigger to solve innodb auto_increment problem. I want to make orderID is auto_increment however innodb does not allow me. Here is ORDER table
CREATE TABLE IF NOT EXISTS `ORDER` (
`placeID` INT UNSIGNED NOT NULL,
`orderID` INT UNSIGNED NOT NULL,
`userID` INT UNSIGNED NOT NULL ,
`tableNum` SMALLINT NOT NULL,
`orderStatus` TINYINT NOT NULL,
`orderDate` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`placeID`,`orderID`),
FOREIGN KEY (`userID`) REFERENCES `USER` (`userID`),
FOREIGN KEY (`placeID`) REFERENCES `PLACE` (`placeID`))
ENGINE=InnoDB;
Here is the trigger
delimiter $$
DROP TRIGGER /*!50032 IF EXISTS */ `ORDER_TRIGGER` $$
CREATE TRIGGER `ORDER_TRIGGER` BEFORE INSERT ON `ORDER`
FOR EACH ROW
BEGIN
DECLARE orderID INT UNSIGNED;
SELECT MAX(`orderID`) INTO orderID FROM `ORDER` WHERE `placeID` = NEW.placeID;
IF orderID IS NULL THEN
orderID = 1;
END IF;
SET NEW.orderID = orderID+1;
END;
$$
delimiter;
When I execute this script I get this error.
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '= 1;
END IF;
SET NEW.orderID = orderID+1;
END' at line 7
Can anybody help me? I looked at google but I can't find accurate solution.
I found my mistake. This is right code.
delimiter $$
DROP TRIGGER /*!50032 IF EXISTS */ `ORDER_TRIGGER` $$
CREATE TRIGGER `ORDER_TRIGGER` BEFORE INSERT ON `ORDER`
FOR EACH ROW
BEGIN
DECLARE orderID INT UNSIGNED;
SELECT MAX(`ORDER`.`orderID`) AS ID INTO orderID FROM `ORDER` WHERE `ORDER`.`placeID` = NEW.placeID;
IF orderID IS NULL THEN
SET orderID = 0;
END IF;
SET NEW.orderID = orderID+1;
END;
$$