I have a stored procedure about 2 tables like this:
CREATE DEFINER=`brambang`#`%` PROCEDURE `create_discount_campaign`(
IN discount_campaign_discount_type_id CHAR(22),
IN discount_campaign_product_id INT(10),
IN discount_campaign_marketing_target_id INT(10),
IN discount_campaign_max_use_per_user int(11),
IN discount_campaign_discount_code varchar(100),
IN discout_campaign_discount_amount decimal(10,0),
IN discount_campaign_start_date datetime,
IN discount_campaign_end_date datetime,
IN discount_campaign_min_order_quantity INT(11),
IN discount_campaign_min_order_price decimal(10,0),
IN discount_campaign_discount_quota INT(11),
IN discount_campaign_min_product_varian INT(11),
IN discount_campaign_apply_all_product INT(10),
IN discount_campaign_product_product_id int(10) unsigned,
IN discount_campaign_product_active tinyint(1),
IN discount_campaign_product_createdby int(11),
IN discount_campaign_product_updatedby int(11),
IN discount_campaign_product_category_id VARCHAR(100),
IN discount_campaign_advanced_discount_advanced_rules_id int(50),
IN discount_campaign_advanced_value varchar(255),
IN discount_campaign_advanced_status tinyint(4)
)
proc:
BEGIN
DECLARE is_dc_discount_type_id INT(10);
DECLARE is_dc_product_id INT(10);
DECLARE is_dc_marketing_target_id INT(10);
DECLARE is_dc_max_use_per_user INT(11);
DECLARE is_dc_discount_code varchar(100);
DECLARE is_dc_discount_amount decimal(10,0);
DECLARE is_dc_start_date datetime;
DECLARE is_dc_end_date datetime;
DECLARE is_dc_min_order_quantity INT(11);
DECLARE is_dc_min_order_price decimal(10,0);
DECLARE is_dc_discount_quota INT(11);
DECLARE is_dc_min_product_variant INT(11);
DECLARE is_dc_apply_all_product INT(10);
DECLARE is_dcp_product_id INT(10);
DECLARE is_dcp_active tinyint(1);
DECLARE is_dcp_createdby int(11);
DECLARE is_dcp_updatedby int(11);
DECLARE is_dca_discount_advanced_rules_id int(50);
DECLARE is_dca_value varchar(255);
DECLARE is_dca_status tinyint(4);
DECLARE LAST_INSERT_ID int(11);
DECLARE discount_campaign_product_category_id varchar(100);
SET #querie = NULL;
SET #querie2 = NULL;
SET #querie3 = NULL;
SET lc_time_names = "id_ID";
SET #is_dc_discount_type_id = NULL;
SET #is_dc_product_id = NULL;
SET #is_dc_marketing_target_id = NULL;
SET #is_dc_max_use_per_user = NULL;
SET #is_dc_discount_code = NULL;
SET #is_dc_discount_amount = NULL;
SET #is_dc_start_date = NULL;
SET #is_dc_end_date = NULL;
SET #is_dc_min_order_quantity = NULL;
SET #is_dc_min_order_price = NULL;
SET #is_dc_discount_quota = NULL;
SET #is_dc_min_product_variant = NULL;
SET #is_dc_apply_all_product = NULL;
SET #is_dcp_product_id = NULL;
SET #is_dcp_active = NULL;
SET #is_dcp_createdby = NULL;
SET #is_dcp_updatedby = NULL;
SET #is_dca_discount_advanced_rules_id = NULL;
SET #is_dca_value = NULL;
SET #is_dca_status = NULL;
SET #LAST_INSERT_ID = NULL;
SET #discount_campaign_product_category_id = NULL;
SET #is_dc_discount_type_id = discount_campaign_discount_type_id;
SET #is_dc_product_id = discount_campaign_product_id;
SET #is_dc_marketing_target_id = discount_campaign_marketing_target_id;
SET #is_dc_max_use_per_user = discount_campaign_max_use_per_user;
SET #is_dc_discount_code = discount_campaign_discount_code;
SET #is_dc_discount_amount = discout_campaign_discount_amount;
SET #is_dc_start_date = discount_campaign_start_date;
SET #is_dc_end_date = discount_campaign_end_date;
SET #is_dc_min_order_quantity = discount_campaign_min_order_quantity;
SET #is_dc_min_order_price = discount_campaign_min_order_price;
SET #is_dc_discount_quota = discount_campaign_discount_quota;
SET #is_dc_min_product_variant = discount_campaign_min_product_varian;
SET #is_dc_apply_all_product = discount_campaign_apply_all_product;
SET #discount_campaign_product_category_id = discount_campaign_product_category_id;
SET #querie = CONCAT("
INSERT INTO discount_campaigns (
discount_type_id,
product_id,
marketing_target_id,
max_use_per_user,
discount_code,
discount_amount,
start_date,
end_date,
min_order_quantity,
min_order_price,
discount_quota,
min_product_variant,
apply_all_products,
createdAt,
updatedAt
) VALUES (
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
NOW(),
NOW()
);
");
PREPARE stmt FROM #querie;
EXECUTE stmt
USING
#is_dc_discount_type_id,
#is_dc_product_id,
#is_dc_marketing_target_id,
#is_dc_max_use_per_user,
#is_dc_discount_code,
#is_dc_discount_amount,
#is_dc_start_date,
#is_dc_end_date,
#is_dc_min_order_quantity,
#is_dc_min_order_price,
#is_dc_discount_quota,
#is_dc_min_product_variant,
#is_dc_apply_all_product;
DEALLOCATE PREPARE stmt;
SET #is_dcp_product_id = discount_campaign_product_product_id;
SET #is_dcp_active = discount_campaign_product_active;
SET #is_dcp_createdby = discount_campaign_product_createdby;
SET #is_dcp_updatedby = discount_campaign_product_updatedby;
SET #LAST_INSERT_ID = LAST_INSERT_ID();
IF (discount_campaign_apply_all_product = 0) THEN
SET #querie2 = CONCAT("INSERT INTO discount_campaign_product (discount_campaign_id,
product_id,
active,
createdby,
updatedby,
createdAt,
updatedAt
) SELECT ?,product_id,?,?,NULL,NOW(),NULL
FROM product_categories WHERE category_id IN
(?) AND status=1");
PREPARE stmt_2 FROM #querie2;
EXECUTE stmt_2
USING
#LAST_INSERT_ID,
#is_dcp_active,
#is_dcp_createdby,
#discount_campaign_product_category_id;
DEALLOCATE PREPARE stmt_2;
END IF;
END
basically i have 2 tables discount_campaign (any variable with an alias dc are this table) and discount_campaign_product (any variable with an alias dcp are this table). This stored procedure has a function to insert data into table discount_campaign with the parameter which been made. in discount_campaign table there's column namely apply_all_product. if apply_all_product filled "0" in parameter, then another parameter (with alias dcp) will insert some data in discount_campaign_product table. but when i applied with apply_all_product = 0, this store procedure only insert data in discount_campaign table, not in discount_campaign_product table.
Where is my mistake in this stored procedure?
I'd guess you didn't see any rows inserted into discount_campaign_product because there were no matching rows in product_categories. You used INSERT...SELECT FROM product_categories but you search for rows where category_id IN (?).
I suppose you mean this to turn into category_id IN (1,2,3,4,5) but that's not how query parameters work in SQL. One parameter can only be used for one scalar value. So in your code, it will search as if you did category_id IN ('1,2,3,4,5') which searches for a single string. It might match the first number in the string as it casts the string to a numeric, but if there is no category matching that first number, then it'll find no matches.
The workaround is to use FIND_IN_SET(category_id, '1,2,3,4,5'). This is really not how the function is supposed to be used, but it works to locate an integer in a comma-separated list of integers. Be careful not to put spaces in between the list elements, because it won't work with FIND_IN_SET().
Other issues:
You DECLARE local variables then you don't use them. Understand that in MySQL, the variables myvar and #myvar are two different variables. You need to declare as local variables the type with no # sigil. Whereas the type with the # sigil are user-defined session variables, which you don't declare -- just by setting its value, the variable is implicitly created.
You are using PREPARE/EXECUTE but there is no need to use dynamic SQL in this case. Your only dynamic parts are values, so you can just use the input parameters for the procedure as if they are query parameters. They are guaranteed to act like a single scalar, and they won't cause SQL injection. You would need to use PREPARE/EXECUTE only if you had dynamic expressions or dynamic identifiers in your queries, but you don't.
The only risk to using your procedure parameters directly in queries is that you should make sure the parameter names are not the same as any column names of tables in your query.
DECIMAL(10,0) doesn't make much sense. Why use decimal with 0 digits of scale? That's just an integer.
INT(11) vs INT(50) makes no difference. The argument to the INT types does not change their size or range of values. In fact, using this argument for INT types is deprecated in MySQL 8.0, so you should get into the habit of removing it.
Here's the procedure I tested, and it works:
CREATE PROCEDURE create_discount_campaign(
IN discount_campaign_discount_type_id CHAR(22),
IN discount_campaign_product_id INT,
IN discount_campaign_marketing_target_id INT,
IN discount_campaign_max_use_per_user INT,
IN discount_campaign_discount_code varchar(100),
IN discout_campaign_discount_amount decimal(10,0),
IN discount_campaign_start_date datetime,
IN discount_campaign_end_date datetime,
IN discount_campaign_min_order_quantity INT,
IN discount_campaign_min_order_price decimal(10,0),
IN discount_campaign_discount_quota INT,
IN discount_campaign_min_product_varian INT,
IN discount_campaign_apply_all_product INT,
IN discount_campaign_product_product_id INT UNSIGNED, -- this is unused?
IN discount_campaign_product_active TINYINT,
IN discount_campaign_product_createdby INT,
IN discount_campaign_product_updatedby INT,
IN discount_campaign_product_category_id VARCHAR(100),
IN discount_campaign_advanced_discount_advanced_rules_id INT,
IN discount_campaign_advanced_value varchar(255),
IN discount_campaign_advanced_status TINYINT
)
MODIFIES SQL DATA
BEGIN
DECLARE last_id BIGINT;
INSERT INTO discount_campaigns
SET
discount_type_id = discount_campaign_discount_type_id,
product_id = discount_campaign_product_id,
marketing_target_id = discount_campaign_marketing_target_id,
max_use_per_user = discount_campaign_max_use_per_user,
discount_code = discount_campaign_discount_code,
discount_amount = discout_campaign_discount_amount,
start_date = discount_campaign_start_date,
end_date = discount_campaign_end_date,
min_order_quantity = discount_campaign_min_order_quantity,
min_order_price = discount_campaign_min_order_price,
discount_quota = discount_campaign_discount_quota,
min_product_variant = discount_campaign_min_product_varian,
apply_all_products = discount_campaign_apply_all_product,
createdAt = NOW(),
updatedAt = NOW();
IF (discount_campaign_apply_all_product = 0) THEN
SET last_id = LAST_INSERT_ID();
INSERT INTO discount_campaign_product (discount_campaign_id,
product_id, active, createdby, updatedby, createdAt, updatedAt)
SELECT last_id, c.product_id, discount_campaign_product_active,
discount_campaign_product_createdby, NULL, NOW(), NULL
FROM product_categories AS c
WHERE FIND_IN_SET(c.category_id, discount_campaign_product_category_id)
AND c.status=1;
END IF;
END
Notice I used a different syntax for the first INSERT. This is a MySQL extension to standard SQL, and it only works for single-row inserts. But it's very handy, because it makes it easier. In standard INSERT syntax with the column list and then a VALUES clause, I find it's difficult to make sure I have matched the columns to the right values. The INSERT ... SET syntax is more readable.
Related
I have a simple mysql procedure which must return an query string. But, it returns almost every time QueryResult (column name) as <null> value.
create procedure return_table_rename_query(
IN targetTable VARCHAR(100),
IN tblPrefix VARCHAR(100)
)
BEGIN
SET #returnQuery = CONCAT('SELECT "MYSQLIMPORT can not rename table for target ', #targetTable, '";');
SET #totalRows = (SELECT COUNT(*) FROM table);
if IFNULL(#totalRows, 0) > 0
then
SET #returnQuery = CONCAT('drop table if exists table_name.', ...);
end if;
SELECT #returnQuery AS 'QueryResult';
end;
#targettable is not the same variable as targettable - you are mixing user defined variables and parameter variables and it seems likely that #targettable is null and if any element in a concat is null then the result is null.
Please read How to declare a variable in MySQL?
I am trying to create a table in a database based on a procedure that was created. I am not to familiar with MySQL procedures to be able to try and create this database.
Here's the code for the procedure:
DELIMITER //
CREATE PROCEDURE SetChanProps(IN vchanmask TEXT, in vchankey TEXT, IN vcommentxt TEXT, IN ventrymsg TEXT, IN vexpires TIMESTAMP, IN vgroupname TEXT, IN vchanlimit INT, IN vmodes TEXT, IN vonlyowner INT, IN vsetbynick TEXT, IN vsetbyhost TEXT, IN vsetbypid INT, IN vtopic TEXT, IN vkickexisting INT)
BEGIN
DECLARE msgid int;
DECLARE rowcount int;
DECLARE setondate TIMESTAMP;
SET setondate = CURRENT_TIMESTAMP;
SELECT COUNT(*) INTO rowcount FROM `chanprops` WHERE `chanmask` = vchanmask;
if rowcount > 0 THEN UPDATE `chanprops` SET `chankey` = vchankey, `comment` = vcommentxt, `entrymsg` = ventrymsg, `expires` = vexpires, `groupname` = vgroupname, `limit` = vchanlimit, `mode` = vmodes, `onlyowner` = vonlyowner, `setbynick` = vsetbynick, `setbyhost` = vsetbyhost, `setbypid` = vsetbypid, `topic` = vtopic, `setondate` = setondate WHERE `chanmask` = vchanmask;
ELSE INSERT INTO `chanprops` (`chanmask`,`chankey`,`comment`,`entrymsg`,`expires`,`groupname`,`limit`,`mode`,`onlyowner`,`setbynick`,`setbyhost`,`setbypid`,`topic`) VALUES (vchanmask,vchankey,vcommentxt,ventrymsg,vexpires,vgroupname,vchanlimit,vmodes,vonlyowner,vsetbynick,vsetbyhost,vsetbypid,vtopic);
end if;
SET msgid = 36;
select matrixqueue(msgid,vchanmask,vchankey,vcommentxt,ventrymsg,Unix_Timestamp(vexpires),vgroupname,vchanlimit,vmodes,vonlyowner,vsetbynick,vsetbyhost,vsetbypid,vtopic,Unix_Timestamp(setondate),vkickexisting);
END//
DELIMITER ;
Is this the correct line to gather what I need to make this table?
ELSE INSERT INTO `chanprops` (`chanmask`,`chankey`,`comment`,`entrymsg`,`expires`,`groupname`,`limit`,`mode`,`onlyowner`,`setbynick`,`setbyhost`,`setbypid`,`topic`) VALUES (vchanmask,vchankey,vcommentxt,ventrymsg,vexpires,vgroupname,vchanlimit,vmodes,vonlyowner,vsetbynick,vsetbyhost,vsetbypid,vtopic);
Would I then use the CREATE PROCEDURE line (Line #2) to determine that types for the the column IDs?
Unfortunately, the project I am trying to utilize this procedure on hasn't been worked on in years and has been abandoned by its creator. They've included other .sql files that usually just create the tables for me. They seemed to have missed this one which conveniently is the one I really care about.
I got a function that returns string between two strings:
CREATE FUNCTION dbo.udf_GetStringBetween2Chars (#String VARCHAR(50), #FirstSpecialChar VARCHAR(50), #LastSpecialChar VARCHAR(50))
RETURNS VARCHAR(50)
AS
BEGIN
DECLARE #FirstIndexOfChar INT,
#LastIndexOfChar INT,
#LengthOfStringBetweenChars INT
SET #FirstIndexOfChar = CHARINDEX(#FirstSpecialChar,#String,0)
SET #LastIndexOfChar = CHARINDEX(#LastSpecialChar,#String,#FirstIndexOfChar+1)
SET #LengthOfStringBetweenChars = #LastIndexOfChar - #FirstIndexOfChar -1
SET #String = SUBSTRING(#String,#FirstIndexOfChar+1,#LengthOfStringBetweenChars)
RETURN #String
END
However, when I try to get string between POINTDESCRIPTION and DATAPOINT, I get error:
SET ANSI_WARNINGS OFF
declare #table table
(string varchar(50))
insert into #table
select 'EVENT: ID Order Reassignment (Individual Job Specific Update)|||LOCATION: Reassign.reassign()|||DATEPOINTDESCRIPTION: Only specific ID orders were reassigned from user fatis to user blake.|||DATAPOINT: blake' union all
select 'EVENT: ID Order Reassignment (Individual Job Specific Update)|||LOCATION: Reassign.reassign()|||DATAPOINTDESCRIPTION: Only specific ID orders were reassigned from user ilevic to user manic2.|||DATAPOINT: manic2' union all
select 'EVENT: ID Order Reassignment (Individual Job Specific Update)|||LOCATION: Reassign.reassign()|||DATAPOINTDESCRIPTION: Only specific ID orders were reassigned from user links to user sepir.|||DATAPOINT: sepir'
select dbo.udf_GetStringBetween2Chars (Tab.string,'POINTDESCRIPTION: ','|||DATAPOINT')
FROM #table Tab
Msg 537, Level 16, State 2, Line 10
Invalid length parameter passed to the LEFT or SUBSTRING function.
Does anyone see why this would happen?
If anyone finds it useful, here is final function to return string between 2 strings:
CREATE FUNCTION dbo.udf_GetStringBetween2Chars (#String VARCHAR(500), #FirstSpecialChar VARCHAR(500), #LastSpecialChar VARCHAR(500))
RETURNS VARCHAR(500)
AS
BEGIN
DECLARE #FirstIndexOfChar INT,
#LastIndexOfChar INT,
#LengthOfStringBetweenChars INT
SET #FirstIndexOfChar = CHARINDEX(#FirstSpecialChar,#String,0)
SET #LastIndexOfChar = CHARINDEX(#LastSpecialChar,#String,#FirstIndexOfChar+1)
SET #LengthOfStringBetweenChars = #LastIndexOfChar - #FirstIndexOfChar -1
SET #String = SUBSTRING(#String,#FirstIndexOfChar+LEN(#FirstSpecialChar),#LengthOfStringBetweenChars)
RETURN #String
END
GO
And to call it:
select dbo.udf_GetStringBetween2Chars (tab.someString,'POINTDESCRIPTION: ','|||DATAPOINT')
FROM yourTable tab
I have looked over numerous tutorials, manuals and documentations, but I still can not get this to work.
I am trying to create a stored procedure using phpMyAdmin.
I cant seem to find the errors here, the sql errors are so vague...
CREATE PROCEDURE insertToonOneShot(IN locale CHAR(2), IN name VARCHAR(16), IN realm VARCHAR(24), IN faction CHAR(1), IN toon_level INT, IN class_name INT)
BEGIN
DECLARE #realmID INT;
DECLARE #classID INT;
DECLARE #toonID INT;
SET #realmID = SELECT id FROM realms WHERE realms.name = realm;
SET #classID = SELECT id FROM classes WHERE classes.name = class_name;
IF NOT #realmID IS NULL AND NOT #classID IS NULL AND #toonID IS NULL THEN
INSERT INTO
toon (`locale`, `name`, `realm_id`, `faction`, `level`, `class_id`)
VALUES
(locale, name, #realmID, faction, toon_level, #classID);
END IF;
END;
The error I am getting right now is:
#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 #realmID INT; DECLARE #classID INT; DECLARE #toonID INT; SET #rea
at line 3
Probably one of the more frustrating things I have ever had to do...
I have seen many tutorials online that show using the # symbol in variable declaration, and others not using it, I have even seen some that use VAR instead of DECLARE. What is the right syntax?...
This question, and its answers, seem to be confusing session variables (which are prefixed with #) with procedural variables (which are not prefixed.) See the answers to this question for more information.
The accepted solution resolves the error by using session variables, but it could introduce problems related to variable scope. For example, if a variable called realmID has been defined outside the procedure, its value will be overwritten when the procedure is run.
The correct way to resolve the problem is to use only procedural variables. These are DECLAREd at the start of the procedure without the # prefix.
DELIMITER $$
CREATE PROCEDURE insertToonOneShot(
IN locale CHAR(2),
IN name VARCHAR(16),
IN realm VARCHAR(24),
IN faction CHAR(1),
IN toon_level INT,
IN class_name INT
)
BEGIN
DECLARE realmID INT;
DECLARE classID INT;
SELECT id INTO realmID FROM realms WHERE realms.name = realm LIMIT 1;
SELECT id INTO classID FROM classes WHERE classes.name = class_name LIMIT 1;
IF realmID IS NOT NULL AND classID IS NOT NULL THEN
INSERT INTO toon (`locale`, `name`, `realm_id`, `faction`, `level`, `class_id`)
VALUES (locale, name, realmID, faction, toon_level, classID);
END IF;
END$$
DELIMITER ;
When you have a subquery, it needs to have parentheses. These lines:
SET #realmID = SELECT id FROM realms WHERE realms.name = realm;
SET #classID = SELECT id FROM classes WHERE classes.name = class_name;
Should be:
SET #realmID = (SELECT id FROM realms WHERE realms.name = realm);
SET #classID = (SELECT id FROM classes WHERE classes.name = class_name);
Or, better yet, you don't need the set:
SELECT #realmID := id FROM realms WHERE realms.name = realm;
SELECT #classID := id FROM classes WHERE classes.name = class_name;
This does the trick:
CREATE PROCEDURE insertToonOneShot(IN locale CHAR(2), IN name VARCHAR(16), IN realm VARCHAR(24), IN faction CHAR(1), IN toon_level INT, IN class_name VARCHAR(12))
BEGIN
SELECT #realmID := id FROM realms WHERE realms.name = realm;
SELECT #classID := id FROM classes WHERE classes.name = class_name;
SELECT #toonID := id FROM toon WHERE toon.name = name AND toon.realm_id = #realmID;
IF NOT #realmID IS NULL AND NOT #classID IS NULL AND #toonID IS NULL
THEN
INSERT INTO toon (`locale`, `name`, `class_id`, `realm_id`, `faction`, `level`)
VALUES (locale, name, #classID, #realmID, faction, toon_level);
END IF;
END;
//
Apparently the declare statements were not required... Who would have known?
Thanks to Gordon Linoff for pointing me in the right direction.
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 ;