I would like to limit the size of a table to X rows (I'll use 5 for example). When the limit is reached, I want to copy the oldest row to another table, then delete it. I currently have:
CREATE TRIGGER LimitRows BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
IF (SELECT COUNT(*) FROM MyTable) >= 5 THEN
INSERT INTO HistoryTable
SELECT *
FROM MyTable A
WHERE vhID = A.min(vhID);
DELETE FROM MyTable
WHERE vhID = min(vhID);
END IF;
END;
Currently, I get the error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 8
How do I write this trigger correctly? Also, how can I modify to cut the table down to 5 rows if it starts out at something like 100 rows?
You need to change the delimiter first
delimiter |
CREATE TRIGGER LimitRows BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
IF (SELECT COUNT(*) FROM MyTable) >= 5 THEN
INSERT INTO HistoryTable
SELECT *
FROM MyTable A
WHERE vhID = A.min(vhID);
DELETE FROM MyTable
WHERE vhID = min(vhID);
END IF;
END
|
delimiter ;
Otherwise the trigger definition would end at the first ; which would make it incomplete.
Related
I'm trying to make this code work but to no avail..
DELIMITER $$
CREATE
TRIGGER `update_tbl1` AFTER UPDATE
ON `tbl1`
FOR EACH ROW BEGIN
IF (SELECT count(*) FROM tbl1 WHERE stn=NEW.stn) = 1
THEN
UPDATE tbl2 SET date_posted=NEW.date_posted WHERE stn=NEW.stn;
ELSE
INSERT INTO tbl2 (stn) VALUES (NEW.stn);
END IF
END$$
DELIMITER ;
I have two tables, and I want a trigger that will update tbl2 if the tbl1 is updated, only if the data already exists on the tbl2, otherwise, insert it. My code seems feasible and the error seems to be syntax-related but I can't find where.
EDIT:
Here is the error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INTO tbl2 (stn) VALUES (NEW.stn); END IF END' at line 10
About syntax error, I think it's just what you forgot semicolon ; after END IF, try following:
DELIMITER $$
CREATE
TRIGGER `update_tbl1` AFTER UPDATE
ON `tbl1`
FOR EACH ROW BEGIN
IF (SELECT count(*) FROM tbl1 WHERE stn=NEW.stn) = 1
THEN
UPDATE tbl2 SET date_posted=NEW.date_posted WHERE stn=NEW.stn;
ELSE
INSERT INTO tbl2 (stn) VALUES (NEW.stn);
END IF;
END$$
DELIMITER ;
I'm not sure what the syntax error is, but the logic you want is:
INSERT INTO tbl2 (stn)
VALUES (NEW.stn)
ON DUPLICATE KEY UPDATE SET date_posted = NEW.date_posted;
For this to work, you need a unique index on tbl2(stn):
CREATE UNIQUE INDEX unq_tbl2_stn ON tbl2(stn);
Note: This doesn't fix your particular syntax error. This addresses a logical error in the code.
I want to create trigger to make update on table when inserting rows to other table, but I get a syntax error for this:
CREATE TRIGGER quantity AFTER INSERT ON sale_items
FOR EACH ROW
BEGIN
update products set quantity = quantity -1 where id =(
SELECT product_id
FROM sale_items
ORDER BY id desc
LIMIT 1)
END;
Error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'END' at line 7
This seems like a silly trigger. Why are you fetching the last update id using a subquery? It should be available through new:
DELIMITER //
CREATE TRIGGER quantity AFTER INSERT ON sale_items
FOR EACH ROW
BEGIN
update products
set quantity = quantity - 1
where id = new.product_id
END//
DELIMITER ;
Use proper Delimiter in your trigger , the correct code is:
DELIMITER //
CREATE TRIGGER quantity AFTER INSERT ON sale_items
FOR EACH ROW
BEGIN
update products set quantity = quantity - 1
where id = new.product_id ;
END//
DELIMITER ;
I've tried every possible combination I can think of to resolve this error but it keeps happening. Any help appreciated. This is just modifying the sakila sample database to do more complex things with.
See towards bottom I labeled the error with -- HERE!.
USE sakila;
DROP PROCEDURE IF EXISTS sp_randCustMult;
DELIMITER //
CREATE PROCEDURE sp_randCustMult()
BEGIN
/* section of code left out for troubleshooting
IF EXISTS (SELECT * FROM information_schema.columns WHERE table_name = customer AND column_name = multiplier)
THEN ALTER TABLE customer DROP COLUMN multiplier;
IF EXISTS (SELECT * FROM information_schema.columns WHERE table_name = customer AND column_name = cust_ranking)
THEN ALTER TABLE customer DROP COLUMN cust_ranking;
END IF;
*/
-- add new columns
ALTER TABLE customer
ADD COLUMN multiplier DECIMAL(3,2) AFTER active;
/* this column not relevant now
ALTER TABLE customer
ADD COLUMN cust_ranking VARCHAR(10) AFTER multiplier;
*/
-- declare a counter
SET #start = (SELECT MIN(customer_id) FROM customer);
SET #stop = (SELECT MAX(customer_id) FROM customer);
-- start while loop
WHILE #start <= #stop
DO
UPDATE customer
-- insert multiplier based on random distribution
SET multiplier =
(SELECT
(CASE
WHEN RAND() <= 0.65 THEN 1.00
WHEN RAND() <= 0.90 THEN 0.85
WHEN RAND() <= 1.00 THEN 1.05
END)
)
WHERE customer_id = #start;
-- tick counter one up
SET #start = #start + 1;
END WHILE;
-- HERE! syntax error on END before //
END//
DROP PROCEDURE sp_randCustMult//
DELIMITER ;
EDIT1: To clarify, MySql version is:
MySQL Workbench Community (GPL) for Mac OS X version 6.1.4 revision 11773 build 1454
And the error response from Workbench:
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END' at line 35
EDIT2: Edited code as suggested. Error no longer happens, however data is not being updated at all. (all NULL in new column)
Your CREATE PROCEDURE doesn't match the required syntax as described in the MySQL manual (simplified below by including just the relevant parts):
CREATE
PROCEDURE sp_name ([proc_parameter[,...]])
routine_body
routine_body:
Valid SQL routine statement
The routine_body consists of a valid SQL routine statement. This can be a simple statement such as SELECT or INSERT, or a compound statement written using BEGIN and END. Compound statements can contain declarations, loops, and other control structure statements. The syntax for these statements is described in Section 13.6, “MySQL Compound-Statement Syntax”.
Therefore, this junk…
IF EXISTS (SELECT * FROM information_schema.columns WHERE table_name = customer AND column_name = multiplier)
THEN ALTER TABLE customer DROP COLUMN multiplier;
IF EXISTS (SELECT * FROM information_schema.columns WHERE table_name = customer AND column_name = cust_ranking)
THEN ALTER TABLE customer DROP COLUMN cust_ranking;
END IF;
… is illegal. Perhaps you meant to move it into the BEGIN … END compound statement?
You also need a semicolon after END WHILE.
All functional logic must be between the tags BEGIN and END
So the IF conditions and alter query stuff must lie between BEGIN and END tags of procedure..
Thanks
I figured out the issues, here is the solution on CR:
https://codereview.stackexchange.com/questions/51603/mysql-modifying-sakila-database
I want a table maximum rows to 100, If i add 101 row to that table, the 1 row should delete automatically. likewise i just want table total row count to 100, delete order should be FIFO.
Is there any direct MySQL function for that?
Use BEFORE INSERT trigger for this.
Below, I kept limit of 25, set according to your need.
DELIMITER $$
CREATE TRIGGER trigger1
BEFORE INSERT
ON table1
FOR EACH ROW
BEGIN
SELECT COUNT(*) INTO #cnt FROM table1;
IF #cnt >= 25 THEN
CALL sth(); -- raise an error
END IF;
END
$$
DELIMITER ;
You can a simple trigger like below:
CREATE TRIGGER Deleter AFTER INSERT on YourTable FOR EACH ROW
BEGIN
Delete from yourTable where ID = (Select MIN(id) from yourTable);
END;
Same as :
How do you make a threshold or limit mysql table?
I get an error (1064) when attempting to run the following... (MySql 5.5.9)
query:
CREATE TRIGGER clearChat AFTER INSERT ON chat
FOR EACH ROW
BEGIN
DELETE p.* FROM chat p LEFT JOIN (SELECT t.id FROM chat t ORDER BY t.id DESC LIMIT 50) x ON x.id = p.id WHERE x.id IS NULL
END;
the error is:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END' at line 5
Any assistance would be great.
Last Edit: Updated to show the 'FOR EACH ROW' and 'BEGIN'
You're missing FOR EACH ROW before DELETE: http://dev.mysql.com/doc/refman/5.1/en/create-trigger.html
Edit: There are more issues. The correct syntax is below:
delimiter |
CREATE TRIGGER clearChat AFTER INSERT ON chat
FOR EACH ROW BEGIN
DELETE p.* FROM chat p LEFT JOIN (SELECT t.id FROM chat t ORDER BY t.id DESC LIMIT 50) x ON x.id = p.id WHERE x.id IS NULL;
END;
|
delimiter ;
Edit 2:
I don't think that query is allowed to be in a trigger at all based on this http://dev.mysql.com/doc/refman/5.1/en/faqs-triggers.html#qandaitem-B-5-1-9:
A trigger can access both old and new
data in its own table. A trigger can
also affect other tables, but it is
not permitted to modify a table that
is already being used (for reading or
writing) by the statement that invoked
the function or trigger.
Since you aren't using OLD or NEW, I don't think you can modify chat since the trigger is triggered on inserts to chat.
I had the same problem with the following statement, it ALWAYS gave me a syntax error on even this simplified delete statement (originally was DELETE FROM APP_CACHE_VIEW WHERE APP_UID = OLD.APP_UID;):
CREATE TRIGGER APPLICATION_DELETE BEFORE DELETE ON APPLICATION
FOR EACH ROW
BEGIN
DELETE FROM APP_CACHE_VIEW;
END
If I changed the SQL command to the following then it WORKED but I don't understand why:
DELIMITER $$
CREATE TRIGGER APPLICATION_DELETE BEFORE DELETE ON APPLICATION
FOR EACH ROW
BEGIN
DELETE FROM APP_CACHE_VIEW;
END$$
DELIMITER ;