Say I've got the following fields that make up a unique key in my table: (productid varchar(30), dateset date, dateend date)
I intend for dateend to be null until another row with the same productid with a newer dateset has been inserted, like this:
+----------+-------------+-------------+
|productid | dateset | dateend |
+----------+-------------+-------------+
|'PRODUCTA'|'2014-10-09' | NULL |
+----------+-------------+-------------+
|'PRODUCTA'|'2009-08-06' |'2014-10-09' |
+----------+-------------+-------------+
Now, I'm thinking about how I'd safely do this and I figure I'd run a trigger before the new row is inserted. It would essentially find the current max(dateset) where productid = #productid, and if it exists, it will update this row's dateend with #newdateset, the date that our new, succeeding row is inserted. The problem is, I have no idea how to get the variable #productid, or #newdateset. Is there any way to get the information of a row that's now about to be inserted? If I wrote:
insert into products (productid, dateset) values ('DEMOA', '2014-10-10')
How would I get my trigger to say #productid = 'DEMOA', #newdateset = '2014-10-10'?
Thanks,
Zakiir
To reference a column in a row that's now about to be updated, you'd write NEW.col_name, in my case:
NEW.productid
would reference 'DEMOA' in the following insert statement:
insert into products (productid, dateset) values ('DEMOA', '2014-10-10');
Like so:
delimiter //
CREATE TRIGGER update_row_version BEFORE INSERT ON products
FOR EACH ROW
BEGIN
SELECT productid, max(dateset) INTO #productid, #maxdateset FROM products WHERE productid = NEW.productid;
END;//
delimiter ;
INSERT INTO products (productid, price_local) VALUES ('DEMOA', 3000.00);
select #productid;
+-----------+
| #productid|
+-----------+
| DEMOA |
+-----------+
Apparently, what I was trying to achieve isn't possible as a trigger does not allow me to UPDATE the same table that I'm trying to INSERT into (Error 1442). There's already a post about it:
mysql trigger stored trigger is already used by statement which invoked stored trigger
Related
I have two tables I'm working with: Records and Invoice. Invoice contains a column for the primary key of Records to be stored as a foreign key.
I'm looking to create a trigger. Immediately when a new row is generated in Records, I want a new row to also be created in Invoice, and I want the PK from Records to be inserted into the corresponding column in invoice.
For example, let's say the tables are Records(RecordsID) and invoice(invoiceID, RecordsID)
When new row created in tbl Records
Create new row in tbl Invoice and insert new Records.RecordID into new invoice.invoiceID
I'm aware this is most likely very far off, but here is the trigger I've been working on:
DELIMITER $$
create trigger new_invoice
after insert
on main for each row
begin
if new.RecordID is not null then
insert into invoice(RecordID)
values(new.RecordID(new.RecordID));
END IF;
END$$
DELIMITER ;
Any assistance will be greatly appreciated.
Thank you.
Yes you have it almost right
CREATE tABLE main(RecordID int)
CREATE tABLE invoice (RecordID int)
create trigger new_invoice
after insert
on main for each row
begin
if new.RecordID is not null then
insert into invoice(RecordID)
values(new.RecordID);
END IF;
END
INSERT INTO main VALUES (1)
SELECT * FROM invoice
| RecordID |
| -------: |
| 1 |
db<>fiddle here
My tables:
Orders Products
Id(PK) |Quantity | Date | ProdIdFK |OrdFK(ref CustomerID) ProdID(PK) | Quantity | Name
and customer table.
I have to make an order using trigger so i do:
INSERT into Orders(Id, Quantity, Date, ProdIDFK, OrdFK)
values(3, 2, '2020/01/27', 15, 2);
CREATE TRIGGER QuantityUpdate
AFTER INSERT
ON Orders FOR EACH ROW
BEGIN
UPDATE Products
SET products.Quantity = Products.Quantity - New.Quantity
WHERE products.ProdID = New.ProdID
END$$
DELIMITER ;
But just nothing happening, it shows the old quantity and doesnt change. I tried to put INSERT after BEGIN(i dunno what is correct one) and also nothing. What is correct query for this?
Your trigger code looks OK - apart, maybe, for a glitch in the column name spotted by Gordon Linoff.
However, if you want it to fire on the INSERT statement that is showed in your script, you need to create it first, then INSERT.
CREATE TRIGGER QuantityUpdate
AFTER INSERT ON Orders FOR EACH ROW
BEGIN
...
END$$
DELIMITER ;
INSERT into Orders(Id, Quantity, Date, ProdIDFK, OrdFK)
VALUES(3, 2, '2020-01-27', 15, 2);
Once the trigger is created, it fires for every order inserted. It has no way, however, to take in account inserts that happened before its creation.
At the very least, the syntax is wrong in either the INSERT or the trigger, because one is using ProdIdfk and the other ProdId.
If the first is the correct name, then the trigger should be:
UPDATE Products p
SET p.Quantity = p.Quantity - New.Quantity
WHERE p.ProdID = New.ProdIDFK;
Let's say we got two tables.
First table is items - id, title.
Second table is history - id, title, action, user.
We can have following AFTER INSERT trigger for "This user inserted this item":
INSERT INTO history (title, action, user) VALUES (NEW.title, 'INSERT', #phpUserId);
If I want to insert new item, I can do something like this.
SET #phpUserId = 123;
INSERT INTO items (title) VALUES ('My best item');
In this case, trigger works perfectly.
But the problem is, when I add some text into variable - for example SET #phpUserId = "library123"; - In this moment the trigger is not able to take that variable.
Any ideas why only integer variables are passed?
Good news there's nothing wrong with your trigger and here's the proof
drop table if exists i,h;
create table i(id int, title varchar(20));
create table h(id int, title varchar(20), action varchar(20), user varchar(30));
drop trigger if exists t;
delimiter $$
create trigger t after insert on i
for each row
begin
INSERT INTO h (title, action, user) VALUES (NEW.title, 'INSERT', #phpUserId);
end $$
delimiter ;
SET #phpUserId = 123;
INSERT INTO i (title) VALUES ('My best item');
SET #phpUserId = 'bob123';
INSERT INTO i (title) VALUES ('My worst item');
+------+---------------+--------+--------+
| id | title | action | user |
+------+---------------+--------+--------+
| NULL | My best item | INSERT | 123 |
| NULL | My worst item | INSERT | bob123 |
+------+---------------+--------+--------+
2 rows in set (0.00 sec)
Please I am trying to insert the last ID into a different column of the same row in mysql. This is what i have tried
Insert Query
"INSERT INTO table(char,name) VALUES (LAST_INSERT_ID(),'KOKO')"
This is the Output
ID | char | name |
1 | 0 | KOKO |
HOWEVER, I expect that when a row is inserted the column char will insert the ID value as well; What i expect
ID | char | name |
1 | 1 | KOKO |
Please is there something i am doing wrong. Will be glad to know, thanks in advance
You can't use LAST_INSERT_ID() and insert in the same transaction because LAST_INSERT_ID() do not know value of the last insert id before insert
Please try to use update:
INSERT INTO table(char,name) VALUES (0,'KOKO')
UPDATE table
SET char = LAST_INSERT_ID()
WHERE ID = LAST_INSERT_ID()
According to MySQL documentation the LAST_INSERT_ID() returns a generated value that was set for an AUTO_INCREMENT column by the most recently executed INSERT statement. Therefore you need this sequence: insert -> get last insert id -> update. Here is code:
INSERT INTO table (char, name) VALUES (0, 'KOKO')
UPDATE table SET `char` = LAST_INSERT_ID() WHERE `ID` = LAST_INSERT_ID()
But it turns out that the column char duplicates column ID which possibly indicates wrong DB structure.
Go a quick question about triggers.
I have two tables. Namely people and attributes.
People has the following structure:
| id | firstname | surname | DOB | Age
Attributes has the following structure:
| id | person_id | haircolor | eyecolor | weight | height
And I have the following trigger:
Insert Into attributes (person_id)
SELECT id
FROM INSERTED
Which when a record gets inserted in the people table, a record gets inserted into the attributes table into the person_id column where the person_id is the same id as the person table. The rest of the inserted row is empty by default.
Now when both tables are empty and I create the first record, everything goes as expected. But when I create a second record two records get inserted into the attribute table.
I need it so that when I insert one row in the people table only one corresponding row gets inserted into the attributes table.
I am using the latest version of phpmyadmin at the time of writing.
Looking forward to hearing some responses
Cheers
You can do as following -
delimiter //
create trigger People_ins after insert on People
for each row
begin
declare pcount int;
select count(*) into pcount from attributes where person_id = new.id;
if pcount = 0 then
insert into attributes
(person_id) values (new.id);
end if;
end ;//
delimiter ;
You can skip the condition part if its always one-to-one relation.