Assume I have the following tables:
Globals:
id (Primary key, Int, Auto increment)
Table 1:
t1Id (Primary key, Int)
date (Key, Datetime)
I want the following behaviour, when I do INSERT INTO table1 (date) VALUES(NOW()) for example, I want that:
An TRIGGER gets called before the actual insert happens.
In the trigger it will insert a new entry in Globals table.
It will use that id as the t1Id for Table 1.
The original INSERT will now happen with the value for t1Id.
This should effectively create a sort of global unique identifier for all tables that are to be effected by this trigger.
My knowledge about TRIGGERs is how to react on them and do stuff after the original trigger condition has been fulfilled (in this case the insert), but I do not know how to properly implement this specific behaviour.
Something like:
CREATE TRIGGER ins_check AFTER INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO Globals .... VALUES (NEW.t1Id)
END;
Row NEW contains the row as soon inserted. And so NEW.t1Id will contain the latest id added.
I would remove the primary key on Id column of the Globals table.
For details.
Related
Im looking for a way to use triggers to update a row in a different table.
The table im trying to get the info from is AI (Auto increment) and also the primary key of that table.
My problem is that i cant find a simple way of doing it.
My code:
DROP TRIGGER IF EXISTS Konsistens;
DELIMITER $$
CREATE TRIGGER Konsistens AFTER INSERT ON PersonData
FOR EACH ROW
BEGIN
INSERT INTO Bruker(BrukerNavn, Passord, PersonId)
VALUES('Bruker1', 'pw1', LAST_INSERT_ID(PersonData.PersonID));
END
All i want is for PersonID to be given a value inside the Bruker table.
Since PersonID is a foreign key from Person to Bruker it doesnt seem to exist when i try to get the value from it. When i use this trigger it also creates a bug where i can no longer insert values into PersonData.
My desired result is that when you insert something into PersonData you get a new row into Bruker which have the same PersonID as the new entry in PersonData.
You just reference recenty inserted row by NEW
CREATE TRIGGER Konsistens
AFTER INSERT ON PersonData
FOR EACH ROW
INSERT INTO Bruker (BrukerNavn, Passord, PersonId)
VALUES(NEW.BrukerNavn, NEW.Passord, NEW.PersonId);
I'm trying to add a value to a table but not without checking if the value already exists. This is what I have so far:
IF NOT EXISTS (
SELECT series.seriesName
FROM series
WHERE series.seriesName='Avengers'
)
BEGIN
INSERT INTO series (seriesName) VALUES 'Avengers'
END;
Database is a MySQL db on Ubuntu
You can use IGNORE keyword here.
It could look like:
INSERT IGNORE INTO series (seriesName) VALUES 'Avengers'
The important thing is to create a unique key on seriesName field as it seems that you want it to be unique.
INSERT IGNORE doesn't make the insert when key value already exists.
If you would like to be able to get id (primary key value) for row that wasn't inserted (already existed), you can do the following trick:
INSERT IGNORE INTO series (seriesName) VALUES 'Avengers'
ON DUPLICATE KEY UPDATE seriesID= LAST_INSERT_ID(seriesID)
Then you will be able to get the ID with LAST_INSERT_ID() function no matter if the row was inserted or not.
I have two table:
Am using this query to populate my marks table with all 'id' in student table:
$module1= "insert into marks (stud_id,moduleID)
select sid, 1
from user_student
where sid not in (
select * from (
select distinct stud_id from marks where moduleID=1
) alias_name
)";
So i need to take all 'sid' from Table student and populate them into table marks my query above does all that. The problem am encountering is that every time i make a change to the data e.g column test1 , new record are inserted again.
If i populate the marks table manually, Can't i have a code that when new data is available in student table, the data is just updated in marks table...
I don't understand some points of your insert query, why insert sid in stud_id if there's a id in student table to relate them?
Maybe solve your problem the creation of a composed unique key to moduleID and stud_id and use a REPLACE in place of INSERT.
But the right way to do it is using a TRIGGER like:
DROP TRIGGER IF EXISTS `student_after_insert`;
CREATE TRIGGER `student_after_insert` AFTER INSERT ON `student`
FOR EACH ROW INSERT INTO marks (stud_id,moduleID)
SELECT NEW.`id`, `modules_table`.`id` FROM `modules_table`;
PS: I suppose you have a table of modules with name modules_table. Change it accordingly.
I haven't understand your question at the best, my tip is:
Make a unique constraint on marks table (up to you is the choice of best constraint rule).
Then use a trigger to make the right insert/update:
Something like that, (hope that syntax is right):
CREATE TRIGGER myTrigger
AFTER INSERT ON students
FOR EACH ROW
BEGIN
// check that insertion doesn't broke the constraint previously define, then
insert into marks (stud_id,moduleID) values (new.sid, 1);
END
Note: NEW is the row that you have as soon inserted/updated on students. Similar you have OLD metarow.
How can I create a trigger that will insert data into another table.
For example: I have a department table and a course table and the course table has a foreign key named department_id.
I insert CICCT into the course table but there is no CICCT in the department table.
My goal is to make the trigger add the value in the department table. How can I do this?
I tried this, is this correct?
CREATE TRIGGER department_insert BEFORE INSERT
ON course
FOR EACH row
begin
INSERT INTO department
(department_id,
description)
VALUES (new.id_dep,
NULL);
end;
Another question in the same subject, what do I need to do in order reduce the room capacity by one when a student enrolls?
Your trigger might look like this
CREATE TRIGGER department_insert
BEFORE INSERT ON course
FOR EACH ROW
INSERT IGNORE INTO department (department_id, description)
VALUES (NEW.id_dep, NULL);
Note:
to access column values of a row being inserted you have to use the NEW keyword
NEW.id_dep
^^^
use IGNORE clause in INSERT to ignore department_id values if they already exist in department table. It allows to greatly streamline your code.
Here is SQLFiddle demo
Make a separate post for your second question and specify table schemas
My idea was to have a table called "changelog_table" that had the following columns:
updated_table //the table being updated
updated_column //the column being updated
updated_row //the id of the row being updated
updated_content //this is what they updated the field to
updated_user //the user who updated
updated_datetime //the timestamp it was updated
I think this is both the minimum and maximum of what I'd really want, but I may be wrong.
Also...I do not understand, after weeks of reading, how to store variables (like "which table is being updated" and "which column is being updated" and so forth) in my trigger.
So let's say I had a table called "foo_table", with a column "bar_column", with a row "58008", that is being updated to "this is the new content", by user "peter_griffin", at 12/30/2013 at noon.
What would a trigger that could capture that look like?
You'll need to create separate triggers on each table for UPDATE (and, if so desired, for INSERT and DELETE too). They could each call the same stored procedure that does the actual logging.
The trigger can pass to the stored procedure a parameter containing the name of the table on which the operation is being performed (since the trigger is table-specific, it will know this - it'll have to be hardcoded); to detect which column(s) have been updated you'll need to compare, within each trigger, NEW.column with OLD.column for each column in the respective table.
For example:
CREATE TRIGGER upd_tbl_name AFTER UPDATE ON tbl_name FOR EACH ROW
CALL AuditLog('UPDATE', 'tbl_name', NEW.id, CONCAT_WS(',',
IF(NEW.columnA <=> OLD.columnA, NULL, CONCAT('columnA:=', NEW.columnA)),
IF(NEW.columnB <=> OLD.columnB, NULL, CONCAT('columnB:=', NEW.columnB)),
-- etc.
));
CREATE PROCEDURE AuditLog(
Action VARCHAR(10),
TableName VARCHAR(64),
RowID INT,
Columns TEXT,
)
INSERT INTO changelog_table VALUES (
Action,
TableName,
RowID,
Columns
USER(),
NOW(),
);