Trigger for a board game not working as intended - mysql

I'm a complete newbie and I am having issues creating a trigger that needs to be executed when the Players table is updated. It first has to check if on_location exists as a location_id in the table Real_estate and to also check if anyone else owns the location_id already (owned_by = NULL if no one owns it).
Once those two conditions are satisfied I need to update the owned_by column in the Real_estate table so that instead of NULL it will have the player_id.
Additionally, I need to update the player_balance in the Players table by subtracting the estate_cost from original player_balance.
This is what I have now:
DROP TRIGGER IF EXISTS R1;
DELIMITER ;;
CREATE TRIGGER R1 AFTER UPDATE ON Players FOR EACH ROW
BEGIN
IF NEW.on_location = (SELECT location_id FROM Real_estate WHERE location_id = NEW.on_location)
AND
(SELECT owned_by FROM Real_estate WHERE location_id = NEW.on_location) = NULL
THEN
UPDATE Real_estate
SET
owned_by = (SELECT player_id FROM Players WHERE on_location = NEW.on_location)
WHERE location_id = NEW.on_location;
UPDATE Players
SET
player_balance = (player_balance - (SELECT estate_cost FROM Real_estate WHERE location_id = NEW.on_location))
WHERE player_id = (SELECT player_id FROM Players WHERE on_location = NEW.on_location);
END IF;
END;;
DELIMITER ;
Thanks in advance for any help

Related

MySQL update after insert trigger

I am new to triggers but have coded this one
DELIMITER $$
CREATE TRIGGER stockupdate
AFTER INSERT ON inventory.orderdetails
FOR EACH ROW
BEGIN
UPDATE inventory.stockitem s
INNER JOIN inventory.OrderDetails d ON s.ID = d.Item
INNER JOIN inventory.orders o ON ebayOrderNumber = d.OrderNumber
SET s.`Sold Date` = o.`Order Date`, s.EbayOrderNumber = o.ebayOrderNumber, s.`Sale Price` = d.Price
WHERE s.ID = d.Item;
END$$
DELIMITER ;
Currently it does not update table stockitem as expected. Is there anything glaringly obvious that I have done wrong please?
Many thanks for looking.
That's because your join returns all or most records from oderDetails and oders table and you are not supressing sql_safe_updates safety feature.
You are definitely missing table alias in o ON ??.ebayOrderNumber = d.OrderNumber. Besides, WHERE s.ID = d.Item; is redundant as your table joins already do that. Your Where condition should be more explicit and tell which stock item to update.
DELIMITER $$
CREATE TRIGGER stockupdate AFTER INSERT ON inventory.orderdetails FOR EACH ROW
BEGIN
UPDATE
(inventory.stockitem s
INNER JOIN inventory.OrderDetails d ON s.ID = d.Item)
INNER JOIN inventory.orders o ON o.ebayOrderNumber = d.OrderNumber
SET
s.`Sold Date` = o.`Order Date`, -- update the stock
s.EbayOrderNumber = o.ebayOrderNumber,
s.`Sale Price` = d.Price
WHERE
d.orederNumber = NEW.OrderNumber, -- From this order
d.Item = NEW.item; -- and this item id
END$$
DELIMITER ;
Having said that, I do not understand why would you want to update the stock table with a sold price? orderDetails already contains those for you and what if you have many quantity for a single stock? i.e 100 Dell laptops. Surely you don't have 100 records for each Dell laptop in your stock item? and updating each record with sold price? Anyway i leave that up to you..

Trigger doesn't let me update

I have the following Trigger:
delimiter |
CREATE TRIGGER DES1actualizarConsultaR_update
AFTER UPDATE ON ranking
FOR EACH ROW
BEGIN
UPDATE player P,
(SELECT
J.player_id AS jugador_id,
SUM(ranking_points) AS PuntosTotales
FROM
player J
INNER JOIN ranking R ON R.player_id = NEW.player_id
GROUP BY J.player_id) AS TD
SET
P.totalPuntos = TD.PuntosTotales
WHERE
P.player_id = TD.jugador_id;
UPDATE player P,
(SELECT
J.player_id AS JnumUno, COUNT(*) AS NumVeces1
FROM
player J
INNER JOIN ranking R ON R.player_id = NEW.player_id
WHERE
R.ranking = '1'
GROUP BY J.player_id) AS TD
SET
P.vecesNum1 = TD.NumVeces1
WHERE
P.player_id = TD.JnumUno;
END |
I'am trying to execute this update:
UPDATE ranking
SET
ranking_points = (ranking_points + 10)
WHERE
player_id IN (SELECT
P.player_id
FROM
player P,
tourney T,
tmatch M
WHERE
T.tourney_name LIKE 'Madrid%'
AND T.tourney_date BETWEEN '2017-01-01' AND '2018-12-31'
AND (M.round = 'F' OR M.round = 'SF')
AND P.player_id = M.winner_id
AND M.tourney_id = T.tourney_id);
But I have this error:
Error Code: 1442. Can't update table 'player' in stored
function/trigger because it is already used by statement which invoked
this stored function/trigger.
How can I do the update query?
I´m using MYSQL.
It happens because you are have a jointure on the ranking table in the TRIGGER's UPDATE statement.
Even if you aren't updating the ranking table itself, MySQL doesn't like it.
You have to get around it by doing a stand-alone SELECT query first to compute the player's points, save those points in a variable, and then use it in your UPDATE of the player table, without referencing the ranking table
Here's the idea:
delimiter |
CREATE TRIGGER DES1actualizarConsultaR_update
AFTER UPDATE ON ranking
FOR EACH ROW
BEGIN
DECLARE vPuntosTotales INT;
DECLARE vNumVeces1 INT;
SELECT SUM(ranking_points) AS PuntosTotales INTO vPuntosTotales
FROM ranking
WHERE player_id = NEW.player_id;
UPDATE player SET totalPuntos = vPuntosTotales WHERE player_id = NEW.player_id;
-- NOT SURE IF THIS ONE IS CORRECT
SELECT COUNT(*) AS NumVeces1 INTO vNumVeces1
FROM ranking R
WHERE R.ranking = '1' AND R.player_id = NEW.player_id;
UPDATE player SET vecesNum1 = vNumVeces1 WHERE player_id = NEW.player_id;
END |
you should review my queries because I don't know exactly your table structure and I might be wrong in my SELECTs, especially in the second one

How to combine while loop in mysql to single update

I have a temporary table named _temp that contains orders that will be sent back to a webpage. When this table is created it populates all the information except the number of photos in each order (currently it will set the number of photos to -1 so that I know it hasn't been updated). I want to update the number of photos in each order to the correct number. I have no idea how to do this without using a while statement and going through each order individually. Here is the code I'm currently using which works fine but is very slow
SET _current_id = (SELECT old_id FROM _temp WHERE photos = -1 LIMIT 1);
WHILE (_current_id IS NOT NULL) DO
UPDATE _temp SET photos = (SELECT COUNT(f.id) FROM files f WHERE f.file_type = "orders" AND f.table_id = _current_id AND deleted = 0) WHERE old_id = _current_id;
SET _current_id = (SELECT old_id FROM _temp WHERE photos = -1 LIMIT 1);
END WHILE;
update _temp t set t.photos = (SELECT COUNT(f.id) FROM files f WHERE f.file_type = "orders" AND f.table_id = t.old_id AND deleted = 0) WHERE old_id = t.old_id;

fetch data employee table with 1 id and multiple transaction id

here in transaction table one employee have multiple transaction .i want all transaction of 1 specific employee .but employee id should be print once in column .here is format
1.here one employee have more than one transaction id .id should display 1 time and display all transaction
desired result: employee details should display in one row but transaction id in multiple row
error id repeating id:
Copied from comments:
select
b.TransactionId,
a.Name
from
TransactionRecharge b
left JOIN Customer a on a.Id=b.CustomerId
where
b.CustomerId=101282
This is not a Good practice, I am pretty sure that "I am going to get negative marks for helping you", Anyway i just did for what you asked.
Below Query using ROW_NUMBER will help you get what you need exactly.
CREATE TABLE #customer(Id INT PRIMARY KEY,Name VARCHAR(255))
CREATE TABLE #TransactionRecharge(TransactionId VARCHAR(255),CustomerId INT FOREIGN KEY REFERENCES #customer(id))
INSERT INTO #customer
VALUES (1,'Raj'),(2,'Bala'),(3,'Chandra')
INSERT INTO #TransactionRecharge
VALUES ('reansaction1',1),('reansaction2',1),
('reansaction3',1),('reansaction4',1),
('reansaction5',1),('reansaction6',1),
('reansaction7',1),('reansaction8',2)
SELECT
CASE
WHEN ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY b.TransactionId,a.Id) = '1' THEN CONVERT(VARCHAR,a.Id)
ELSE ''
END AS Customer,
CASE
WHEN ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY b.TransactionId,a.Id) = '1' THEN Name
ELSE ''
END AS Name,
b.TransactionId
FROM
#TransactionRecharge b
LEFT JOIN
#customer a ON a.Id = b.CustomerId
WHERE 1 = 1
--AND b.CustomerId = 1
DROP TABLE #customer
DROP TABLE #TransactionRecharge

looking for most efficient way to to query multiple email addresses in Mysql

I'm looking for a way to select the email address of joe so that every time i run a select query I get only one email address returning in sequence of the id. sort of round Robin the results ..
so on first select I get joe#blogs.com
and then second I get joe#gmail.com
and third joe#outlook.com
and next joe#blogs.com as there are only three entries
If you know what I mean.
addresses
---------------------
id|name|email
---------------------
1 |joe |joe#blogs.com
2 |joe |joe#gmail.com
3 |joe |joe#outlook.com
Give this a shot:
CREATE TABLE #results (id INT, name VARCHAR(50), email VARCHAR(100))
DECLARE #currentID INT;
WHILE(1 = 1)
BEGIN
SET #currentID =
(SELECT TOP 1 t.id
FROM [YOURTABLE] t
LEFT JOIN #results r
ON r.id = t.id
WHERE t.name = 'joe'
AND r.id IS NULL)
IF #currentID IS NULL
BREAK;
SELECT * FROM [YOURTABLE] WHERE id = #currentID
INSERT INTO #results
SELECT TOP 1 t.id, t.name, t.email
FROM [YOURTABLE] t
WHERE t.id = #currentID
END
I think the best way would be to store the next email id in a field that has a foreign key to the user. This will give you the most interoperability between whatever will be using the database.
Be mindful because you will run into issues if emails are deleted.