How to use alias in mysql triggers? - mysql

I'm am trying to create this mysql trigger:
DELIMITER //
CREATE TRIGGER checkcollision2 AFTER UPDATE ON projectiles p1
FOR EACH ROW
BEGIN
IF (SELECT count(*) FROM players p WHERE p.wolf=1 AND NEW.x>=p.x AND NEW.x<=p.x+25 AND NEW.y>=p.y AND NEW.y<=p.y+25) > 0 THEN
DELETE FROM projectiles p2 WHERE p1.id=p2.id;
END IF;
END;//
DELIMITER ;
But this isn't working, as its getting a syntax error. I'm not sure if its because I'm using an alias names for the tables. I am doing that because, if the if statement is true, then I want to delete the current updated row that the trigger started on. I think I could do that by doing a delete from the same table, where the id is the same, but if I don't use alias, then all rows from this table would be deleted.
Does anyone see whats wrong here?

Alias names on identifies at trigger signature level is not supported and hence is incorrect.
Instead you can define alias within the trigger body if required.
And as you want to perform a delete operation based on a condition, you can make use of NEW to compare with a specific row-column value. Current where clause WHERE p1.id=p2.id will delete ALL rows from the table, which is unsafe.
Change your trigger definition as below:
DELIMITER //
DROP TRIGGER IF EXISTS checkcollision2 //
CREATE TRIGGER checkcollision2 AFTER UPDATE ON projectiles
FOR EACH ROW
BEGIN
DELCARE match_count INT DEFAULT 0;
SELECT count(*) INTO match_count
FROM players p
WHERE p.wolf = 1
AND NEW.x BETWEEN p.x AND ( p.x + 25 )
AND NEW.y BETWEEN p.y AND ( p.y + 25 )
IF match_count > 0 THEN
DELETE FROM projectiles WHERE id = NEW.id;
END IF;
END;
//
DELIMITER ;

Related

How to trigger the procedure for the sql database in system files

I have a table that holds a bunch of values for an order, I can do basic calculations on it until I get to a percentage. Right now I have my query as follows
declare #MyNumber decimal
set #MyNumber = (select SalesTax from [OrderHeader] where OrderHeaderID = 20)
select
sum(o.MaterialPrice) as "MatPrice",
sum(o.LaborPrice) as "LaborPrice",
sum(o.MaterialCost) as "MaterialCost",
sum(isnull(o.MaterialPrice,0)) - sum(isnull(o.MaterialCost,0)) - sum(isnull(o.LaborPrice,0)) * #MyNumber as "RESULT"
from [OrderDetail] o
inner join [OrderHeader] oh on oh.OrderHeaderID = o.OrderHeaderID
where o.OrderHeaderID = 20
PLEASE CHANGE AT LEAST NAZOV
DELIMITER $$
CREATE TRIGGER `nazov` BEFORE UPDATE
ON test
FOR EACH ROW BEGIN
SET NEW.OLD_TEXT=OLD.TEXT;
END $$
DELIMITER;

Mysql said: #1422 - Explicit or implicit commit is not allowed in stored function or trigger

In the code below I'm trying to create a trigger which inserts 'incidentimg' table id along with an image path if the user of the web application did not upload a image with the form belonging to 'incidentreport' table, however, I'm only getting the error "MySQL said: #1422 - Explicit or implicit commit is not allowed in stored function or trigger"
DROP TRIGGER IF EXISTS `insertImage`;
CREATE TRIGGER `insertImage` AFTER INSERT ON `incidentreport`
FOR EACH ROW
BEGIN
IF(SELECT incidentimg.incidentImgId FROM incidentimg
LEFT JOIN incidentreport ON incidentimg.imgs_incidentReportId = incidentreport.incidentReportId
WHERE incidentimg.incidentImgId IS NULL)
THEN INSERT INTO incidentimg(incidentImgId, imgUrl)values(NEW.incidentReportId, 'images/no-image.png');
END IF;
END
;
Here are the tables being used
Can someone assist me on how to correct this problem
I finally got the code to work. Now the code will check whether 'incidentimg' table has all the 'incidentReportId' that the 'incidentreport' table has, and if it doesn't then the last inserted id from the 'incidentreport' table along with a default image path will be inserted into 'incidentimg' table AFTER INSERT.
CREATE TRIGGER insertImage AFTER INSERT ON incidentreport
FOR EACH ROW
BEGIN
IF(SELECT incidentreport.incidentReportId
FROM incidentreport
LEFT JOIN incidentimg ON incidentreport.incidentReportId = incidentimg.imgs_incidentReportId
WHERE incidentimg.imgs_incidentReportId IS NULL)
THEN INSERT INTO incidentimg(imgs_incidentReportId, imgUrl) VALUES(NEW.incidentReportId, 'images/no-image.png');
END IF;
END
I am not much sure but I am guessing that probably it's because of the IF .. THEN conditional INSERT. Try modifying your INSERT statement with an EXISTS like
DROP TRIGGER IF EXISTS `insertImage`;
CREATE TRIGGER `insertImage` AFTER INSERT ON `incidentreport`
FOR EACH ROW
BEGIN
INSERT INTO incidentimg(incidentImgId, imgUrl)
SELECT NEW.incidentReportId, 'images/no-image.png'
FROM DUAL WHERE EXISTS (
SELECT 1 FROM incidentimg
LEFT JOIN incidentreport
ON incidentimg.imgs_incidentReportId = incidentreport.incidentReportId
WHERE incidentimg.incidentImgId IS NULL
)
END;

How to store select results in mysql?

In mysql, I have a trigger which checks for collisions, and updates the hp value of rows that have a collision. I also set a boolean value of the projectile to be true to mean that it should be deleted later. But I seem to do something twice that I would rather done once.
DELIMITER //
CREATE TRIGGER checkcollision2 BEFORE UPDATE ON projectiles
FOR EACH ROW
BEGIN
SET #unit_size:=25;
IF (SELECT count(*) FROM players WHERE wolf=1 AND NEW.x>=x AND NEW.x<=x+#unit_size AND NEW.y>=y AND NEW.y<=y+#unit_size)>0 THEN
SET NEW.deleted=1;
UPDATE players SET hp=hp-NEW.dmg WHERE wolf=1 AND NEW.x>=x AND NEW.x<=x+#unit_size AND NEW.y>=y AND NEW.y<=y+#unit_size;
END IF;
END;//
DELIMITER ;
In the above, I do a select which gives me the number of rows that have a collision. Then below I do the same query because I want to update those same rows. I could have just done the update, but I only want to do the SET NEW.deleted=1; if there was at least 1 row affected. Im not sure how to do that if I only keep the update statement.
Does anyone know of a batter way of doing this?
Thanks
If you want to set the NEW.deleted value based on the number of rows affected on update then you can use ROW_COUNT() to check the number of rows affected.
Example:
DELIMITER //
CREATE TRIGGER checkcollision2 BEFORE UPDATE ON projectiles
FOR EACH ROW
BEGIN
SET custom_unit_size := 25;
UPDATE players
SET hp = hp - NEW.dmg
WHERE wolf = 1
AND NEW.x >= x
AND NEW.x <= x + custom_unit_size
AND NEW.y >= y
AND NEW.y <= y + custom_unit_size;
IF ROW_COUNT() > 0 THEN
SET NEW.deleted = 1;
END IF;
END;
//
DELIMITER ;
Refer to:
ROW_COUNT()
returns the number of rows changed, deleted, or inserted by the last statement if it was an UPDATE, DELETE, or INSERT. For other statements, the value may not be meaningful.

Assigning the value from a select statement to a vairable in MySQL

I'm fairly new to SQL in general and even more so to MySQL and I've hit a stumbling block. I'm attempting to use a procedure to copy the value of one field to another if the original field is not null, this procedure is then called by triggers whenever the table is updated or has a new row inserted into it. Here is what I have so far:
-- WORK_NOTES_PROCEDURE - This copies the contents of the estimate notes to the work order notes if the original estimate had any notes with it.
DROP PROCEDURE IF EXISTS 'WORK_NOTES_PROCEDURE';
DELIMITER $$
CREATE PROCEDURE WORK_NOTES_PROCEDURE()
BEGIN
DECLARE var_temp VARCHAR(50);
SET var_temp := (SELECT ESTIMATE_NOTES FROM ESTIMATES WHERE ESTIMATES.ESTIMATE_NUMBER = WORK_ORDERS.ESTIMATE_NUMBER);
IF var_temp IS NOT NULL THEN
UPDATE WORK_ORDERS SET WORK_ORDER_NOTES = var_temp WHERE WORK_ORDERS.ESTIMATE NUMBER = ESTIMATES.ESTIMATE_NUMBER;
END IF;
END$$
DELIMITER ;
Absolutely any help would be appreciated, the error I'm getting is a syntax error for the line where I'm assigning a value to var_temp.
try,
SET var_temp = (SELECT ESTIMATE_NOTES
FROM ESTIMATES INNER JOIN WORK_ORDERS
ON ESTIMATES.ESTIMATE_NUMBER = WORK_ORDERS.ESTIMATE_NUMBER
LIMIT 1);

writing a query for updating a table using another table's attributes by using a clause

I WANT TO DO SOMETHING LIKE THIS:
CREATE TRIGGER addwinner AFTER INSERT ON bids
FOR EACH ROW BEGIN
IF exists(select * from wins as LT where LT.item_index=NEW.item_index) THEN
SELECT item_index, MIN( bid_amount )
FROM update_winnerslist AS a1
WHERE a1.item_index = NEW.item_index;
UPDATE wins SET email_id=NEW.emai_id, bid_amount=a1.bid_amount where wins.item_index=a1.item_index;
END IF;
END;
Basically what i want is to update a table using another table's tuple by comparing certain attributes.
As explained in the manual, when defining procedures/triggers/etc. that use ; within their body to separate commands, you need to define an alternate delimiter in order that the CREATE command is interpreted as a single statement.
To UPDATE with the results of the SELECT, like you describe, you can do any of:
Save the result of the SELECT in a variable which you then use in the UPDATE:
DELIMITER ;; -- or anything else you like
CREATE TRIGGER addwinner AFTER INSERT ON bids FOR EACH ROW
IF EXISTS (SELECT * FROM wins AS LT WHERE LT.item_index=NEW.item_index)
THEN
SELECT MIN(bid_amount) INTO #bid_amount
FROM update_winnerslist AS a1
WHERE a1.item_index = NEW.item_index;
UPDATE wins
SET email_id=NEW.emai_id, bid_amount=#bid_amount
WHERE wins.item_index=a1.item_index;
END IF;; -- whatever command delimiter you chose above goes here
DELIMITER ; -- reset to normal
Just use a subquery (so long as it doesn't reference the table you're updating):
DELIMITER ;; -- or anything else you like
CREATE TRIGGER addwinner AFTER INSERT ON bids FOR EACH ROW
IF EXISTS (SELECT * FROM wins AS LT WHERE LT.item_index=NEW.item_index)
THEN
UPDATE wins
SET wins.email_id=NEW.emai_id, wins.bid_amount=(
SELECT MIN(bid_amount)
FROM update_winnerslist AS a1
WHERE a1.item_index = NEW.item_index
)
WHERE item_index = NEW.item_index
END IF;; -- whatever command delimiter you chose above goes here
DELIMITER ; -- reset to normal
Or just join the tables:
DELIMITER ;; -- or anything else you like
CREATE TRIGGER addwinner AFTER INSERT ON bids FOR EACH ROW
IF EXISTS (SELECT * FROM wins AS LT WHERE LT.item_index=NEW.item_index)
THEN
UPDATE wins JOIN update_winnerslist AS a1 USING (item_index)
SET wins.email_id=NEW.emai_id, wins.bid_amount=MIN(a1.bid_amount);
WHERE item_index = NEW.item_index
END IF;; -- whatever command delimiter you chose above goes here
DELIMITER ; -- reset to normal