Trigger before insert is not working - mysql

There is a "session" table, for it you need to write a trigger to check the date and time before inserting the data, if the date and time are greater than or equal to the current date and time, the value can be inserted into the table, otherwise the error message is displayed.
CREATE TABLE `seance` (
`idSeance` int(11) NOT NULL,
`Date/time` datetime NOT NULL,
`Hall_idHall` int(45) DEFAULT NULL,
`Hall_Theatre_idTheatre` int(45) DEFAULT NULL,
`Performance_idPerformance` int(45) NOT NULL,
`price` int(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TRIGGER `insert_seance` BEFORE INSERT ON `seance`
FOR EACH ROW BEGIN
IF (NEW.`Date/time` >= CURRENT_TIMESTAMP)
THEN
INSERT INTO seance
(`idSeance`, `Date/time`, `Hall_idHall`,
`Hall_Theatre_idTheatre`,`Performance_idPerformance`, `price`)
VALUES (NEW.`idSeance`,NEW.`Date/time`,NEW.`Hall_idHall`,
NEW.`Hall_Theatre_idTheatre`,NEW.`Performance_idPerformance`,NEW.`price`);
ELSE
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Error for updating values';
END IF;
END
I can not understand why it gives an error?
1442 - Can't update table 'seance' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

This is one of few mysql error messages which are crystal clear (IMHO). However - You don't need that INSERT statement. Just rise an error if the data is invalid. If the data is valid, you don't need to do anything in the trigger. The row will be just inserted.
CREATE TRIGGER `insert_seance` BEFORE INSERT ON `seance` FOR EACH ROW
BEGIN
IF (NEW.`Date/time` < CURRENT_TIMESTAMP)
THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error for updating values';
END IF;
END

Related

Rollback Stored procedure Call is not working in the mySQL

I have created a student table.
CREATE TABLE `student` (
`id` int DEFAULT NULL,
`name` varchar(5) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
I have created a stored procedure inserting the data.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_studentinsert1`(in_id int, in_name varchar(5),inn_id int, inn_name varchar(10))
BEGIN
DECLARE `_rollback` BOOL DEFAULT 0;
DECLARE exit HANDLER FOR SQLEXCEPTION
begin
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'SQLError occured. Triggered ROLLBACK';
select 'err' as message;
-- ERROR
end;
start transaction;
insert into student(id,name) values(in_id,in_name);
INSERT INTO student(id,name) values(inn_id,inn_name);
commit;
select * from student;
END$$
DELIMITER ;
. I have written two insert queries inside of stored procedure. I have given first two input parameters valid data, For 2nd record , I have given invalid data, once run the sp, first record inserted & 2nd record exception happen but once exception happen , 1st record rollback not happen.
Please help me.

How to cancel an INSERT operation in a PostgreSQL Database from within a BEFORE-INSERT TRIGGER (Have done this in MySQL)

I made some work in MySQL where I did put a lot of business logic in the Back-end using TRIGGERS, I have to migrate to PostgreSQL and unfortunately the trigger mechanisms are not the same. So far I think I have to recode them all manually.
Here is a small issue : in a Postgresql trigger that executes before insert How do I cancel the insert operation from within the trigger function?
Example: I have a table with 2 fields (id,field_a), I have a trigger that executes in before inserting a row in this table.
Just to illustrate this I cancel this insert from within the trigger if the field_a = 5.
So in MySQL I did this(Raised a custom exception) and it worked (stopped the insert and showed a custom message) :
CREATE TABLE `mydatabase`.`mytable` (
`id` int(11) DEFAULT '0',
`field_a` int(11) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC ;
CREATE DEFINER=`username`#`localhost` TRIGGER `the_trigger_in_mysql` BEFORE INSERT ON `mytable` FOR EACH ROW
BEGIN
IF NEW.a_field = 5 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Please choose another number!!';
END IF;
END;
I am trying to do the same here for Postgresql , found some new stuff reading about Pgplsql and all
CREATE TABLE "public"."mytable" (
"id" int4 DEFAULT '0',
"field_a" int4 DEFAULT '0',
CONSTRAINT "mytable__pkey" PRIMARY KEY ("id")
) ;
ALTER TABLE "public"."log"
OWNER TO "username";
CREATE TRIGGER "the_trigger_in_postgresql" BEFORE INSERT ON "public"."mytable"
FOR EACH ROW
EXECUTE PROCEDURE "public"."the_trigger_in_postgresql_function"();
CREATE OR REPLACE FUNCTION "public"."the_trigger_in_postgresql_function"()
RETURNS "pg_catalog"."trigger" AS $BODY$BEGIN
IF NEW.a_field = 5 THEN
RAISE DEBUG 'Please choose another number!!';
END IF;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION "public"."the_trigger_in_postgresql_function"() OWNER TO "username";
Unfortunately it doesn't work! Any thoughts about this?
So As pointed in the link by #user2864740 , the Idea was good same as MySQL raising an exception but I was wrong in the spelling the code must be
RAISE EXCEPTION 'Please choose another number!!';
instead of raise debug in the TRIGGER body function

MySQL Insert/Update Trigger with AUTO_INCREMENT

So, I've got a table roughly as follows:
CREATE TABLE CUSTOMER (
CUSTID INT NOT NULL AUTO_INCREMENT,
NAME CHAR (45),
CONSTRAINT CUSTOMER_PRIMARY_KEY PRIMARY KEY (CUSTID))
AUTO_INCREMENT = 100;
I'm auto incrementing the CUSTID so that it's possible to simply insert a name and have it created with the next available CUSTID. However, I also want to ensure that it isn't possible to set the CUSTID value to zero, either on creation of the row or on update so I've constructed the following trigger:
DELIMITER $$
CREATE TRIGGER `custid_before_insert` BEFORE INSERT ON `CUSTOMER`
FOR EACH ROW
BEGIN
IF (NEW.CUSTID) <= 0 THEN
SIGNAL SQLSTATE '12345'
SET MESSAGE_TEXT = 'Check constraint on CUSTOMER.CUSTID failed';
END IF;
END$$
CREATE TRIGGER `custid_before_update` BEFORE UPDATE ON `CUSTOMER`
FOR EACH ROW
BEGIN
IF (NEW.CUSTID) <= 0 THEN
SIGNAL SQLSTATE '12345'
SET MESSAGE_TEXT = 'Check constraint on CUSTOMER.CUSTID failed';
END IF;
END$$
DELIMITER ;
Unfortunately in my blissful ignorance of how AUTO_INCREMENT worked, I've come to the conclusion that this is the wrong way to go about this. Trying to insert a customer with no CUSTID value is tripping the trigger causing the insert to fail which I presume is due to the value being a zero before insertion when AUTO_INCREMENT assigns it a value.
Would the best way to do this really be to change the trigger to occur after the insert and delete the row or is there a better way to do this to just throw an error?
The insert trigger is not needed.
From Auto_Increment
No value was specified for the AUTO_INCREMENT column, so MySQL
assigned sequence numbers automatically. You can also explicitly
assign 0 to the column to generate sequence numbers.
E.G.
create table t(id int auto_increment, primary key(id));
insert into t(id) values (0);
select id from t;
# 1
Update:
To allow the insert to complete when CUSTID is not specified,
INSERT INTO customer(name) VALUES('Chuck');
check for null in the trigger:
IF NEW.CUSTID IS NOT NULL AND NEW.CUSTID <= 0 THEN
Inserting '0' into an auto-increment column causes it to increment the same as inserting NULL, so you really neither need nor want the INSERT trigger. Try it with just the UPDATE trigger.

CHECK constrain in MySQL

I have a simple table in MySQL that contain two columns: Timestamp and floats. All I need is to ensure that new inserted value is greater than any other before in table. How can I achive that proper way?
CREATE TABLE IF NOT EXISTS `mydb`.`table1` (
`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`read` FLOAT UNSIGNED NOT NULL,
PRIMARY KEY (`timestamp`))
ENGINE = InnoDB;
CREATE TRIGGER TRG_CHECKCONSTRAINT
BEFORE INSERT ON TABLE1
FOR EACH ROW
BEGIN
DECLARE msg varchar(255);
IF NOT new.READ > (SELECT MAX(READ) FROM TABLE1) THEN
SET msg = 'INVALID DATA'
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
END IF;
END
Use a BEFORE INSERT trigger. MySQL does not use CHECK constraints.

Before insert trigger prevents following INSERT INTO statements to execute

I have a problem with the following sql code executed in MySQL Workbench 5.6. The table is orderly created, the trigger creation code is also run without errors. But when I try to run the both insert into statements I have an error Error Code: 1054. Unknown column 'Pass' in 'field list'. If I run the last select statements it is also runned as expected!?
I really can not imagine what is happening after running the trigger creation script!?
If I do not run the triger creation code before the insert into statements they are executed as expected and the data is inserted in the columns.
/*TASK 15: Write a SQL statement to create a table Users. Users should have username,
password, full name and last login time. Choose appropriate data types for the table fields.
Define a primary key column with a primary key constraint. Define the primary key column
as identity to facilitate inserting records. Define unique constraint to avoid repeating
usernames. Define a check constraint to ensure the password is at least 5 characters long.
*/
create table Users(
UserID int auto_increment not null,
Username nvarchar(50) not null,
Pass varchar(100) not null,
FullName nvarchar(100),
LastLoginTime datetime,
constraint PK_Users primary key(UserID),
constraint UK_Users_Username UNIQUE(Username),
constraint CH_Users_Password CHECK(length(users.Pass)>=5)
);
DELIMITER $$
CREATE TRIGGER `TR_BeforeInsert_Users`
BEFORE INSERT ON `users`
FOR EACH ROW
BEGIN
IF LENGTH(`Pass` ) < 5 THEN
SIGNAL SQLSTATE '12345'
SET MESSAGE_TEXT = 'check constraint on Pass failed';
END IF;
END$$
delimiter ;
Insert into Users(Username, Pass, FullName,lastlogintime) values('ttitto','alabala','Todor', now());
Insert into Users(Username, Pass, FullName,lastlogintime) values('ttitt','ala','Todor', now());
select length(Pass) from users;
Within triggers, one must reference columns with either the NEW or OLD pseudo-table prefix. In your case:
DELIMITER $$
CREATE TRIGGER `TR_BeforeInsert_Users`
BEFORE INSERT ON `users`
FOR EACH ROW
BEGIN
IF CHAR_LENGTH(NEW.Pass) < 5 THEN
SIGNAL SQLSTATE '12345'
SET MESSAGE_TEXT = 'check constraint on Pass failed';
END IF;
END$$
delimiter ;