Trigger doesn't let me update - mysql

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

Related

Trigger for a board game not working as intended

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

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..

UPDATE FROM WHERE Subquery SQL Server

How can I use a subquery from an UPDATE statement? Here is my query:
UPDATE car_availability
SET availability_status = 'GOOD'
FROM car_trip AS TRIP
WHERE car_availability.car_no = TRIP.car_no
AND NOT EXISTS (SELECT DISTINCT A.car_No
FROM car_maintenance A
WHERE A.car_no = TRIP.vehicle_id
AND start_date = TRIP.workday)
AND EXISTS (SELECT DISTINCT B.car_No
FROM car_maintenance B
WHERE B.car_no = TRIP.vehicle_id
AND end_date IS NOT NULL)
I get an error 'FROM clause in UPDATE and DELETE statements cannot contain subquery sources or joins.'
I want to update availability_status to GOOD in which car exists in car_maintenance with its start_date is equal to workday of car_trip and cars which is in car_maintenance with its end date is not null.
As #McNets said, you need to add the car_availability table to your FROM clause. Try this:
UPDATE CA
SET availability_status = 'GOOD'
FROM car_availability CA
JOIN car_trip AS TRIP ON CA.car_no = TRIP.car_no
WHERE NOT EXISTS (SELECT DISTINCT A.car_No
FROM car_maintenance A
WHERE A.car_no = TRIP.vehicle_id
AND start_date = TRIP.workday)
AND EXISTS (SELECT DISTINCT B.car_No
FROM car_maintenance B
WHERE B.car_no = TRIP.vehicle_id
AND end_date IS NOT NULL)

MySQL select in update statement

This MySQL statement give me all id_duel_player for player with id_player=30 and it work fine.
SELECT b.id_duel_player
FROM duels a
INNER JOIN duel_player b
ON a.id_duel = b.id_duel
WHERE id_player = 30
UNION ALL
SELECT c.id_duel_player
FROM duel_player c
INNER JOIN
(
SELECT aa.*
FROM duels aa
INNER JOIN duel_player bb
ON aa.id_duel = bb.id_duel
WHERE bb.id_player = 30
) d ON c.id_duel = d.id_duel AND c.id_player <> 30
I want to make MySQL statement for UPDATE (fields from duel_player table) all of this id_duel_player that returns this select statement.
UPDATE duel_player
SET num = 2,
total = 5
WHERE (duel_player.id_duel_player = id_duel_player's from above SELECT statement)
I want most effective and fastest way to do this.
Thanks
For 200-400 rows it's likely fastest to create a temporary table with the results, and then do the UPDATE with a join:
CREATE TEMPORARY TABLE id_duel_players AS
SELECT b.id_duel_player as id FROM duels a ...
UPDATE duel_player
JOIN id_duel_players ON duel_player.id_duel_player = id_duel_players.id
SET num = 2,
total = 5
For smaller result sets you may find the IN operator sufficiently fast (... WHERE id_duel_player IN (SELECT ...)), but I've found it unreliable for result sets with hundreds of rows. (Unreliable = suddenly no matches are found, no idea why, I haven't investigated.)

MySQL - UPDATE query based on SELECT Query

I need to check (from the same table) if there is an association between two events based on date-time.
One set of data will contain the ending date-time of certain events and the other set of data will contain the starting date-time for other events.
If the first event completes before the second event then I would like to link them up.
What I have so far is:
SELECT name as name_A, date-time as end_DTS, id as id_A
FROM tableA WHERE criteria = 1
SELECT name as name_B, date-time as start_DTS, id as id_B
FROM tableA WHERE criteria = 2
Then I join them:
SELECT name_A, name_B, id_A, id_B,
if(start_DTS > end_DTS,'VALID','') as validation_check
FROM tableA
LEFT JOIN tableB ON name_A = name_B
Can I then, based on my validation_check field, run a UPDATE query with the SELECT nested?
You can actually do this one of two ways:
MySQL update join syntax:
UPDATE tableA a
INNER JOIN tableB b ON a.name_a = b.name_b
SET validation_check = if(start_dts > end_dts, 'VALID', '')
-- where clause can go here
ANSI SQL syntax:
UPDATE tableA SET validation_check =
(SELECT if(start_DTS > end_DTS, 'VALID', '') AS validation_check
FROM tableA
INNER JOIN tableB ON name_A = name_B
WHERE id_A = tableA.id_A)
Pick whichever one seems most natural to you.
UPDATE
`table1` AS `dest`,
(
SELECT
*
FROM
`table2`
WHERE
`id` = x
) AS `src`
SET
`dest`.`col1` = `src`.`col1`
WHERE
`dest`.`id` = x
;
Hope this works for you.
Easy in MySQL:
UPDATE users AS U1, users AS U2
SET U1.name_one = U2.name_colX
WHERE U2.user_id = U1.user_id
If somebody is seeking to update data from one database to another no matter which table they are targeting, there must be some criteria to do it.
This one is better and clean for all levels:
UPDATE dbname1.content targetTable
LEFT JOIN dbname2.someothertable sourceTable ON
targetTable.compare_field= sourceTable.compare_field
SET
targetTable.col1 = sourceTable.cola,
targetTable.col2 = sourceTable.colb,
targetTable.col3 = sourceTable.colc,
targetTable.col4 = sourceTable.cold
Traaa! It works great!
With the above understanding, you can modify the set fields and "on" criteria to do your work. You can also perform the checks, then pull the data into the temp table(s) and then run the update using the above syntax replacing your table and column names.
Hope it works, if not let me know. I will write an exact query for you.
UPDATE
receipt_invoices dest,
(
SELECT
`receipt_id`,
CAST((net * 100) / 112 AS DECIMAL (11, 2)) witoutvat
FROM
receipt
WHERE CAST((net * 100) / 112 AS DECIMAL (11, 2)) != total
AND vat_percentage = 12
) src
SET
dest.price = src.witoutvat,
dest.amount = src.witoutvat
WHERE col_tobefixed = 1
AND dest.`receipt_id` = src.receipt_id ;
Hope this will help you in a case where you have to match and update between two tables.
I found this question in looking for my own solution to a very complex join. This is an alternative solution, to a more complex version of the problem, which I thought might be useful.
I needed to populate the product_id field in the activities table, where activities are numbered in a unit, and units are numbered in a level (identified using a string ??N), such that one can identify activities using an SKU ie L1U1A1. Those SKUs are then stored in a different table.
I identified the following to get a list of activity_id vs product_id:-
SELECT a.activity_id, w.product_id
FROM activities a
JOIN units USING(unit_id)
JOIN product_types USING(product_type_id)
JOIN web_products w
ON sku=CONCAT('L',SUBSTR(product_type_code,3), 'U',unit_index, 'A',activity_index)
I found that that was too complex to incorporate into a SELECT within mysql, so I created a temporary table, and joined that with the update statement:-
CREATE TEMPORARY TABLE activity_product_ids AS (<the above select statement>);
UPDATE activities a
JOIN activity_product_ids b
ON a.activity_id=b.activity_id
SET a.product_id=b.product_id;
I hope someone finds this useful
UPDATE [table_name] AS T1,
(SELECT [column_name]
FROM [table_name]
WHERE [column_name] = [value]) AS T2
SET T1.[column_name]=T2.[column_name] + 1
WHERE T1.[column_name] = [value];
You can update values from another table using inner join like this
UPDATE [table1_name] AS t1 INNER JOIN [table2_name] AS t2 ON t1.column1_name] = t2.[column1_name] SET t1.[column2_name] = t2.column2_name];
Follow here to know how to use this query http://www.voidtricks.com/mysql-inner-join-update/
or you can use select as subquery to do this
UPDATE [table_name] SET [column_name] = (SELECT [column_name] FROM [table_name] WHERE [column_name] = [value]) WHERE [column_name] = [value];
query explained in details here http://www.voidtricks.com/mysql-update-from-select/
You can use:
UPDATE Station AS st1, StationOld AS st2
SET st1.already_used = 1
WHERE st1.code = st2.code
For same table,
UPDATE PHA_BILL_SEGMENT AS PHA,
(SELECT BILL_ID, COUNT(REGISTRATION_NUMBER) AS REG
FROM PHA_BILL_SEGMENT
GROUP BY REGISTRATION_NUMBER, BILL_DATE, BILL_AMOUNT
HAVING REG > 1) T
SET PHA.BILL_DATE = PHA.BILL_DATE + 2
WHERE PHA.BILL_ID = T.BILL_ID;
I had an issue with duplicate entries in one table itself. Below is the approaches were working for me. It has also been advocated by #sibaz.
Finally I solved it using the below queries:
The select query is saved in a temp table
IF OBJECT_ID(N'tempdb..#New_format_donor_temp', N'U') IS NOT NULL
DROP TABLE #New_format_donor_temp;
select *
into #New_format_donor_temp
from DONOR_EMPLOYMENTS
where DONOR_ID IN (
1, 2
)
-- Test New_format_donor_temp
-- SELECT *
-- FROM #New_format_donor_temp;
The temp table is joined in the update query.
UPDATE de
SET STATUS_CD=de_new.STATUS_CD, STATUS_REASON_CD=de_new.STATUS_REASON_CD, TYPE_CD=de_new.TYPE_CD
FROM DONOR_EMPLOYMENTS AS de
INNER JOIN #New_format_donor_temp AS de_new ON de_new.EMP_NO = de.EMP_NO
WHERE
de.DONOR_ID IN (
3, 4
)
I not very experienced with SQL please advise any better approach you know.
Above queries are for MySql server.
if you are updating from a complex query. The best thing is create temporary table from the query, then use the temporary table to update as one query.
DROP TABLE IF EXISTS cash_sales_sums;
CREATE TEMPORARY TABLE cash_sales_sums as
SELECT tbl_cash_sales_documents.batch_key, COUNT(DISTINCT tbl_cash_sales_documents.cash_sale_number) no_of_docs,
SUM(tbl_cash_sales_documents.paid_amount) paid_amount, SUM(A.amount - tbl_cash_sales_documents.bonus_amount - tbl_cash_sales_documents.discount_given) amount,
SUM(A.recs) no_of_entries FROM
tbl_cash_sales_documents
RIGHT JOIN(
SELECT
SUM(
tbl_cash_sales_transactions.amount
)amount,
tbl_cash_sales_transactions.cash_sale_document_id,
COUNT(transaction_id)recs
FROM
tbl_cash_sales_transactions
GROUP BY
tbl_cash_sales_transactions.cash_sale_document_id
)A ON A.cash_sale_document_id = tbl_cash_sales_documents.cash_sale_id
GROUP BY
tbl_cash_sales_documents.batch_key
ORDER BY batch_key;
UPDATE tbl_cash_sales_batches SET control_totals = (SELECT amount FROM cash_sales_sums WHERE cash_sales_sums.batch_key = tbl_cash_sales_batches.batch_key LIMIT 1),
expected_number_of_documents = (SELECT no_of_docs FROM cash_sales_sums WHERE cash_sales_sums.batch_key = tbl_cash_sales_batches.batch_key),
computer_number_of_documents = expected_number_of_documents, computer_total_amount = control_totals
WHERE batch_key IN (SELECT batch_key FROM cash_sales_sums);
INSERT INTO all_table
SELECT Orders.OrderID,
Orders.CustomerID,
Orders.Amount,
Orders.ProductID,
Orders.Date,
Customer.CustomerName,
Customer.Address
FROM Orders
JOIN Customer ON Orders.CustomerID=Customer.CustomerID
WHERE Orders.OrderID not in (SELECT OrderID FROM all_table)