I want to make a stored procedure for my mySQL server.
Here is my procedure
CREATE PROCEDURE ClientInsertProcedure (nomClient CHAR(40), userID INT(4), tel CHAR(10), codePostal CHAR(6), noCivique CHAR(6), r CHAR(30), v CHAR(30), cred DECIMAL(6, 2))
BEGIN
INSERT INTO Entreprise(nom_entreprise, telephone, code_postal, no_civique, rue, ville, credit) VALUES(nomClient, tel, codePostal, noCivique, r, v, cred)
ON DUPLICATE KEY UPDATE telephone = tel, code_postal = codePostal, no_civique = noCivique, rue = r, ville = v, credit = cred
WHERE nom_entreprise = nomClient;
END;
It keep saying that i have an error on last line near END;
I've tried with DELIMITER // and it has change nothing. I also went to mySQL website and i took the syntax there. I also looked Here. Is there any problem with the syntax itself or am i just doing it wrong?
Presumably you want an update on nom_entreprise = nomClient. If so, you need a unique index/constraint on that column:
create unique index idx_ClientInsertProcedure_nomClient
on ClientInsertProcedure(nomClient);
Then, this should work:
CREATE PROCEDURE ClientInsertProcedure (nomClient CHAR(40), userID INT(4), tel CHAR(10), codePostal CHAR(6), noCivique CHAR(6), r CHAR(30), v CHAR(30), cred DECIMAL(6, 2))
BEGIN
INSERT INTO Entreprise(nom_entreprise, telephone, code_postal, no_civique, rue, ville, credit)
VALUES(nomClient, tel, codePostal, noCivique, r, v, cred)
ON DUPLICATE KEY UPDATE telephone = tel, code_postal = codePostal, no_civique = noCivique, rue = r, ville = v, credit = cred;
END;
As a general rule of advice, you should name parameters to stored procedures and functions with something like v_ so you can readily distinguish them from columns in tables.
you can try move away code inside, only
CREATE PROCEDURE ClientInsertProcedure (nomClient CHAR(40), userID INT(4), tel CHAR(10), codePostal CHAR(6), noCivique CHAR(6), r CHAR(30), v CHAR(30), cred
DECIMAL(6, 2))
BEGIN
END;
if no error, that mean your insert with problem
Here is how i got the code working :
I used DELIMITER
As pointed out by Gordon Linoff I wasn't needing a WHERE statement as the item was automatically selected
If so, you need a unique index/constraint on that column
The spacing after DELIMITER is VERY important
DELIMITER //
CREATE PROCEDURE sp_ClientInsert (v_nomClient CHAR(40), v_userID INT(4), v_tel CHAR(10), v_codePostal CHAR(6), v_noCivique CHAR(6), v_rue CHAR(30), v_ville CHAR(30), v_cred DECIMAL(6, 2))
BEGIN
INSERT INTO Entreprise(nom_entreprise, telephone, code_postal, no_civique, rue, ville, credit) VALUES(v_nomClient, v_tel, v_codePostal, v_noCivique, v_rue, v_ville, v_cred)
ON DUPLICATE KEY UPDATE telephone = v_tel, code_postal = v_codePostal, no_civique = v_noCivique, rue = v_rue, ville = v_ville, credit = v_cred;
END //
DELIMETER ;
After some research the DELIMITER keyword make the code act as a single block. On the mySQL website, it specifies that the string "//" (without quotes) after DELIMITER is replace by ";" (without quotes)
The delimiter is changed to // to enable the entire definition to be passed to the server as a single statement, and then restored to ; before invoking the procedure. This enables the ; delimiter used in the procedure body to be passed through to the server rather than being interpreted by mysql itself.
This enable a block of code to be execute as a whole.
Thanks for the help.
EDIT
Here is a link that explain INSERT INTO... ON DUPLICATE KEY UPDATE provided by Yu Yenken
Related
I'm looking for something can help me to get the id of the ticket created at the first row.
I know i can simplify this by using different prepared query but I want not (try and see if it possible by this way and if it's not using the multiple queries way.
I know LAST_INSERT_ID() in mysql but I'm a little worried about inserting several lines at the same time....
During my research I also see someone directy SELECT the specified ID but it's a big cost of ressources.
I also see ##INSERTED and i didn't see a big difference between them, so i had the same problem...
The code :
CREATE PROCEDURE `Create_Ticket`(IN idU bigint(16),IN type VARCHAR(45),IN pseudo VARCHAR(45), IN lienacc VARCHAR(100), IN liengame VARCHAR(100), IN content VARCHAR(500))
BEGIN
INSERT INTO `dbOneT`.`Ticket` (`FaceitGame`,`Status`,`Ouverture` )
VALUES ( liengame , 0 , NOW());
INSERT INTO `dbOneT`.`Users_has_Ticket` (`Users_id`, `Ticket_id`)
VALUES ( idU, `Ticket`.`idTicket` );
INSERT INTO `dbOneT`.`Accuse` (`Pseudo`,`LienFaceit`)
VALUES (pseudo, lienacc);
INSERT INTO `dbOneT`.`Ticket_has_Accuse` (`Ticket_id_A`, `Accusé_id`)
VALUES (`Ticket`.`idTicket`, `Accuse`.`idAccuse`);
END
I'm running MariaDB 10.3.27
The "computer" is a raspberry pi 4B with 8go ram
On Raspberry Pi OS (A debian)
thanks for your help and have a nice day
Tom
CREATE PROCEDURE `Create_Ticket`(IN idU bigint(16),IN type VARCHAR(45),IN pseudo VARCHAR(45), IN lienacc VARCHAR(100), IN liengame VARCHAR(100), IN content VARCHAR(500))
BEGIN
-- declare variables for inserted PK AI values
DECLARE _idTicket INT;
DECLARE _idAccuse INT;
INSERT INTO `dbOneT`.`Ticket` (`FaceitGame`,`Status`,`Ouverture` )
VALUES ( liengame , 0 , NOW());
-- save assignerd AI value to the variable
SET _idTicket := LAST_INSERT_ID();
INSERT INTO `dbOneT`.`Users_has_Ticket` (`Users_id`, `Ticket_id`)
-- use saved value
VALUES ( idU, _idTicket );
INSERT INTO `dbOneT`.`Accuse` (`Pseudo`,`LienFaceit`)
VALUES (pseudo, lienacc);
-- save assignerd AI value to the variable
SET _idAccuse := LAST_INSERT_ID();
-- use saved values
INSERT INTO `dbOneT`.`Ticket_has_Accuse` (`Ticket_id_A`, `Accusé_id`)
VALUES (_idTicket, _idAccuse);
END
The following procedure is not returning values. Whats wrong?
CREATE PROCEDURE `sp_ValidarLogin`
(pEmail VARCHAR(45),
pSenha VARCHAR(255),
OUT rId INT,
OUT rNome VARCHAR(45),
OUT rDataNascimento DATE)
SELECT #rId = ID,
#rNome = NOME,
#rDataNascimento = DATA_NASCIMENTO
FROM usuario
WHERE EMAIL = pEmail AND SENHA = pSenha;
CALL sp_ValidarLogin ('rcaldas.ti#gmail.com','1234', #id, #nome, #nascimento);--its correct
select #id, #nome, #nascimento;
You have to use := instead of = to assign values on SELECT:
CREATE PROCEDURE `sp_ValidarLogin` (
pEmail VARCHAR(45),
pSenha VARCHAR(255),
OUT rId INT,
OUT rNome VARCHAR(45),
OUT rDataNascimento DATE)
SELECT #rId := ID, #rNome := NOME, #rDataNascimento := DATA_NASCIMENTO
FROM usuario
WHERE EMAIL = pEmail AND SENHA = pSenha;
demo on dbfiddle.uk
Previous releases of MySQL made it possible to assign a value to a user variable in statements other than SET. This functionality is supported in MySQL 8.0 for backward compatibility but is subject to removal in a future release of MySQL.
When making an assignment in this way, you must use := as the assignment operator; = is treated as the comparison operator in statements other than SET.
source: https://dev.mysql.com/doc/refman/8.0/en/user-variables.html
there is a hranimka, when it was created, an error occurs. Maybe she who struck by the ...
The stored procedure:
CREATE PROCEDURE insert_log(
IN LogType INT,
IN LogIdNote INT,
IN LogName VARCHAR,
IN LogTime TIMESTAMP,
IN logTypeCategory INT,
IN LogIdUser INT)
begin
INSERT INTO log (LogType,
LogIdNote,
LogName,
LogTime,
logTypeCategory,
LogIdUser,
LogTypeUser,
LogUrl)
SELECT LogType, LogIdNote, LogName, LogTime, logTypeCategory, LogIdUser, url.URLCategorysubscribetotype, u.UsersTypeAccount FROM users u LEFT JOIN categorysubscribetotype url ON url.CategoryTypeCategorysubscribetotype = LogType WHERE u.idUsers = LogIdUser;
end //
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 'INT LogType, INT LogIdNote, VARCHAR LogName, TIMESTAMP LogTime,
I' at line 3
I tried only change data types at params.
I think, the next code will give me a good result, but I need save result from SELECT query at variable and insert it at query Insert:
DELIMITER |
CREATE PROCEDURE insert_log(
IN pLogType INT,
IN pLogIdNote INT,
IN pLogName VARCHAR(150),
IN pLogTime TIMESTAMP,
IN plogTypeCategory INT,
IN pLogIdUser INT)
BEGIN
DECLARE user_type INT DEFAULT 0;
DECLARE url VARCHAR(250) DEFAULT;
SET user_type = (SELECT UsersTypeAccount FROM users WHERE idUsers = pLogIdUser);
SET url = (SELECT URLCategorysubscribetotype FROM categorysubscribetotype WHERE CategoryTypeCategorysubscribetotype = pLogType);
INSERT INTO log (pLogType,
pLogIdNote,
pLogName,
pLogTime,
plogTypeCategory,
pLogIdUser,
pLogTypeUser,
pLogUrl)
VALUES (
LogType,
LogIdNote,
LogName,
LogTime,
logTypeCategory,
LogIdUser,
user_type,
url
);
END |
delimiter ;
Your issue is here:
INSERT INTO log (pLogType, //wrong!
pLogIdNote,
pLogName,
pLogTime,
plogTypeCategory,
pLogIdUser,
pLogTypeUser,
pLogUrl)
You have used the parameter as column while they should be VALUES try this Query
DELIMITER //
CREATE PROCEDURE insert_log(
IN pLogType INT,
IN pLogIdNote INT,
IN pLogName VARCHAR(150),
IN pLogTime TIMESTAMP,
IN plogTypeCategory INT,
IN pLogIdUser INT)
BEGIN
DECLARE user_type INT DEFAULT 0;
DECLARE url VARCHAR(250) DEFAULT;
SET user_type = (
SELECT UsersTypeAccount
FROM users
WHERE idUsers = pLogIdUser
);
SET url = (
SELECT URLCategorysubscribetotype
FROM categorysubscribetotype
WHERE CategoryTypeCategorysubscribetotype = pLogType
);
INSERT INTO log (
`LogType`,
`LogIdNote`,
`LogName`,
`LogTime`,
`logTypeCategory`,
`LogIdUser`,
`LogIdUserType`, /*I added this*/
`LogIdUrl`, /*this one too */
)VALUES (
pLogType,
pLogIdNote,
pLogName,
pLogTime,
plogTypeCategory,
pLogIdUser,
user_type,
url
);
END //
DELIMITER ;
Please note You need to adjust this stored procedure, there was few mistakes. for example pLogTypeUser and pLogUrl are undefined and I added comments where you need to change the column name.
Your syntax is wrong. The data types come after the parameter names, the IN/OUT specifiers come before. Something like this:
CREATE PROCEDURE insert_log(
IN LogType INT,
IN LogIdNote INT,
IN LogName VARCHAR(10),
IN LogTime TIMESTAMP,
IN logTypeCategory INT,
IN LogIdUser INT)
begin
...
Edit: Also note that I added a size specifier to the VARCHAR data type, since it requires one. I guessed at 10, but you can replace that value with whatever yours is.
I created the following stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `add_summit`(IN `assoc_code` CHAR(5), IN `assoc_name` CHAR(50), IN `reg_code` CHAR(2), IN `reg_name` CHAR(100), IN `code` CHAR(20), IN `name` CHAR(100), IN `sota_id` CHAR(5), IN `altitude_m` SMALLINT(5), IN `altitude_ft` SMALLINT(5), IN `longitude` DECIMAL(10,4), IN `latitude` DECIMAL(10,4), IN `points` TINYINT(3), IN `bonus_points` TINYINT(3), IN `valid_from` DATE, IN `valid_to` DATE)
BEGIN
declare assoc_id SMALLINT(5);
declare region_id SMALLINT(5);
declare summit_id MEDIUMINT(8);
-- ASSOCIATION check if an association with the given code and name already exists
SELECT id INTO assoc_id FROM association WHERE code = assoc_code LIMIT 1;
IF (assoc_id IS NULL) THEN
INSERT INTO association(code, name) VALUES (assoc_code, assoc_name);
set assoc_id = (select last_insert_id());
END IF;
-- REGION check if a region with the given code and name already exists
SET region_id = (SELECT id FROM region WHERE code = reg_code AND name = reg_name AND association_id = assoc_id);
IF (region_id IS NULL) THEN
INSERT INTO region(association_id, code, name) VALUES (assoc_id, reg_code, reg_name);
set region_id = (select last_insert_id());
END IF;
-- SUMMIT check if a summit with given parameters already exists
SET summit_id = (SELECT id FROM summit WHERE association_id = assoc_id AND region_id = region_id);
IF (summit_id IS NULL) THEN
INSERT INTO summit(code, name, sota_id, association_id, region_id, altitude_m, altitude_ft, longitude,
latitude, points, bonus_points, valid_from, valid_to)
VALUES (code, name, sota_id, assoc_id, region_id, altitude_m, altitude_ft, longitude, latitude,
points, bonus_points, valid_from, valid_to);
END IF;
END$$
basically, it should check if a record exists in some tables and, if it doesn't, it should insert it and use the inserted id (auto increment).
The problem is that even if the record exists (for instance in the association table), assoc_id keeps returning null and that leads to record duplication.
I'm new to stored procedures so I may be doing some stupid errors. I've been trying to debug this SP for hours but I cannot find the problem.
A newbie mistake.
I forgot to specify the table name in the field comparison and that leads to some conflicts with param names (for example the param name).
A good idea is to specify some kind of prefix for parameters (like p_) and always specify the name of the table in the SP.
I have written the following stored procedure which in HeidiSQL is giving me an Error 1064 at the line starting with SET pay_ref = SELECT CONCAT('KOS' ...
Let me firstly explain what's going on with this procedure. I have a table gamers with a BIGINT primary key with auto_increment. This proc is supposed to:
Take in some params from the user
Check if the user already exists in the db according to his/her email address, and spits back the word "DUPLICATE" if a reord does exist
Else it does the insert as normal
Then it reads in the ID of the new record created and converts it to a varchar, pads it with leading zeros and then gets concatenated with some other strings
This new string (which should read for example KOS00001ABCDEF) then gets updated to the pay_refcode field >>> this is how we have settled on generating a unique payment reference for the user
If all works out well it updates retval with the newly generated reference code to be read by PHP script.
DELIMITER //
CREATE PROCEDURE `InsertGamer` (
IN p_fname VARCHAR(30),
IN p_lname VARCHAR(30),
IN p_email VARCHAR(255),
IN p_favgame VARCHAR(60),
IN p_pay_suffix VARCHAR(6),
OUT retval VARCHAR(14)
)
BEGIN
DECLARE last_id BIGINT;
DECLARE pay_ref VARCHAR(14);
IF (EXISTS(SELECT * FROM gamers WHERE (email = p_email))) THEN
SET retval = 'DUPLICATE';
ELSE
INSERT INTO gamers (fname, lname, email, favgame, pay_refcode)
VALUES (p_fname, p_lname, p_email, p_favgame, NULL);
SET last_id = LAST_INSERT_ID();
SET pay_ref = SELECT CONCAT('KOS', (SELECT LPAD(CONVERT(last_id, VARCHAR(5)),5,'0')), p_pay_suffix);
UPDATE gamers
SET pay_refcode = pay_ref
WHERE application_id = last_id;
SET retval = pay_ref;
END IF;
END //
I cannot for the life of me figure out what the problem is and would sincerely appreciate any help from you. Thank you very much in advance!
You just need to remove the SELECT keyword from line which you set the value for pay_ref.
SET pay_ref = CONCAT('KOS', LPAD(CONVERT(last_id, CHAR(5)),5,'0'), p_pay_suffix);
full code:
DELIMITER //
CREATE PROCEDURE `InsertGamer` (
IN p_fname VARCHAR(30),
IN p_lname VARCHAR(30),
IN p_email VARCHAR(255),
IN p_favgame VARCHAR(60),
IN p_pay_suffix VARCHAR(6),
OUT retval VARCHAR(14)
)
BEGIN
DECLARE last_id BIGINT;
DECLARE pay_ref VARCHAR(14);
SET #count := (SELECT COUNT(*) FROM gamers WHERE email = p_email)
IF (#count > 0) THEN
SET retval = 'DUPLICATE';
ELSE
INSERT INTO gamers (fname, lname, email, favgame, pay_refcode)
VALUES (p_fname, p_lname, p_email, p_favgame, NULL);
SET last_id = LAST_INSERT_ID();
SET pay_ref = CONCAT('KOS', LPAD(CONVERT(last_id, CHAR(5)),5,'0'), p_pay_suffix);
UPDATE gamers
SET pay_refcode = pay_ref
WHERE application_id = last_id;
SET retval = pay_ref;
END IF;
END //
DELIMITER ;