I'm trying to create a trigger that increments the cardcount in faction table after an INSERT into card if a row'sfaction.factionname matches cards.faction of the INSERT.
so far I have tried a couple of different methods but the code below is my closest guess
create table cards(
cardid int not null,
faction varchar(255) not null,
primary key(cardid)
);
create table faction(
factionname varchar(255) not null,
cardcount int not null,
primary key(factionname)
);
create trigger updatecountinsert
after insert on cards
for each row
begin
update faction
set cardcount=carcount+1
where last_insert_id().faction=faction.factionname
end;
Basically if I insert values(11,'x') x being the faction if a row of faction has factionname=x
the trigger should
increase that row's "cardcount" by 1
DELIMITER $$
CREATE TRIGGER updatecountinsert
AFTER INSERT ON cards
FOR EACH ROW
BEGIN
-- NEW is used to qualify references values of the row that was just inserted
-- e.g. NEW.faction is a reference to the value in the faction column
UPDATE faction f
SET f.cardcount = f.cardcount + 1
WHERE f.factionname = NEW.faction ;
END;
$$
DELIMITER ;
What is the best method to atomically update a row if exists, else insert a new row into an table?
e.g. say we have this example below.
CREATE TABLE Test(
id integer,
val varchar(255)
)
DELIMITER $$
DROP PROCEDURE IF EXISTS `TestUpsert` $$
CREATE PROCEDURE `TestUpsert` (in value1 varchar(255), in id1 int)
BEGIN
IF EXISTS(Select 1 from Test where id=id1) THEN
UPDATE Test set val = value1 where id = id1;
ELSE
insert into Test(id, val) VALUES (id1, value1);
END IF;
END $$
DELIMITER ;
What changes can we make to TestUpsert to make it atomic?
Use on duplicate key update:
CREATE PROCEDURE `TestUpsert` (
in in_value varchar(255),
in in_id int
)
BEGIN
insert into test(id, val)
values (in_id, in_val)
on duplicate key update val = in_val;
END $$
I should add that for this to work, test.id has to be declared as the primary key or unique.
I recommend you read about INSERT ... ON DUPLICATE KEY UPDATE.
See my lengthy answer about this statement here: https://stackoverflow.com/a/548570/20860
I created a stored procedure which should perform the following:
Insert into Agencies Table, creating an id in the PK index row
Save the id in a variable
Insert the id and other data into Users table
The syntax below does not trigger any errors:
DELIMITER $$
CREATE PROCEDURE insertNewAgencyAndAdmin (IN aName varchar (100), IN numTrav int, IN polType int, IN uEmail varchar(255), IN uFName varchar(40), IN uLName varchar(40), IN uTitle varchar(100))
BEGIN
INSERT INTO btsAgency.Agencies (agencyName, numTrav, polType) VALUES (#aName, #numTrav, #polType);
SET #agencyID = (SELECT agencyID from btsAgency.Agencies where agencyID = LAST_INSERT_ID());
INSERT INTO btsUsers.Users (userAgencyID, userEmail, userFirstName, userLastName, userTitle ) VALUES
(#agencyID, #uEmail, #uFName, #uLName, #uTitle);
END
However, the Stored Proc doesn't insert my parameters into the tables when executed. So, after searching I try to create the SP like this (including $$ after "END" and resetting the delimiter to a semi-colon ):
DELIMITER $$
CREATE PROCEDURE insertNewAgencyAndAdmin (IN aName varchar (100), IN numTrav int, IN polType int, IN uEmail varchar(255), IN uFName varchar(40), IN uLName varchar(40), IN uTitle varchar(100))
BEGIN
INSERT INTO btsAgency.Agencies (agencyName, numTrav, polType) VALUES (#aName, #numTrav, #polType);
SET #agencyID = (SELECT agencyID from btsAgency.Agencies where agencyID = LAST_INSERT_ID());
INSERT INTO btsUsers.Users (userAgencyID, userEmail, userFirstName, userLastName, userTitle ) VALUES
(#agencyID, #uEmail, #uFName, #uLName, #uTitle);
END $$
DELIMITER ;
MySql creates the Stored Proc but gives me the following 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 'DELIMITER' at line 1
When I execute the created Stored Proc it still doesn't insert the data in my parameters.
Any help would be appreciated.
Some problems in your stored procedure:
It is important to indicate the difference between 9.4. User-Defined Variables and routine parameters 13.1.15. CREATE PROCEDURE and CREATE FUNCTION Syntax, are different variables (eg.: aName != #aName).
Avoid naming parameters or variables as columns of your tables.
DELIMITER $$
CREATE PROCEDURE `insertNewAgencyAndAdmin` (
/*
IN `aName` varchar (100),
IN `numTrav` int,
IN `polType` int,
IN `uEmail` varchar(255),
IN `uFName` varchar(40),
IN `uLName` varchar(40),
IN `uTitle` varchar(100)
*/
IN `_aName` varchar (100),
IN `_numTrav` int,
IN `_polType` int,
IN `_uEmail` varchar(255),
IN `_uFName` varchar(40),
IN `_uLName` varchar(40),
IN `_uTitle` varchar(100)
)
BEGIN
/*
INSERT INTO `btsAgency`.`Agencies` (
`agencyName`,
`numTrav`,
`polType`
) VALUES (
#`aName`,
#`numTrav`,
#`polType`
);
*/
INSERT INTO `btsAgency`.`Agencies` (
`agencyName`,
`numTrav`,
`polType`
) VALUES (
`_aName`,
`_numTrav`,
`_polType`
);
/*
SET #`agencyID` = (SELECT `agencyID` from `btsAgency`.`Agencies` where `agencyID` = LAST_INSERT_ID());
INSERT INTO `btsUsers`.`Users` (
`userAgencyID`,
`userEmail`,
`userFirstName`,
`userLastName`,
`userTitle`
) VALUES (
#`agencyID`,
#`uEmail`,
#`uFName`,
#`uLName`,
#`uTitle`
);
*/
INSERT INTO `btsUsers`.`Users` (
`userAgencyID`,
`userEmail`,
`userFirstName`,
`userLastName`,
`userTitle`
) VALUES (
LAST_INSERT_ID(),
`_uEmail`,
`_uFName`,
`_uLName`,
`_uTitle`);
END$$
DELIMITER ;
SELECT * FROM discounts $$
delimiter $$;
CREATE PROCEDURE insertData(IN id int,IN title varchar(255),IN amount decimal)
BEGIN
insert into discounts values (id,title,amount);
END; $$
call insertData(3,"sadasd",56);
/*DROP PROCEDURE insertData */
I have such procedure
DROP PROCEDURE IF EXISTS CreateNativeUser;
delimiter $$
CREATE PROCEDURE CreateNativeUser (p_email varchar(100), p_pass varchar(32))
BEGIN
insert into users(email) values (p_email);
insert into user_logins_native() values(???, p_email, p_pass);
commit;
END $$
delimiter ;
and I need some way to get user_id because user_logins_native has a foreign key on user_id column of users table
Using the LAST_INSERT_ID() function:
insert into users(email) values (p_email);
insert into user_logins_native() values(LAST_INSERT_ID(), p_email, p_pass);
I have 'users' table with the following fields:-
user_id (int, auto increment PK)
encrypted_userid (varchar 50)
user_name (varchar 50)
user_location (varchar 50)
What I want to do is create a trigger so that when values are inserted into the users table into user_name and user_location, i want to populate the encrypted_userid field with an AES_ENCRYPTED value from user_id - e.g. AES_ENCRYPT(user_id,'MYAESKEY') but only for the newly INSERTed row
Is this possible in MySQL with some kind of trigger?
Thanks in advance.
So is there a solution to my problem that will not fail etc? using a trigger - all other solutions i tried from reading other sources just didn't work.
Well all solutions revolve around LAST_INSERT_ID() because it's the only multi-user safe way to obtain auto generated ID.
First possible way, if you're very fond of triggers, is to have a separate table for auto generated sequences. Your schema will look like this
CREATE TABLE users_seq (user_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT);
CREATE TABLE users
(
user_id INT NOT NULL PRIMARY KEY DEFAULT 1,
encrypted_userid varchar(50),
user_name varchar(50),
user_location varchar(50),
FOREIGN KEY user_id_fk (user_id) REFERENCES users_seq (user_id)
);
And the trigger
DELIMITER //
CREATE TRIGGER useridinserttrigger
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO users_seq() VALUES();
SET NEW.user_id = LAST_INSERT_ID(),
NEW.encrypted_userid = AES_ENCRYPT(LAST_INSERT_ID(), 'MYAESKEY');
END//
DELIMITER ;
Second way is to leverage your existing schema but use a stored procedure
DELIMITER //
CREATE PROCEDURE insert_user(IN _name VARCHAR(50), IN _location VARCHAR(50))
BEGIN
DECLARE _id INT;
START TRANSACTION;
INSERT INTO users (user_name, user_location) VALUES(_name, _location);
SET _id = LAST_INSERT_ID();
UPDATE users
SET encrypted_userid = AES_ENCRYPT(_id, 'MYAESKEY')
WHERE user_id = _id;
COMMIT;
END//
DELIMITER ;
Sample usage:
CALL insert_user('johndoe', null);
I solved my problem using MySQL - Trigger for updating same table after insert (JCLG's entry)
CREATE TRIGGER `useridinserttrigger` BEFORE INSERT ON `users`
FOR EACH ROW BEGIN
DECLARE tmpid,tmpid2 INT(11);
SELECT user_id INTO tmpid FROM users ORDER BY user_id DESC LIMIT 1;
SET tmpid2=tmpid+1;
SET new.encrypted_userid=AES_ENCRYPT(tmpid2,'MYAESKEY');
END;