How to implement 2 or more triggers on mysql - mysql

Hello this is my structure for tbl_patient:
CREATE TABLE tbl_patient
(
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
idPatient varchar(15) DEFAULT NULL,
namePatient varchar(40) NOT NULL,
age int NOT NULL,
birthDate date,
gender varchar(15) NOT NULL,
status varchar(15) NOT NULL,
address varchar(255) NOT NULL,
work varchar(25) NOT NULL,
phone varchar(15) NOT NULL
)
ENGINE=InnoDb;
I want to put 2 triggers on tbl_patient:
CREATE TRIGGER patientTrigger
BEFORE INSERT ON tbl_patient
FOR EACH ROW
SET NEW.idPatient = CONCAT("PAS-",COALESCE((SELECT MAX(id)+1 from tbl_patient),1));
CREATE TRIGGER ageTrigger
BEFORE INSERT ON tbl_pasien
FOR EACH ROW
SET NEW.age = YEAR(CURDATE()) - YEAR(birthDate);
But I got some error with :
1235 - This version of MariaDB doesn't yet support 'multiple triggers with the same action time and event for one table'
How can I implement that 2 triggers on my table?

You could use computed columns instead:
CREATE TABLE tbl_patient
(
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
idPatient varchar(15) AS (CONCAT("PAS-", id)),
namePatient varchar(40) NOT NULL,
age int AS (YEAR(CURDATE()) - YEAR(birthDate)),
birthDate date,
gender varchar(15) NOT NULL,
status varchar(15) NOT NULL,
address varchar(255) NOT NULL,
work varchar(25) NOT NULL,
phone varchar(15) NOT NULL
)
ENGINE=InnoDb;
Remarks:
1) Note that your code to calculate age is not correct, for example (2015-12-31 and 2016-01-01).
Better way to calcualte age:
SELECT YEAR(NOW()) - YEAR(birthDate) -
(DATE_FORMAT(birthDate, '%m%d') > DATE_FORMAT(NOW(), '%m%d')) AS age
2)
CREATE TRIGGER patientTrigger
BEFORE INSERT ON tbl_patient
FOR EACH ROW
SET NEW.idPatient = CONCAT("PAS-",COALESCE((SELECT MAX(id)+1 from tbl_patient),1));
is poor solution when multiple concurrent INSERTs occur.
EDIT
Using triggers you have update age when user update birthDate (yes it may happen).
Other possible solution is to simply create view.
CREATE VIEW vw_patient
AS
SELECT `id`, `namePatient`, `birthDate`,
`gender`, `status`, `address`, `work`, `phone`,
CONCAT("PAS-", id) AS `idPatient`,
YEAR(NOW()) - YEAR(birthDate) -
(DATE_FORMAT(birthDate, '%m%d') > DATE_FORMAT(NOW(), '%m%d')) AS `age`
FROM `tbl_patient`
SqlFiddleDemo

Try to merge body of both triggers into single one, something like this:
CREATE TRIGGER patientTrigger BEFORE INSERT ON tbl_patient FOR EACH ROW
BEGIN
SET NEW.idPatient = CONCAT("PAS-",COALESCE((SELECT MAX(id)+1 from tbl_patient),1));
SET NEW.age = YEAR(CURDATE()) - YEAR(birthDate);
END

Related

Trigger to update all records with same data

I have a column named 'Ratio' in my table. Which I want to use to store the value of the ratio of the items with respect to the total value at a specific date.
The problem I'm facing is that the trigger only changes the ratio of one row (NEW.row) and leaves the values of the rest alone. But when one value changes I want them all to change since it is a ratio.
This is what I have so far;
CREATE TABLE `item_table` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`Date` DATE DEFAULT NULL,
`Name` VARCHAR(20) DEFAULT NULL,
`Value` DECIMAL(7 , 6 ) DEFAULT NULL,
`Ratio` DECIMAL(7 , 6 ) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE
TRIGGER `ins_ratio`
BEFORE INSERT ON `item_table` FOR EACH ROW
SET NEW . `Ratio` = NEW.`Value` / (SELECT
SUM(`Value`)
FROM
`item_table`
WHERE
Date = NEW.Date);
How can I get this done?
CREATE TRIGGER `ins_ratio`
BEFORE INSERT ON `item_table`
FOR EACH ROW
SET NEW.`Ratio` = NEW.`Value` / (SELECT COALESCE(SUM(`Value`), 0) + NEW.`Value`
FROM `item_table`
WHERE `Date` = NEW.`Date`);
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=e387a87a05422afec40ecad070e78627
Pay attention - your Ratio is cumulative, not recalculational.

Column count doesn't match value count at row 1 in MySQL

I have created a table with the following query:
CREATE TABLE `dailydata` (
`id` int(9) NOT NULL,
`Date` varchar(100) NOT NULL,
`EmpID` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`TeamName` varchar(100) NOT NULL,
`active` varchar(100) NOT NULL,
`idle` double NOT NULL,
`Stime` double NOT NULL,
`Etime` varchar(100) NOT NULL,
`Inofficehr` decimal(20,2) NOT NULL,
`activehr` double(19,2) NOT NULL,
`idlehr` double(19,2) NOT NULL,
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Set Primary key For 'id' column:
ALTER TABLE `dailydata`ADD PRIMARY KEY (`id`);
Now I'm trying to insert the data with this code:
INSERT INTO dailydata
SELECT A.Date, A.EmpID, B.name, B.TeamName,
SUM(CASE WHEN State = 'active' THEN A.MinutesatState ELSE 0 END) AS active,
SUM(CASE WHEN State = 'idle' THEN A.MinutesatState ELSE 0 END) AS idle,
Min(A.Statestarttime) AS Stime, MAX(A.StateEndtime) AS Etime,
ROUND((TIME_TO_SEC(MAX(A.StateEndtime))/60 -
TIME_TO_SEC(MIN(A.StateStarttime))/60)/60,2) as Inofficehr,
ROUND(SUM(CASE WHEN State = 'active' THEN A.MinutesatState ELSE 0 END)/60,2)
AS activehr,
ROUND(SUM(CASE WHEN State = 'idle' THEN A.MinutesatState ELSE 0 END)/60,2)
AS idlehr
FROM time A join ttld.login B on A.EmpID=B.username
WHERE A.Date='01-01-2019' AND A.Statestarttime <>'' AND A.StateEndtime <>''
GROUP BY A.EmpID;
But I'm getting this error:
#1136 - Column count doesn't match value count at row 1
I understand I have not define the ID in my insert code and the reason for it is I want it to auto populate.
How can I modify my INSERT query code to do so...
You have 13 columns in your table, but only 11 in your select, which is why you are getting this error.
But first, to make your id column auto-populate, you need to declare it as AUTO_INCREMENT. You can change it with an ALTER TABLE command:
ALTER TABLE dailydata CHANGE id id INT AUTO_INCREMENT PRIMARY KEY
Since you have a default value for your Timestamp column you don't need to insert a value for that.
To resolve the error you are seeing, you need to modify your INSERT query to to match the number of columns being inserted to the data either by
(a) naming the columns you are inserting; or
(b) inserting NULL values for the columns with no values (id and Timestamp)
e.g. (a)
INSERT INTO dailydata (`Date`, `EmpID`, `name`, `TeamName`, `active`, `idle` ,`Stime`, `Etime`, `Inofficehr`, `activehr`, `idlehr`)
SELECT A.Date, A.EmpID, B.name, B.TeamName,
...
e.g. (b)
INSERT INTO dailydata
SELECT NULL AS id,
A.Date, A.EmpID, B.name, B.TeamName,
...
NULL AS Timestamp
FROM ...

Error in creating a stored procedure

I'm trying to retrieve values by joining two tables (the customer and enquiry table),then i'm trying to store the retrieved values into another table that would come in handy for reasons irrelevant here.And then i'm finally deleting the retrieved values from the enquiry table. When i'm trying to execute the stored procedure i'm getting the following error shown in the screenshot below.
how do i resolve this error?
Stored Procedure:-
CREATE PROCEDURE `backup_eq`(
IN `eq` VARCHAR(15), IN `mail` VARCHAR(30), IN `dates` DATE, IN `cmp` VARCHAR(10), IN `rea` VARCHAR(50))
NOT DETERMINISTIC MODIFIES SQL DATA SQL SECURITY DEFINER
BEGIN
SELECT eqno into #eno,Date1 into #d,cmpname into #c,subject into #s,cid into #cd
FROM `enquiry` NATURAL JOIN `customer`
WHERE eqno=eq and email=mail and cmpname=cmp and Date=dates;
INSERT INTO `enquiryBin`(`Eqno`, `Date1`, `Cmpname`, `Subject`, `CID`, `Reason`)
VALUES (#eno,#d,#c,#s,#cd,rea);
DELETE FROM `enquiry`
WHERE eqno=eq and cid=#cd and cmpname=cmp and Date1=dates;
END
The create table statements of the two tables are given below
CREATE TABLE `customer` (
`CID` int(15) NOT NULL,
`Address` varchar(100) NOT NULL,
`Name` varchar(20) NOT NULL,
`email` varchar(30) NOT NULL,
`phone` bigint(20) NOT NULL
)
ALTER TABLE `customer`
ADD PRIMARY KEY (`CID`);
CREATE TABLE `enquiry` (
`Eqno` varchar(15) NOT NULL,
`Date1` date NOT NULL,
`Cmpname` varchar(10) NOT NULL,
`Subject` varchar(100) NOT NULL,
`CID` int(15) NOT NULL
)
ALTER TABLE `enquiry`
ADD PRIMARY KEY (`Eqno`,`Cmpname`,`CID`,`Date1`)
SELECT eqno into #eno,Date1 into #d,cmpname into #c,subject into #s,cid into #cd
Should be
SELECT eqno, Date1, cmpname, subject, cid INTO #eno, #d, #c, #s, #cd
That is, name all columns in the select-list separately from the INTO clause.
Refer to syntax documentation: https://dev.mysql.com/doc/refman/5.7/en/select-into.html
There's no need for all those variables, just use an INSERT INTO ... SELECT query, and a JOIN in the DELETE query.
INSERT INTO enquiryBin (`Eqno`, `Date1`, `Cmpname`, `Subject`, `CID`, `Reason`)
SELECT eqno, Date1, cmpname, subject, cid, rea
FROM FROM `enquiry` NATURAL JOIN `customer`
WHERE eqno=eq and email=mail and cmpname=cmp and Date1 = dates;
DELETE e FROM enquiry AS e
NATURAL JOIN customer
WHERE eqno = eq AND email = mail AND cmpname = cmp AND Date1 = dates

oracle trigger on update and on insert

I have a table defined in MySQL as following. Now I want to create this table in oracle.
But how can I convert on update trigger in to oracle?
create table test(
userid INTEGER(10) NOT NULL AUTO_INCREMENT,
CONSTRAINT PRIMARY KEY (userid),
fullname VARCHAR(200) NOT NULL,
email VARCHAR(50) NOT NULL,
createdat DATETIME NOT NULL DEFAULT NOW(),
updatedat DATETIME ON UPDATE NOW()
);
For a example, so:
CREATE TABLE test
(
userid INTEGER PRIMARY KEY
, fullname VARCHAR2(200) NOT NULL
, email VARCHAR2(50) NOT NULL
, createdat DATE DEFAULT CURRENT_DATE NOT NULL
, updatedat DATE
);
CREATE SEQUENCE test_seq START WITH 1 INCREMENT BY 1;
CREATE OR REPLACE TRIGGER test_insert
BEFORE INSERT
ON test
FOR EACH ROW
BEGIN
SELECT test_seq.NEXTVAL
INTO :new.userid
FROM DUAL;
END;
CREATE OR REPLACE TRIGGER test_update
BEFORE UPDATE
ON test
FOR EACH ROW
BEGIN
SELECT CURRENT_DATE
INTO :new.updatedat
FROM DUAL;
END;
Triggers may BEFORE UPDATE, AFTER UPDATE, and INSTEAD. Choose that you want. For more information read docs http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7004.htm
Since Oracle 12c, you can avoid using SEQUENCE in using IDENTITY as done in standard SQL.
The solution to your problem is following
CREATE TABLE test
( userid INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY
, fullname VARCHAR2(200) NOT NULL
, email VARCHAR2(50) NOT NULL
, createdat DATE DEFAULT CURRENT_DATE NOT NULL
, updatedat DATE
);
CREATE OR REPLACE TRIGGER test_update
BEFORE UPDATE
ON test
FOR EACH ROW
BEGIN
SELECT CURRENT_DATE
INTO :new.updatedat
FROM DUAL;
END;

Use a trigger like assertion

I know that in MySQL we can't use assertion. I Have these tables:
CREATE TABLE `soggiorno` (
`idSoggiorno` varchar(16) NOT NULL,
`price` int(11) NOT NULL,
PRIMARY KEY (`idSoggiorno`))
CREATE TABLE `prenotazione` (
`idPrenotazione` varchar(16) NOT NULL,
`soggiorno` varchar(16) NOT NULL,
`paymentType` varchar(45) NOT NULL,
PRIMARY KEY (`idPrenotazione`))
CONSTRAINT `guest_ibfk_1` FOREIGN KEY (`soggiorno`) REFERENCES `soggiorno` (`idSoggiorno`)
I have to ensure that, if 'price' > 1500, you can't pay with "cash". How can I do that without assertion? I'm thinking for a trigger...Thanks to all
Try
CREATE TRIGGER tg_prenotazione_before_insert
BEFORE INSERT ON prenotazione
FOR EACH ROW
SET NEW.soggiorno = IF((SELECT price
FROM soggiorno
WHERE idSoggiorno = NEW.soggiorno) > 1500
AND NEW.paymentType = 'Cash', NULL, NEW.soggiorno);
What is does it checks for your desired conditions (if price > 1500 and paymentType is 'Cash') and if it's a match it violates NOT NULL constraint effectively preventing a row from being inserted.
Here is SQLFiddle demo. Try to uncomment the last insert statement in the demo and you'll see that it won't let you insert it.