how to update multiple columns from a trigger MySQL - php

hi i am using mysql trigger to update a table on another table's insertion
this trigger works fine
CREATE TRIGGER `update_pupil_subject` AFTER INSERT ON `pupil_marks`
FOR EACH ROW
BEGIN
UPDATE pupil_subjects SET NumberOfStudens = NumberOfStudens + 1 WHERE NEW.SubjectID = SubjectID;
END$$
but this gives an error
CREATE TRIGGER `update_pupil_subject` AFTER INSERT ON `pupil_marks`
FOR EACH ROW
BEGIN
UPDATE pupil_subjects SET NumberOfStudens = NumberOfStudens + 1 , AverageMarks = (SELECT AVG(Marks) FROM pupil_marks WHERE NEW.StudentID = StudentID ) WHERE NEW.SubjectID = SubjectID;
END$$
how to write this correctly , please help . thanks in advance .

Apparently there were problems when sub-queries were used:
Can you try splitting the SQL statement:
DELIMITER $$
CREATE TRIGGER `update_pupil_subject`
AFTER INSERT
ON `pupil_marks`
FOR EACH ROW
BEGIN
DECLARE avg_marks float;
SELECT AVG(Marks)
INTO avg_marks
FROM pupil_marks
WHERE NEW.SubjectID = SubjectID;
UPDATE pupil_subjects
SET NumberOfStudens = NumberOfStudens + 1, AverageMarks = avg_marks
WHERE NEW.SubjectID = SubjectID;
END
$$
Edit: Use
SHOW TRIGGERS WHERE `table` = 'pupil_marks';
to get all triggers defined on pupil_marks. You can't have multiple triggers on an event as all actions can be covered in single trigger.
NOTE: I think AVG(Marks) is for a given subject, so modified trigger definition accordingly.

declare a variable inside the trigger and assign it with the subquery
declare avg_mark integer default 0;
set avg_mark := (SELECT AVG(Marks) FROM pupil_marks WHERE NEW.StudentID = StudentID);
then use the variable "avg_mark" in your update statement...
it may work...
if not then check the delimiter just below phpmyadmin sql box . It should be "$$"

Related

MySQL generate url using already assigned ID

I'm trying to generate URL in SQL database using already assigned auto_incremented ID
When a new form is submitted then SQL automatically generates and unique lens_id for me. How can I automatically add it there in this lens_url? (Picture below)
You can do this by creating a trigger on your table. Trigger is as follows,
DELIMITER $$
CREATE TRIGGER `UpdateLensURL` BEFORE INSERT ON `your_table_name`
FOR EACH ROW BEGIN
SET NEW.lens_url= CONCAT('localhost:8888/lensview/post.php?id=', (
SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'your_table_name'
));
END;
$$
DELIMITER ;
There are two options here:
1) Use a stored procedure (which will require code changes for anywhere that inserts rows)
2) Use a trigger and insert as normal - something like below should do the trick:
DELIMITER //
CREATE TRIGGER my_awesome_trigger
BEFORE INSERT
ON your_table_name
FOR EACH ROW
BEGIN
DECLARE next_id int default 0;
SELECT auto_increment INTO next_id
FROM information_schema.tables
WHERE table_name = 'your_table_name'
AND table_schema = DATABASE();
SET NEW.lens_url = CONCAT('localhost:8888/.../', next_id);
END; //
DELIMITER ;
Try something like this
$qry1="insert into tablename(lens_name,lens_url,lens_category,lens_author,lens_discription,lens_repert)values('A','B','C','D','E','F')";// your query to insert data to table
mysqli_query($con,$qry1); // run query
$last_insertid=mysqli_insert_id($con); // save last insetred ID
$url="localhost:8888/lenseview/post.php?id=".$last_insertid; //prepare url
$qry2="upadte tablename set lens_url=$url where lens_id=$last_insertid"; //update query
mysqli_query($con,$qry2); // run your query to update url
I think easiest option would be this
$Last_Lens_IdQ = mysqli_query($conn, "SELECT `lens_id` FROM `table` ORDER BY `lens_id` DESC LIMIT 1");
$Last_LensId = mysqli_fetch_array($Last_Lens_IdQ);
$x = $Last_Lens[0]++;
$LensUrl = "localhost:8888/lenseview/post.php?id=".$x;
Then insert the field and use $LensUrl When inserting the lens url column

How to get last inserted row ID from wordpress database with trigger which increment ID

I use Wordpress with a database. My problem is that I want to retrieve the inserted ID when using wpdb-> insert. I want to clarify that I increment the ID using a database trigger because my table is a relative entity. I was thinking of creating a procedure that I would call after my insertion.
My trigger
BEGIN
DECLARE num INTEGER;
IF NEW.id IS NULL THEN
SET num =
(
SELECT MAX(id) + 1
FROM ab_autreFrais
WHERE idDevis = NEW.idDevis
);
SET NEW.id = num;
ELSEIF NEW.id = 0 THEN
SET num =
(
SELECT MAX(id) + 1
FROM ab_autreFrais
WHERE idDevis = NEW.idDevis
);
SET NEW.id = num;
END IF;
END
There is the LAST_INSERT_ID() function that you can use instead of the trigger. Also you can get this value through an output parameter of a stored procrdure.
Or you could use auxiliary table or a global variable to put id value from the trigger. For example:
...
SET NEW.id = num;
UPDATE `SysData` SET `LastID` = num;
...
#Alexander
UPDATE ``SysData`` SET ``LastID`` = num; Does not work on MySQL SysData is not exist. I used SET SESSION last_insert_id = num in sql on phpmyadmin it work but with wpdb when i call last_insert_id() it return 0

trigger after insert on table 1, insert on table 2 with where condition column from table 1

My trigger is not working at all.
DELIMITER $$
CREATE TRIGGER leave_credit_nt
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
INSERT INTO nonteaching_leavecredit (IdNum, Date_Hired, Emp_Stat, Date_Leave_Ac, Vac_Leave, Sick_Leave)
VALUES (new.IdNum, new.Date_Hired, new.Emp_Stat, new.Date_Hired + INTERVAL 1 YEAR, 0, 0)
WHERE employees.Emp_Type = 'NON-TEACHING';
END $$
DELIMITER
I want that the trigger will insert values into my second table only those with employees.emp_type = 'NON-TEACHING'. Can someone help me get this trigger working?
emp_type is a column in my table employees.
Your INSERT query is wrong. MySQL INSERT Syntax does not support the WHERE clause so your query as it stands will fail.
You cant use WHERE condition with INSERT query. If you are using WHERE condition, it means you already have that row in the table. So , you should use UPDATE query instead of INSERT.
You can add conditional logic to your trigger with:
if new.Emp_Type = 'NON-TEACHING' then
INSERT INTO nonteaching_leavecredit (IdNum, Date_Hired, Emp_Stat, Date_Leave_Ac, Vac_Leave, Sick_Leave)
VALUES (new.IdNum, new.Date_Hired, new.Emp_Stat, new.Date_Hired + INTERVAL 1 YEAR, 0, 0);
end if;

Migration script in MySQL

I want to do a Migration data from one table to another.
I wrote a simple PHP script for my purposes but I wanted to do this by MySql script using user defined variables:
the PHP script looks like this:
//MIGRATION
$sql = "SELECT position FROM ts_user_config WHERE position != '' AND position NOT REGEXP '^-?[0-9]+$' GROUP BY TRIM(position) ORDER BY position";
$positions = db_loadColumn( $sql );
foreach ($positions as $key => $pos) {
$sql = "SELECT id FROM user_positions where UPPER(position) = UPPER('$pos')";
$posId = db_loadResult($sql);
if ($posId == null) {
$sql = "INSERT INTO user_positions (position, `desc`) VALUES ('$pos', '$pos')";
db_exec($sql);
$posId = db_insert_id();
}
$sql = "UPDATE ts_user_config SET position='$posId' WHERE TRIM(position)='$pos'";
db_exec($sql);
}
//---------
Could somebody be so kind and rewrite this PHP instructions to MySQL script? I tried to do this but my mySQL knowledge is very low and I couldn't done that.
Please help me if its not too much effort.
Thank you in advance.
I Have DONE IT !!!!!! :)
this is my mySQL script, I dont know if its perfect but its do what I need. Please tell me if I can make something better here. Thanks again :)
drop procedure if exists PositionMigration;
delimiter '//'
CREATE PROCEDURE PositionMigration()
BEGIN
BLOCK1: BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE pos VARCHAR(100);
DECLARE posId1 INT;
DECLARE posId2 INT;
DECLARE sql1 CURSOR FOR SELECT position FROM ts_user_config WHERE position != '' AND position NOT REGEXP '^-?[0-9]+$' GROUP BY TRIM(position) ORDER BY position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN sql1;
read_loop: LOOP
FETCH sql1 INTO pos;
IF done THEN
LEAVE read_loop;
END IF;
BLOCK2: BEGIN
DECLARE posNotFound INT DEFAULT FALSE;
DECLARE sql2 CURSOR FOR SELECT id FROM user_positions where UPPER(position) = UPPER(pos);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET posNotFound = TRUE;
OPEN sql2;
FETCH sql2 INTO posId1;
IF posNotFound THEN
INSERT INTO user_positions (position, \`desc\`) VALUES (pos, pos);
BLOCK3: BEGIN
DECLARE sql3 CURSOR FOR SELECT LAST_INSERT_ID();
OPEN sql3;
FETCH sql3 INTO posId2;
UPDATE ts_user_config SET position=posId2 WHERE TRIM(position)=pos;
CLOSE sql3;
END BLOCK3;
ELSE
UPDATE ts_user_config SET position=posId1 WHERE TRIM(position)=pos;
END IF;
CLOSE sql2;
END BLOCK2;
END LOOP;
CLOSE sql1;
END BLOCK1;
END;
//
delimiter ';'
call PositionMigration();

Get Updated Value in MySQL instead of affected rows

I've been trying to find an answer to this question, but haven't found any definitive "yes" or "no" in all my research.
I'm running a simple MySQL query like this:
UPDATE item SET `score`=`score`+1 WHERE `id`=1
Is there a way for that query to return the updated value, instead of the number of rows affected? Just as a reference, I'm doing this in PHP, so the actual code looks like:
$sql = "UPDATE item SET `score`=`score`+1 WHERE `id`=1";
$new_value = mysql_query($sql);
//Unfortunately this does not return the new value
I know I could do a second query and just SELECT the value, but I'm trying to cut down on queries as much as possible. Is there a way?
You can do it with a stored procedure that updates, and then selects the new value into an output parameter.
The following returns one column new_score with the new value.
DELIMITER $$ -- Change DELIMITER in order to use ; withn the procedure
CREATE PROCEDURE increment_score
(
IN id_in INT
)
BEGIN
UPDATE item SET score = score + 1 WHERE id = id_in;
SELECT score AS new_score FROM item WHERE id = id_in;
END
$$ -- Finish CREATE PROCEDURE statement
DELIMITER ; -- Reset DELIMITER to standard ;
In PHP:
$result = mysql_query("CALL increment_score($id)");
$row = mysql_fetch_array($result);
echo $row['new_score'];
No, there's nothing like postgresql's UPDATE ... RETURNING output_expression in MySQL (yet?).
If you don't want to run another Query SELECT then here is another way to do it. I have modified Mr. Berkowski code for reference:
DELIMITER $$
CREATE PROCEDURE increment_score
(
IN id_in INT
)
BEGIN
set #newScore := null;
UPDATE item SET score = IF((#newScore := score+1) <> NULL IS NULL, #newScore, NULL) WHERE id = id_in;
SELECT #newScore;
END
DELIMITER ;
No you cant. You could make a function or stored procedure that could do the insert and return the updated value but that would still require you to execute two queries from within the function or stored procedure.
You can create a trigger, and you will know everything about the modifications.

Categories