Problem with inserting values after creating a TRIGGER - mysql

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.

Related

Insert a record and also update existing records

hi there i was trying to right a Proc for a DataLoad when you want to insert records on a Table1 based on Table2
This is what i came of with
it has 2 condition
1) if the record does not exist create a new row of record
2) if the record already exist update the record based on keys
this is my proc need some help thanks
DECLARE #TableKey INT --(it is passed by the user proc param),
DECLARE #TableCount INT,
DECLARE #CLassKey INT,
SELECT #TableCount= COUNT(*) FROM Table1 WHERE Tablekey= #TableKey
INSERT INTO #CLassKey
SELECT Distinct c.PK_ClassKey FROM CLASS as c
INNER JOIN BOOK as B ON B.FK_ClassKey=C.PK_ClassKEy
IF ((SELECT COUNT(*) FROM #ClassKey) > 0 AND #TableCount= 0)--- this will check
BEGIN
Insert into NOTE
n.note
Select
c.note
FROM Class where c.FK_Note = n.PK_Note.
END
---- this will just insert for the first time..
How do i update it any idea as the records are only inserted for the first time put does not update using the same format thanks a lot
try this one
INSERT INTO table_name (id,col2,col3)
VALUES (value_id,value2,value3)
ON DUPLICATE KEY UPDATE
col2=value2,
col3=value3;

Create a trigger to update a table based on another table

Please I need your help. I have been working on a trigger statement and it seem not to be working.
I need help on writing a trigger to update a table called membership when a column on another table called serialcode is updated.
DETAILS: I have two tables called membership and serialcode. The membership table has the following columns
id fullname email date state sn
and the serialcode table has only
id sn
I want the sn in membership to be updated with the value of sn in serialcode is updated where the id in membership table is same as the id in serialcode table.
Here is what I have been able to write below
CREATE TRIGGER MembershipSerialCode
BEFORE UPDATE ON serialcode
FOR EACH ROW
BEGIN
if :new.sn != :old.sn
then
UPDATE membership m
set membership.sn = :new.sn
where m.id = :new.id;
end if;
END;
Thank you.
Mike
Can you try this one and let me know if you have luck on implementing it?
CREATE Trigger TriggerName
ON SerialNumberTable FOR UPDATE
AS
IF (Update(sn)) -- This is the column on SerialCodeTable that will be updated first
BEGIN
IF EXISTS (Select i.id
FROM Deleted d INNER JOIN Inserted i
ON d.id = i.id
AND d.sn <> i.sn)
BEGIN
UPDATE MembershipTable SET MembershipTable.sn = i.sn
FROM Inserted i
WHERE MembershipTable.id = i.id
END
END

Trigger can't work properly when check condition

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

Add a row if there are less than 5, otherwise replace the lowest number in MySQL

I'm pretty stuck on a Mysql query.
I have a table with three columns;
user_id | person_id | score.
The table is going to be used to store top 5 highscores for each person.
I need at query that checks if there is less than five rows for a specific person.
Is there is less, insert new row. But if there is five rows I have to replace the lowest score with the new one.
It is for a webservice written in PHP and the data about the new score is posted to the method as params.
Been stuck for some hours now — is it even possible to make this happen in one query ?
You can use stored procedure in mysql. I dont know the names of the tables but if you look closer you will understand how it works.
DELIMITER $$
DROP PROCEDURE IF EXISTS test $$
CREATE PROCEDURE test( IN testparam VARCHAR(22) )
BEGIN
DECLARE count INT(11);
SET count = (SELECT COUNT(*) FROM persons );
IF count < 5 THEN
insert into table_needed_for_insert values(testparam);
ELSE
update table_needed_for_insert where score=(select min(score) from table_needed_for_insert);
END IF;
select * from table_needed_for_insert
END $$
DELIMITER;
And how to execute this thing CALL test(1); 1 is the parameter, you can create as many as you need.
And from php you can call directly as like
$result = mysql_query("call test(".$param.")");
And here you can check a tutorial on mysql stored procedures:
http://www.mysqltutorial.org/mysql-stored-procedure-tutorial.aspx
It might be possible if you have a unique key which identifies the lowest score. Then you could use the
INSERT ... ON DUPLICATE KEY construct. But you would have to install a trigger which keeps explicit track of the lowest score.
I would propose this scenario (I have not tried it, it is just an idea):
as I understand, you only need 5 ids. you can run a subqueries like these
SELECT MAX(id) AS last_id FROM table
SELECT MIN(score), id AS lowest_id FROM table
then
insert or replace into table (id, ...) values ( MIN(last_id+1, lowest_id), ... )
there are possible mistakes and also only one subquery is possible, but I hope you get the main idea
The simplest way imo is to insert data,
INSERT INTO top_scores (user_id, person_id, score_id) VALUES (1,2,3)
then delete inappropriate rows
DELETE top_scores FROM top_scores
INNER JOIN
(SELECT * FROM top_scores WHERE person_id = 2 ORDER BY score ASC LIMIT 5, 1000000) AS inappropriate_rows
USING (user_id, person_id, score)

trigger updating all rows, not just inserted

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