I know I'm missing something obvious here. This trigger is updating all rows in the table (killing performance) when all I want it to do is perform the update on the new inserted row.
CREATE TRIGGER [dbo].[update_location_topo_name]
--fires at each row insert, queries topo map layer (must be present!) and inserts name of topo into new location record
on [dbo].[TBL_LOCATIONS]
after insert
AS
BEGIN
update TBL_LOCATIONS
set TOPO_NAME = dbo.QD24K_GRSM.NAME
FROM dbo.tbl_locations
inner join dbo.QD24K_GRSM
on TBL_LOCATIONS.Location_ID = TBL_LOCATIONS.Location_ID
WHERE (QD24K_GRSM.Shape.STContains(TBL_LOCATIONS.SHAPE) = 1)
END
You need to reference the INSERTED pseudo table to get only the rows that were inserted.
Additionally your join condition of TBL_LOCATIONS.Location_ID = TBL_LOCATIONS.Location_ID makes no sense at all.
Probably better to do this as an INSTEAD OF trigger to modify the rows before insert rather than after they are inserted.
CREATE TRIGGER [dbo].[update_location_topo_name]
ON [dbo].[TBL_LOCATIONS]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO TBL_LOCATIONS
(foo,
bar,
TOPO_NAME)
SELECT foo,
bar,
dbo.QD24K_GRSM.NAME
FROM INSERTED I
LEFT JOIN dbo.QD24K_GRSM
ON QD24K_GRSM.Shape.STContains(I.SHAPE) = 1/* Will insert additional
rows if more than one match*/
END
I would suggest to create trigger "Instead of Insert" rather than "After Insert".
That way you can modify newly inserted rows as you need before actually inserting them in target table.
And there is absolutely no need to join "inserted" table with target table.
Something like this (syntax might be wrong as not actually run that code):
CREATE TRIGGER [dbo].[update_location_topo_name]
on [dbo].[TBL_LOCATIONS]
Instead Of insert
AS
BEGIN
Insert Into TBL_LOCATIONS (...., TOPO_NAME)
Select ..., CrTable.NAME as TOPO_NAME
From Inserted Cross Apply
(
Select top 1 QD24K_GRSM.NAME from QD24K_GRSM where
QD24K_GRSM.Shape.STContains(Inserted.SHAPE) = 1
) as CrTable
END
Related
I want to use a trigger to automatically update another table but I'm having some problems with it.
DELIMITER $$
DROP TRIGGER IF EXISTS `trigger1` $$
CREATE TRIGGER `trigger1`
AFTER UPDATE ON `table1` FOR EACH ROW
UPDATE `table4`
inner join (SELECT o.`Name`,
o.Date,
(o.`Availability` * (c.Rate)) total
FROM `table2` o
LEFT JOIN `table1` r
ON o.`Name` = r.`Name`
AND o.Date = r.Date
LEFT JOIN (SELECT table3.`Name`,Choke, Rate FROM table3
left join `table1` as w
on table3.`Name` = w.`Name`
and table3.Choke = w.`Size`
where w.`Name` = table3.`Name`
and table3.Date <= w.Date
ORDER BY table3.Date DESC
LIMIT 1) c
ON c.`Name` = o.`Name`)x
set `Contribution` = x.total
where (`table4`.Date) = x.Date and `table4`.`Name` = x.`Name`;
END $$
DELIMITER ;
I would like to use the date from table1 row (that is the table which triggers the trigger) in my left join named c. As it stands c.Rate gives the same value every time because it uses the default table1.
If the row being updated has a date of '2022-01-13' then I want the date used at the line asterisked
and table3.Date <= w.Date
I want w.Date to be '2022-01-13'. But as it stands I can't get that and all the c.Rate give the same value.
Thanks.
The lack of consistent indentation and capitalisation makes your query almost impossible to read. Instead of obfuscating what is going on by using table1, table2, table3 & table4 you would be better off using the real table names, as it will make more sense to anyone trying to read it.
Your current update query makes little sense with the repeated left joins back to the originating table1 but it is hard to be sure given the lack of supporting information in your question. Your first left join to table1, aliased as r, does not get used anywhere. Your second left join to table1, aliased as w, is then referenced in the where clause which turns it into an inner join.
I suggest you update your question with the CREATE TABLE statements and some sample data to show the values before and after executing your update and the trigger update. Your current update query is definitely not the most efficient way of achieving your goal.
I don't really understand your question but it seems that you all are asking is how to use the value from the table1 row being updated? In which case the answer is simply -
and w.Date = NEW.Date
where NEW references the post-update version of the table1 row.
From 25.3.1 Trigger Syntax and Examples -
Within the trigger body, the OLD and NEW keywords enable you to access
columns in the rows affected by a trigger. OLD and NEW are MySQL
extensions to triggers; they are not case-sensitive.
In an INSERT trigger, only NEW.col_name can be used; there is no old
row. In a DELETE trigger, only OLD.col_name can be used; there is no
new row. In an UPDATE trigger, you can use OLD.col_name to refer to
the columns of a row before it is updated and NEW.col_name to refer to
the columns of the row after it is updated.
I am new in mysql and I am facing a problem I can't overcome, so I need your help.
I have created a trigger that looks like this:
delimiter //
CREATE trigger NEWBOOKTRIGGER138
after insert ON NEW_SALES
FOR each row
BEGIN
IF (SELECT COUNT(*) FROM NEW_SALES NS
INNER JOIN NEW_BOOKS NB ON NS.ISBN=NB.ISBN GROUP BY GENRE)>138 then
update GENRE set genre=GENRE|| "BEST.SELLER";
ELSEif (SELECT COUNT(*) FROM NEW_SALES NS
INNER JOIN NEW_BOOKS NB ON NS.ISBN=NB.ISBN GROUP BY GENRE)<=138 then
update GENRE set genre= GENRE;
end if;
END;//
In order to change the genre title(in table new_books) into genre BEST.SELLER if a book appears more than 138 times in the new_sales table, let's say.
I get a message that the trigger was successfully created.
The problem is that when I try to insert a tuple in new_books table (in order to see if the trigger actually works) I get an Error code 1242: Subquery returns more than 1 row.
I try to insert the tuple this way:
INSERT INTO NEW_SALES(ISBN,cid)
VALUES ("6666666666666",555);
When I drop the trigger the above insert command works just fine,
But how can I test the functionality of the trigger if I can't insert a new tuple?
Thank u in advance guys.
Kostas
You seem to be updating the wrong table, I assume you want to update the genre column in the NEW_BOOKS table. And it only seems necessary to update it for the book that you're currently inserting, which is NEW.isbn, so you don't need a JOIN.
Also, MySQL doesn't use || for concatenation, it uses the function CONCAT().
CREATE trigger NEWBOOKTRIGGER138
after insert ON NEW_SALES
FOR each row
IF (SELECT COUNT(*) FROM NEW_SALES WHERE isbn = NEW.isbn) > 138
THEN
UPDATE NEW_BOOKS AS b
SET genre = CONCAT(genre, "BEST.SELLER")
WHERE b.isbn = NEW.isbn;
You don't need an ELSEIF statement, since you don't need to do anything to keep the genre the same.
I am new to MySQL and learning it to my own. Actually I want to copy a column from a table into my existing table column! suppose that my existing table is:
where pid values are inserted by default!
now i want to copy a column from another table using:
INSERT INTO exist_tab(FirstLevel) SELECT some_col FROM another_table;
so that the values should come inside FirstLevel Column.
but the problem is that the copies values come below the pid values in FirstLevel Column as:
see that the firstlevel comes below! what is wrong with it? I need the "H" value against 19 but i dont want to use wild cards just want to copy the new data against old column data
thanks
I am new to this kind a work please can somebody give me any idea how to do it please!
thanks in advance
INSERT and UPDATE is different Command to Perform Different Task.
INSERT :Insert New Record into the table
Update:Update Existing Record in table If Exist.
NOT SURE ABOUT IT:(i'm Not Familiar With MYSQL)
Update a set
a.FirstLevel=b.some_col
from
exist_tab a join another_table b on a.Id=b.Id
Or You can Try :
update exist_tab a set a.FirstLevel=
(select top 1 some_col from another_table where Id=a.Id)
EDIT2:
update exist_tab a set a.FirstLevel=
(select top 1 some_col from another_table)
You Can Find Here.
You are using INSERT statement here. INSERT will create a new record in the table. You have to use UPDATE for updating a particular column in the existing table like this:
UPDATE exist_tab
SET FirstLevel = (SELECT some_col FROM another_table)
If you want any conditional update then you can use JOIN like this:
UPDATE exist_tab a
LEFT JOIN another_table b ON
a.pid = b.id
SET FirstLevel = a.some_col;
I just want to store records in two way.
If it exists, it will update information
If it dosn't exist, it will insert as new record
Here are the outline schemas for my tables:
product_purchase_item has product_purchase_item_id, product_id, quantity columns
product_stock has product_stock_id, product_id, product_total_quantity columns
I was creating a trigger
DELIMITER //
CREATE TRIGGER store_check AFTER INSERT ON product_purchase_item
FOR EACH ROW
BEGIN
DECLARE X INTEGER;
SET X =(SELECT product_id FROM product_stock where product_id = NEW.product_id);
IF NEW.product_id !=X THEN
INSERT INTO product_stock VALUES(NULL,NEW.product_id,NEW.quantity);
ELSE
UPDATE product_stock
SET product_total_quantity=product_total_quantity+NEW.quantity
WHERE product_id=NEW.product_id;
END IF;
END;//
DELIMITER;//
The problem is in product_stock table, INSERT query doesn't work when product record not exist, but update query work does properly when product record does exist.
Is it really the INSERT statement that "doesn't work"? Or, is the problem that the INSERT statement is not being executed at all?
What happens when the preceding SELECT query does not return a row? What value gets assigned to X?
When X has that value, does a conditional test "foo != X" return TRUE, or does it return something else (like FALSE, or NULL)?
Have you tried something like this?
IF NEW.product_ID = X THEN
UPDATE ...
ELSE
INSERT ...
END IF;
(I know it's bad practice to answer a question with a question; but it seemed apropros, since answering those will get you the answer to the question you really wanted to ask.)
You can do the desired operation through one of MySQL's standard commands:
INSERT INTO product_stock (product_id,product_total_quantity)
VALUES (NEW.product_id,NEW.quantity)
ON DUPLICATE KEY UPDATE product_total_quantity=product_total_quantity+NEW.quantity;
see the MySQL manual
What I'm looking to do is insert a record, then deactivate previous records with the same ID because they will no longer be in use. However, I'm looking to do this in the simplest way possible. Deleting the record really isn't an option.
Attempted order of operations:
Insert with active inUse value inUse = 1
Update the following records for the same ID that are no longer in use: inUse = 0
My first thought was to run this query:
UPDATE page_tags
SET inUse = IF(inUse = 1, 0, 1)
WHERE page_id = 23678459
AND tag_id NOT IN (10, 4);
The only problem with this query is that if it's run again, it will toggle all of those deactivated values back to 1. I need all of the tags for the specific ID to only toggle back if they are being targeted by the WHERE statement.
Sounds like a job for trigger. Something like will perhaps do (pseudocode)?
UPDATE for handling reuse of previuos tags:
Do your insert/update:
INSERT INTO ... ON DUPLICATE KEY UPDATE
Then use two triggers, one for inserts and one for updates.
CREATE TRIGGER tr_inuse_insert BEFORE INSERT ON page_tags
FOR EACH ROW BEGIN
UPDATE page_tags SET inuse=0 WHERE page_id = NEW.page_id;
END;
CREATE TRIGGER tr_inuse_update BEFORE UPDATE ON page_tags
FOR EACH ROW BEGIN
UPDATE page_tags SET inuse=0 WHERE page_id = NEW.page_id;
END;
#John P has a decent answer, however his answer requires the use of triggers. That to me seems to be more than needed to solve the problem at hand. The current working solution is:
Create an Unique Index on page_tags.page_id and page_tags.tag_id.
Update all rows where the *page_id = 234234*:
UPDATE page_tags SET inUse = 0 WHERE page_id = 234234
Insert tags:
INSERT INTO page_tags (page_id, tag_id, inUse) VALUES (234234, 49343, 1) ON DUPLICATE KEY UPDATE inUse = 1