So I've tried a whole lot of diffrent things with If statements, and i simply can't seem to work out how to do this.
I wan't to make the trigger delete the row with the lowest ID, if it recurring.
And by recurring i mean the number and username are the same in two rows.
For example
ROW1: ID: 1 , Nr: 1 , UN: MVJ and
Row2: ID: 2 , Nr: 1 , UN: MVJ
Those are recurring, but if the 'Nr' or 'UN' were different, they wouldn't be.
So here is my try so far.
CREATE TRIGGER no_double_reservations
AFTER INSERT ON tilmeldte
FOR EACH ROW
WHERE
'SELECT COUNT(*) from tilmeldte WHERE (kursus_nr, username) IN ( SELECT kursus_nr, username FROM tilmeldte GROUP BY kursus_nr, username HAVING count(*) = 2 )' = '2'
DELETE from tilmeldte Where tilmeldingsid =
'Select min(`tilmeldingsid`) from tilmeldte WHERE (kursus_nr, username) IN ( SELECT min(kursus_nr), username FROM tilmeldte GROUP BY kursus_nr, username HAVING count(*) = 2 )'
END;
Found the right syntax, but found out the move was impossible in SQL.
You can't delete a row from the same the table you select which row to delete.
The right syntax was:
DELIMITER !!
CREATE TRIGGER no_double_reservations
AFTER INSERT ON tilmeldte
FOR EACH ROW BEGIN
IF(
SELECT COUNT(*) from tilmeldte WHERE (kursus_nr, username) IN ( SELECT kursus_nr, username FROM tilmeldte GROUP BY kursus_nr, username HAVING count(*) = 2 ) = 2)
THEN
DELETE from tilmeldte Where tilmeldingsid = (Select min(`tilmeldingsid`) from tilmeldte WHERE (kursus_nr, username) IN ( SELECT min(kursus_nr), username FROM tilmeldte GROUP BY kursus_nr, username HAVING count(*) = 2 ));
END IF;
END!!
DELIMITER ;
Your trigger has some syntax errors, but those are somewhat unimportant, because what you are trying to do is not possible:
A stored function or trigger cannot modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
http://dev.mysql.com/doc/refman/5.6/en/stored-program-restrictions.html
Triggers in MySQL cannot modify other rows in the table that the trigger is defined against. That would open up the possibility for infinite trigger recursion, e.g. a trigger on row A modifies row B, which fires a trigger that modifies row A, which fires a trigger that modifies row B, which...
Related
This is my first trigger in MySql and I am having a few problems. I tried both of these pieces of code but both would not compile. I got it to work without the where clause.
CREATE TRIGGER ins_meal_details
AFTER INSERT ON meal_details
FOR EACH ROW
INSERT INTO sql_changes
SET
sc_table='book_room',
sc_reason='DINNER1',
sc_key='bh_no=NEW.bh_no,date=NEW.md_date',
sc_value='1',
sc_done =0
WHERE not exists (select 1 from booking where bh_no = NEW.bh_no and bo_date = NEW.md_date and bo_meals < 1)
CREATE TRIGGER ins_meal_details AFTER INSERT meal_details FOR EACH ROW
BEGIN
IF NOT EXISTS (select 1 from booking where bh_no = NEW.bh_no and bo_date = NEW.md_date and bo_meals < 1) THEN
INSERT INTO sql_changes (sc_table, sc_reason, sc_key, sc_value, sc_done )
VALUES ('book_room','DINNER1', 'bh_no=NEW.bh_no,date=NEW.md_date','1', 0);
END IF
END
CREATE TRIGGER ins_meal_details
AFTER INSERT
ON meal_details
FOR EACH ROW
INSERT INTO sql_changes (sc_table,
sc_reason,
sc_key,
sc_value,
sc_done)
SELECT 'book_room',
'DINNER1',
CONCAT('bh_no=',NEW.bh_no,',date=',NEW.md_date),
1,
0
WHERE NOT EXISTS (SELECT 1
FROM booking
WHERE bh_no = NEW.bh_no
AND bo_date = NEW.md_date
AND bo_meals < 1);
MySql did not like the select/where exists in my code when there is no table specified. This was due to using version 5.6 of MySql server.
This will not work: select 'works' where exists (select 1 from my-table)
The fix would be thanks to #akina to add from DUAL. The best solution.
I got round it by using a count(*) instead :-
DROP TRIGGER IF EXISTS ins_meal_details;
DELIMITER //
CREATE TRIGGER ins_meal_details
AFTER INSERT ON meal_details FOR EACH ROW
BEGIN
IF (select count(*) from booking where bh_no = NEW.bh_no and bo_date = NEW.md_date and bo_meals < 1) > 0 THEN
INSERT INTO sql_changes (sc_table,
sc_reason,
sc_key,
sc_value,
sc_done)
VALUES ('book_room','DINNER1', CONCAT('bh_no=',NEW.bh_no,',date=',NEW.md_date),'New Value', 0);
END IF;
END//
DELIMITER ;
I have a very simple procedure which performs an update on multiple rows. Is their a way I can loop through the insert id of each updated row?
BEGIN
UPDATE testTable set testValue = 2
where username = inputUser and flag = 1;
//for each update performed, insert LAST_INSERT_ID() into tableB
END
is this possible? If so, can you lead me in the right direction?
LAST_INSERT_ID only gives you one last id. You can do multiple inserts without a loop. You can use the output of SELECT query and insert to the desired table. You can do something like that:
BEGIN
UPDATE testTable set testValue = 2
where username = inputUser and flag = 1;
INSERT into tableB (column1, column2)
SELECT column1, column2 FROM testTable
WHERE username = inputUser and flag = 1;
END
For example:
User (username, password)
UserLoginLog (username, last_log_in_date)
INSERT INTO UserLogInLog (username, last_log_in_date)
SELECT username, NOW()
FROM User
WHERE username = "JohnDoe"
I have created 2 tables named snag_list and defect_list. I need to change the status field of snag_list to 2 when all the defect_list status should to be 2
Not sure if this helps but try to create a trigger for defect_list
and check the distinct count of status column if it is one and the value is 2 then update the snag_list a example would look like this
DELIMITER $$
CREATE TRIGGER checkstatus
AFTER UPDATE ON defect_list
FOR EACH ROW
BEGIN
DECLARE cnt INT
SELECT COUNT(DISTINCT status) FROM defect_list INTO cnt
DECLARE st INT
SELECT DISTINCT status FROM defect_list LIMIT 1 INTO st
IF(cnt = 1 AND st = 2)
UPDATE snag_list SET status = 2
ENF IF
END$$
DELIMITER ;
Your question is very vague but I guess this is what you may be looking for.
DECLARE
count_rec VARCHAR2(10);
data_rec VARCHAR2(10);
BEGIN
SELECT COUNT(DISTINCT status) INTO count_rec FROM defect_list;
SELECT DISTINCT status INTO data_rec FROM defect_list;
IF (count_rec = '1' AND data_rec = '2') THEN
UPDATE snag_list SET status = '2';
END IF;
END;
edit -> You can change the datatype of the 2 variables as required. Go with VARCHAR2 if you're unsure whether the data would be numeric.
I wan't to make the trigger delete the row with the lowest ID, if it is recurring. And by recurring i mean the number and username are the same in two rows.
For example
ROW1: ID: 1 , Nr: 1 , UN: MVJ and
Row2: ID: 2 , Nr: 1 , UN: MVJ
Those are recurring, but if the 'Nr' or 'UN' were different, they wouldn't be.
But as the title explains, MYSQL can't do that, atleast with the way I've made my SQL Statement.
I'm open to solve the problem in an whole other way.
Drop trigger no_double_reservations;
DELIMITER !!
CREATE TRIGGER no_double_reservations
AFTER INSERT ON tilmeldte
FOR EACH ROW BEGIN
IF(
SELECT COUNT(*)
FROM tilmeldte
WHERE (kursus_nr, username)
IN (
SELECT kursus_nr, username
FROM tilmeldte
GROUP BY kursus_nr, username
HAVING COUNT(*) = 2
) = 2
)
THEN
DELETE FROM tilmeldte
Where tilmeldingsid = (
Select MIN(`tilmeldingsid`)
FROM tilmeldte
WHERE (kursus_nr, username)
IN (
SELECT MIN(kursus_nr), username
FROM tilmeldte
GROUP BY kursus_nr, username
HAVING COUNT(*) = 2
)
);
END IF;
END!!
DELIMITER ;
I hope you can help.
Since you haven't given any table definition, here is a logic how to get this done in MySQL.
create stored procedure that takes your username and kursus_id
check whether the username already exists
if yes > delete and insert new id
if no > just insert new record and send message back
in code it would be something like.
CREATE PROCEDURE `SP_NEW_RESERVATION` (in iUsername varchar(50), in iKursus_id int)
BEGIN
DECLARE EXIT HANDLER for sqlexception
BEGIN
rollback;
SELECT 'False' as Result, 'Some error description or diagnose description from mysql' as `Description`;
END;
Start Transaction;
SET #mExists := (SELECT ID from tbl_yourTable where ((kursus_id = iKursus_id) and (username like iUsername)));
if (length(coalesce(#mExists,'')) <> 0) then
-- username does not exists so you can continue with insert a new reservation
insert into tbl_yourTable and continue here
-- send back message
SELECT 'True' as Result, 'New record inserted') as `Description`;
ELSE
-- username exists already and the id would be saved in mExists so delete the id and continue with your insert_method
Delete from Tbl_yourtable where id = #mExists something ligke that;
insert into tbl_yourtable .....
-- you can send back a message like
SELECT 'True' as Result, concat('Old record(', #mExists, ') Deleted and new record inserted') as `Description`;
end if;
Commit;
END
above code is incomplete. To execute this code you need to correct your insert and delete commands. Then just call the procedure like.
call SP_NEW_RESERVATION('KrishKm', 2);
if username 'KrishKm' already exists you will get message back like:
True, Old record(10) Deleted and new record inserted.
if not you get message back:
True, New record inserted.
if anything goes wrong you get message :
False, 'Some error description or diagnose description from mysql'
Good luck.
I have a MYSQL table and two of the fields are called Rate_per_unit and Cost. First I want the field Rate_per_unit to populate itself from another table called SHD_TEACHER then I want the field COST to populate itself also from RATE in SHD_TEACHER and multiplies by UNITS.
I have the following code which is giving me an error:
CREATE TRIGGER RATE_PER_UNIT_1
BEFORE INSERT ON SHD_SCHEDULE
FOR EACH ROW
SET NEW.RATE_PER_UNIT =
(
SELECT RATE
FROM SHD_TEACHER
WHERE TEACHERID = NEW.TEACHER_ID
LIMIT 1
)
SET NEW.COST = (
SELECT RATE
FROM SHD_TEACHER
WHERE TEACHERID = NEW.TEACHER_ID
) * UNITS
Any help please?
thanks
using your syntax, I would expect a delimiter statement and a begin/end block. So, try this:
DELIMITER $$
CREATE TRIGGER RATE_PER_UNIT_1
BEFORE INSERT ON SHD_SCHEDULE
FOR EACH ROW
BEGIN
SET NEW.RATE_PER_UNIT =
(
SELECT RATE
FROM SHD_TEACHER t
WHERE t.TEACHERID = NEW.TEACHER_ID
LIMIT 1
)
SET NEW.COST = (
SELECT t.RATE
FROM SHD_TEACHER t
WHERE t.TEACHERID = NEW.TEACHER_ID
) * NEW.UNITS
END $$
DELIMITER ;
You have a limit 1 in the first subquery, suggesting that there might be multiple matches. If so, you will get a run-time error in the second. Also, UNITS is just hanging out there, all alone. I assumed it is in the NEW record.
Here is another way to write this:
DELIMITER $$
CREATE TRIGGER RATE_PER_UNIT_1
BEFORE INSERT ON SHD_SCHEDULE
FOR EACH ROW
BEGIN
SELECT NEW.RATE_PER_UNIT := t.RATE, NEW.COST := t.RATE * NEW.UNITS
FROM (SELECT t.*
FROM SHD_TEACHER t
WHERE t.TEACHERID = NEW.TEACHER_ID
LIMIT 1
) t
END $$
DELIMITER ;