I have a table called tblReservations with follwing columns:
reserv_ID (int), aptID (int), client_ID (int),
start_date (datetime), end_date (datetime),
details (nvarchar(max)), confirmation (bit)
What trigger should is to compare two dates start_date for new reservation and end_date for existing reservation in tblReservation for specific aptID.
If start_date < end_date trigger must prevent insertion of new reservation for that aptID.
I wrote this trigger:
CREATE TRIGGER NewReservation
on tblReservations
after insert
as
begin
declare #aptID int
declare #start_date datetime
declare #end_date datetime
select #aptID=aptID, #start_date=start_date from inserted
select #end_date=end_date from tblReservations
where aptID=#aptID
if #end_date>#start_date
BEGIN
ROLLBACK TRANSACTION
END
end
Why does this trigger not work?
please help
Aside from the multiorw issue that others have brought up, you are likely not considering that there are many rows in the tblReservations for a particular apt id.
Plus you do not want to insert the record and then get rid of it, you want the record to not go in. therefore an instead of trigger is a better bet.
CREATE TRIGGER NewReservation
ON tblReservations
INSTEAD OF INSERT
AS
BEGIN
INSERT tblReservations (<put field list here>)
SELECT <put field list here>
FROM inserted i
JOIN (SELECT aptid, MAX(reservationid)AS reservationid FROM tblReservations GROUP BY aptid) maxid
ON i.aptid = r.aptid
JOIN tblReservations r
ON r.reservationid = maxid.reservationid
WHERE r.enddate<i.startdate
END
The first problem I see is you are assuming inserted is a single row.
Try:
Select top 1 #aptID=bb.aptID, #start_date=start_date
from inserted as aa
join
(
select Max(start_date) as Start_Date from inserted
) as bb
on aa.Start_Date =bb.Start_Date
But you should think about changing your logic so that the record never gets inserted in the first place if the date is wrong.
Related
I have a table A which has column NoOfDays, and another table B which has a column MyDate of type datetime and it is set to Default as "CURRENT_TIMESTAMP".
Now in table B, I want to add a new column (called ValidDate), which should AUTOMATICALLY store the sum value of (B.MyDate + A.NoOfDays)
For example, if B.MyDate has value of "2022-07-25 04:50:26" and A.NoOfDays has value of "60", then B.ValidDate should get the value of "2022-09-23 04:50:26"
What is the way in MySQL to set this new column value to store this summed value automatically.
Checked for existing threads, but found only this one which does not offer a solution to store, but to create a view output only.
MySQL - Add number of days to date in 3rd column automatically
For existing rows in table_b , use an update statement like UPDATE table_b set ValidDate=date_add(MyDate , interval + (select NoOfDays from table_a) day);
For new inserts, we can use a trigger to handle that. Here is the complete script written and tested in workbench:
create table table_a (NoOfDays int);
create table table_b(MyDate timestamp,ValidDate datetime);
insert table_a values(60);
DELIMITER //
drop trigger if exists auto_sum //
create trigger auto_sum before insert on table_b for each row begin
set new.ValidDate=date_add(new.MyDate , interval + (select NoOfDays from table_a) day);
end //
delimiter ;
insert into table_b (MyDate) values (default); -- The value of ValidDate is calculated in the trigger,so we only need to specify the value for MyDate.
Please try this:
CREATE TABLE TableA (NoOfDays INT);
INSERT INTO TableA VALUES(60);
CREATE TABLE TableB(MyDate DATETIME DEFAULT CURRENT_TIMESTAMP);
INSERT INTO TableB VALUES('2022-07-25 04:50:26');
ALTER TABLE TableB
ADD ValidDate DATETIME;
UPDATE TableB
SET ValidDate = date_add(MyDate, INTERVAL (SELECT NoOfDays FROM TableA) DAY);
If we test the result :
SELECT * FROM TableB;
Hi guys, I'm facing an issue trying to auto update a table with triggers.
I'm developing a real estate management app and I'd like to generate, for the property manager side, a table (bill) with all charges and payments received per year and per landlord for a same shared building.
The main tables that I use for this part are:
building
charge (which contains building_id)
charge_payment(which contains building_id and landlord_id as user_id)
To generate this table (bill), for exemple, I made a trigger on table charge which will generate a table on each new charge insert that I insert into bill table. I check in table charge and table charge_payment for that.
Here is how it looks like:
CREATE DEFINER=`root`#`localhost` TRIGGER `charge_AFTER_INSERT` AFTER INSERT ON `charge` FOR EACH ROW BEGIN
INSERT INTO bill(building_id, user_id, year, amount, payment)
SELECT
p.building_id,
ll.user_id user_id,
bcharge_annual.year year,
ROUND(sum(p.building_slice) * (bcharge_annual.amount), 2) amount,
IFNULL(total_payments.payments, 0) payment
FROM landlord ll
LEFT JOIN property p ON ll.property_id=p.id
LEFT JOIN (
SELECT
c.building_id building_id,
c.year,
SUM(c.amount) amount
FROM charge c
WHERE c.building_id=new.building_id and c.property_id IS NULL
GROUP BY c.year
) bcharge_annual ON p.building_id=bcharge_annual.building_id
LEFT JOIN (
SELECT
cp.user_id user_id,
cp.corresponding_year year,
IFNULL(sum(cp.amount), 0) payments
FROM charge_payment cp
WHERE cp.corresponding_year=new.year
GROUP BY user_id,corresponding_year
) total_payments ON ll.user_id=total_payments.user_id
WHERE p.building_id=new.building_id AND (ll.ownership_end IS NULL OR ll.ownership_end > (SELECT NOW())) AND bcharge_annual.year=new.year
GROUP BY ll.user_id,year;
END
My problem is that if I add an other charge on the same building and same year, I had an error. Until now, I solved the problem by deleting all raws in table bill with same year before each new charge insert, but it's quite dirty :)
CREATE DEFINER=`root`#`localhost` TRIGGER `charge_AFTER_INSERT` AFTER INSERT ON `charge` FOR EACH ROW BEGIN
DECLARE matchbillyear INT;
SELECT COUNT(*)
INTO matchbillyear
FROM bill b
WHERE b.building_id=new.building_id AND b.year=new.year;
IF matchbillyear > 0 THEN
DELETE FROM bill bil
WHERE bil.year=new.year;
...
So I've been thinking, and I tried to remove this deletion trigger on table charge and add a trigger on table bill to check before insert on each row if it should be an insert or just an amount update:
CREATE DEFINER=`root`#`localhost` TRIGGER `bill_BEFORE_INSERT` BEFORE INSERT ON `bill` FOR EACH ROW BEGIN
DECLARE matchBillId INT;
SELECT b.id
INTO matchBillId
FROM bill b
WHERE b.building_id=new.building_id AND b.year=new.year AND b.user_id=new.user_id;
IF EXISTS (
SELECT b.id
FROM bill b
WHERE b.building_id=new.building_id AND b.year=new.year AND b.user_id=new.user_id) THEN
UPDATE bill
SET NEW.amount = amount + NEW.amount
WHERE id = matchBillId;
END IF;
END
Was looking good to me, but definitely not for MySql which throws me this error:
ERROR 1442: 1442: Can't update table 'bill' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
SQL Statement:
INSERT INTO `erem_pro`.`charge` (`building_id`, `year`, `type`, `amount`) VALUES ('1', '2021', 'Entretien', '1300.00')
If anyone has any clue on how to make it work, would be great. Otherwise I think I'll have to rethink my app... :/
Thanks a lot in advance and congratulation if you read all that :)
I have these two table called "cases" and attendance respectively which has four columns:
cases-
id empid reaction date_t
1 EMP12654 interested 2017-09-22
attendance-
id empid logintime logouttime date_t flag workinghours call_att
1 EMP12654 00:14:49 05:14:49 2017-09-18 set 6 1
What I want to do is create a trigger on cases table that updates call_att column of attendance table with number of entries in reaction column of cases table, this is what I have tried so far
CREATE DEFINER=`root`#`localhost` TRIGGER `number_call`
AFTER INSERT ON `cases` FOR EACH ROW
BEGIN UPDATE attendance set call_att=call_att +1
WHERE empid=new.empid AND date_t=new.date_t; END
But that doesn't seem to work. I am quite new to triggers.
try this
CREATE TRIGGER number_call
AFTER INSERT ON cases
FOR EACH ROW
BEGIN
UPDATE attendance set call_att=(select count(*) from cases where empid=NEW.empid )
date_t=NEW.date_t;
END
Inventory Table:
Inventory History Table:
The query:
INSERT INTO inventory_history (SKU, Quantity, timestamp)
SELECT SKU, Quantity, modifiedtime FROM inventory WHERE modifiedtime BETWEEN '2016-12-25 00:00:00' AND '2016-12-26 00:00:00';
The Trigger:
CREATE TRIGGER `sold_diff` BEFORE INSERT ON `inventory_history`
FOR EACH ROW begin
declare prev_quantity int(11) default 0;
declare prev_sku varchar(255) default null;
select sku
into prev_sku
from inventory_history
where prev_sku = NEW.sku
order by id desc
limit 1;
select quantity
into prev_quantity
from inventory_history
order by id desc
limit 1;
set NEW.sold = prev_quantity
;
end
The Result:
Now, how it's set-up is it's taking prev_quantity from the previous row, and putting it into the sold column.
I can not figure out a way to bind SKU in with prev_quantity, so that it will give me the previous Quantity value from the corresponding SKU.
Desired Result:
I've messed with a variety of different WHERE clauses on the two declared, but nothing is working right.. so I'm thinking this is not the right path to take.
How can this be achieved?
I think you are taking the wrong approach.
You seem to want an insert on the inventory table. When a new value is inserted or updated (or deleted), you then insert a row in the inventory_history table with the old and new values.
You then don't need an explicit insert on inventory_history.
I'm trying to create a trigger on the employeepayhistory table. Whenever I update the RATE column in the table its effect on the monthly salary should be displayed, but instead it gives me the monthly salary of the whole record if I update one record. Please help.
CREATE TRIGGER MONTHTRG
ON HumanResources.EmployeePayHistory
FOR UPDATE
AS
BEGIN
DECLARE #Rate MONEY
SELECT #Rate=Rate FROM INSERTED
SELECT 'MONTHSAL'=Rate*PayFrequency*30 FROM HumanResources.EmployeePayHistory
END
You also need to give the where condition, typically you'll
DECLARE #Id bigint
SET #Id = (SELECT Id from Inserted)
SELECT 'MONTHSAL' = Rate * PayFrequency*30 From HumanResources.EmployeePayHistory where Humanresources.EmployeeID=#Id
This will work if the Primary key is called 'Id' and ofcourse, is unique. You can also do this with a Unique key(which should be Non-NULL)