I'm wrote this mysql procedure for inserting customer billing details into an ecommerce database.
If i run this in phpmyadmin, it throws errors for any semicolons. I removed the semicolons but it gives 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 'DECLARE addr_id INT UNSIGNED ... at line 4
I've never worked with procedures before but i double checked the syntax and can't figure out the error.
DELIMITER //
CREATE PROCEDURE addCustomer(email VARCHAR(60), status VARCHAR(15), bill_pin_id SMALLINT UNSIGNED, bill_addr VARCHAR(175), name VARCHAR(60), tel VARCHAR(15))
BEGIN
DECLARE em_id INT UNSIGNED;
DECLARE addr_id INT UNSIGNED;
DECLARE cust_id INT UNSIGNED;
DECLARE sql_error TINYINT DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET sql_error = true;
--check if customer email already exists
SELECT id INTO em_id FROM email_list WHERE email = email;
-- not sure of the return value, haven't tested it
IF em_id = 1 THEN
-- if emails exists check if customer exists
SELECT id INTO cust_id FROM customer WHERE email_list_id = em_id;
IF cust_id = 1 THEN
-- customer must have address information
SELECT address_id INTO addr_id from customer_addr
INNER JOIN address on address_id = address.id
WHERE customer_id = cust_id and address = bill_addr;
END IF
END IF
START TRANSACTION;
IF (em_id = 0) THEN
-- if email doesn't exist, no customer no address - simple insert
INSERT INTO email_list (email, status) VALUES (email, status);
SELECT LAST_INSERT_ID() INTO em_id;
INSERT INTO customer (email_list_id, full_name, phone)
VALUES (em_id, name, tel);
SELECT LAST_INSERT_ID() INTO cust_id;
INSERT INTO address (pincode_id, address) VALUES (bill_pin_id, bill_addr);
SELECT LAST_INSERT_ID() INTO addr_id;
INSERT INTO customer_addr (address_id, customer_id)
VALUES (addr_id, cust_id);
ELSE
UPDATE email_list SET status = status where id = em_id;
UPDATE customer SET full_name = name, phone = tel WHERE id = cust_id;
UPDATE address SET pincode_id = bill_pin_id, address = bill_addr;
END IF
IF sql_error = FALSE THEN
COMMIT;
SELECT 'SUCCESS';
ELSE
ROLLBACK;
SELECT 'FAILED';
END IF
END //
DELIMITER ;
Try this solution, I added some missing semicolons and spaces in some comments.
CREATE addCustomer(email VARCHAR(60), status VARCHAR(15), bill_pin_id SMALLINT UNSIGNED, bill_addr VARCHAR(175), name VARCHAR(60), tel VARCHAR(15))
BEGIN
DECLARE em_id INT UNSIGNED;
DECLARE addr_id INT UNSIGNED;
DECLARE cust_id INT UNSIGNED;
DECLARE sql_error TINYINT DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET sql_error = true;
-- check if customer email already exists
SELECT id INTO em_id FROM email_list WHERE email = email;
-- not sure of the return value, haven't tested it
IF em_id = 1 THEN
-- if emails exists check if customer exists
SELECT id INTO cust_id FROM customer WHERE email_list_id = em_id;
IF cust_id = 1 THEN
-- customer must have address information
SELECT address_id INTO addr_id from customer_addr
INNER JOIN address on address_id = address.id
WHERE customer_id = cust_id and address = bill_addr;
END IF;
END IF;
START TRANSACTION;
IF (em_id = 0) THEN
-- if email doesn't exist, no customer no address - simple insert
INSERT INTO email_list (email, status) VALUES (email, status);
SELECT LAST_INSERT_ID() INTO em_id;
INSERT INTO customer (email_list_id, full_name, phone)
VALUES (em_id, name, tel);
SELECT LAST_INSERT_ID() INTO cust_id;
INSERT INTO address (pincode_id, address) VALUES (bill_pin_id, bill_addr);
SELECT LAST_INSERT_ID() INTO addr_id;
INSERT INTO customer_addr (address_id, customer_id)
VALUES (addr_id, cust_id);
ELSE
UPDATE email_list SET status = status where id = em_id;
UPDATE customer SET full_name = name, phone = tel WHERE id = cust_id;
UPDATE address SET pincode_id = bill_pin_id, address = bill_addr;
END IF;
IF sql_error = FALSE THEN
COMMIT;
SELECT 'SUCCESS';
ELSE
ROLLBACK;
SELECT 'FAILED';
END IF;
END
I figured this out by executing the entire procedure via mysql console
It accepted it without any errors. I then accessed the procedure from phpmyadmin routines tab and exported the statement.
The only difference i could find is this
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `addCustomer`(
IN `email` VARCHAR(60),
IN `status` VARCHAR(15),
IN `bill_pin_id` SMALLINT UNSIGNED,
IN `bill_addr` VARCHAR(175),
IN `name` VARCHAR(60),
IN `tel` VARCHAR(15)
)
-- regular procedure statements
END$$
DELIMITER ;
I had made some errors with not adding semicolons after if statements as pointed out by Domingo Sambo.
I deleted the procedure and tested it again adding it via phpmyadmin query box and its working perfectly.
Related
I created a parameterized STORED PROCEDURE with CRUD operation in MYSQL Version(6.0.11-alpha-community)
DELIMITER $$
CREATE PROCEDURE `mae`.`USP_CustomersToken_CURD`(IN CID INT , IN CName VARCHAR(50), IN CToken VARCHAR(250), IN CTokenTime DATETIME , IN OPType INT)
BEGIN
IF (OPType = 1) --Insert
THEN
INSERT INTO tbl_CustomersTokenInfo (ID, CustomerName, Token, TokenTime) VALUES (CID, CName, CToken, CTokenTime)
ELSEIF (OPType = 2) --delete
THEN
DELETE FROM tbl_CustomersTokenInfo WHERE ID = CID
ELSEIF (OPType = 3) --Update
THEN
UPDATE tbl_CustomersTokenInfo SET CustomerName = CName, Token = CToken , TokenTime = CTokenTime WHERE ID = CID
ELSEIF (OPType = 4) --Select
THEN
SELECT * FROM tbl_CustomersTokenInfo WHERE ID =CID
ELSEIF (OPType = 5)--Fetch
THEN
SELECT * FROM tbl_CustomersTokenInfo
END IF
END$$
DELIMITER ;
but when I executing this SP I'm getting this below error :
Query: CREATE PROCEDURE mae.USP_CustomersToken_CURD(IN CID INT , IN CName VARCHAR(50), IN CToken VARCHAR(250), IN CTokenTime DATETI...
Error Code: 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 'THEN
INSERT INTO tbl_CustomersTokenInfo (ID, CustomerName, Token, TokenTime) VAL' at line 4
Execution Time : 0 sec
Transfer Time : 0 sec
Total Time : 0 sec
I'm new to MYSQL commands and syntaxes if I did any mistake give the best approach .
MySQL (unlike most other DBMS) doesn't like comments introduced with -- where no space follows --.
You need to terminate all the statements, including the IF statement (after END IF), with a ;.
Correct that:
DELIMITER $$
CREATE PROCEDURE `mae`.`USP_CustomersToken_CURD`(IN CID INT , IN CName VARCHAR(50), IN CToken VARCHAR(250), IN CTokenTime DATETIME , IN OPType INT)
BEGIN
IF (OPType = 1) -- Insert
THEN
INSERT INTO tbl_CustomersTokenInfo (ID, CustomerName, Token, TokenTime) VALUES (CID, CName, CToken, CTokenTime);
ELSEIF (OPType = 2) -- delete
THEN
DELETE FROM tbl_CustomersTokenInfo WHERE ID = CID;
ELSEIF (OPType = 3) -- Update
THEN
UPDATE tbl_CustomersTokenInfo SET CustomerName = CName, Token = CToken , TokenTime = CTokenTime WHERE ID = CID;
ELSEIF (OPType = 4) -- Select
THEN
SELECT * FROM tbl_CustomersTokenInfo WHERE ID =CID;
ELSEIF (OPType = 5)-- Fetch
THEN
SELECT * FROM tbl_CustomersTokenInfo;
END IF;
END$$
DELIMITER ;
How do I check if the firstname is not filled and I've tried not null like this:
DELIMITER go
Create procedure registerusers(
Out UserID tinyint(11),
IN iFirstName varchar(30),
IN iLastName varchar(30),
IN iPassword varchar(30),
IN iEmailAddress varchar(30),
IN iSalt varchar(40),
IN iRoleID varchar(1))
BEGIN
/* I've used not null and it works for empty firstname but when I
try to pass the firstname it didn't work and I kept getting an error message saying "fill out the firstname" */
If(iFirstName not null) then
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Fill out the First Name ';
else
insert into users(
/* insert into user if its not empty */
FirstName,
LastName ,
Password ,
EmailAddress ,
Salt ,
RoleID
)
Values
(
iFirstName,
iLastName ,
iPassword ,
iEmailAddress ,
iSalt ,
iRoleID
);
set UserID = last_insert_id();
end if;
End
go
DELIMITER ;
However when I used
set #new_id = null;
call registerusers(#new_id,'','Jones','5566','jones#gmail.com','sdfd','1');
select #new_id;
it manages to display an error message but when I used
set #new_id = null;
call registerusers(#new_id,'Jason','Jones','5566','jones#gmail.com','sdfd','1');
select #new_id;
for inserting the firstname it kept displaying an error message other than wanting to insert the data.
I've tried if(firstname is null) but it didn't work because it went pass through message. For example if I used
set #new_id = null;
call registerusers(#new_id,'','Jones','5566','jones#gmail.com','sdfd','1');
select #new_id;
as empty for firstname it went through and it suppose to display an error message. If I used
set #new_id = null;
call registerusers(#new_id,'Jason','Jones','5566','jones#gmail.com','sdfd','1');
select #new_id;
it manages to go through.
I typed this up in verbatim from a textbook on MySQL.
There's a red X denoting an error on the line BEGIN with the text 'BEGIN' (begin) is not a valid input at this position.
The database used is View Ridge Gallery. Is there any obvious issues with the code?
DROP FUNCTION IF EXISTS InsertCustomerAndInterests;
DELIMITER $$
CREATE FUNCTION InsertCustomerAndInterests
(
newLastName Char(25),
newFirstName Char(25),
newAreaCode Char(3),
newPhoneNumber Char(8),
newEmail Varchar(100),
newNationality Char(30)
)
BEGIN
DECLARE varRowCount Int;
DECLARE varArtistID Int;
DECLARE varCustomerID Int;
DECLARE done Int DEFAULT 0;
DECLARE AristCursor CURSOR FOR
SELECT AristID
FROM ARTIST
WHERE Nationality=newNationality;
DECLARE continue HANDLER FOR NOT FOUND SET done = 1;
#Check to see if Customer already exists in datebase
SELECT Count(*) INTO varRowCount
FROM CUSTOMER
WHERE LastName = newLastName
AND FirstName = newFirstName
AND AreaCode = newAreaCode
AND PhoneNumber = newPhoneNumber
AND Email = newEmail;
#IF (varRowCount > 0 ) THEN Customer already exists
IF (varRowCount > 0 )
THEN
ROLLBACK;
SELECT 'Customer already exists';
END IF;
#IF (varRowCount = 0 ) THEN Customer does not exist.
#Insert new Customer data
IF (varRowCount = 0)
THEN
INSERT INTO CUSTOMER (LastName, FirstName, AreaCode, PhoneNumber, Email)
VALUES (newLastName, newFirstName, newAreaCode, newPhoneNumber, newEmail);
#Get new CustomerID surrogate key value
SET varCustomerID = LAST_INSERT_ID();
#Create intersection record for each appropriate Arist.
OPEN AristCursor;
REPEAT
FETCH ArtistCursor INTO varArtistArtistID;
IF NOT done THEN
INSERT INTO CUSTOMER_ARTIST_INT (ArtistID, CustomerID)
VALUES (varArtistID, varCustomerID);
END IF;
UNTIL done END REPEAT;
CLOSE ArtistCursor;
SELECT 'New customer and artist interest data added to database.'
AS InsertCustomerAndInterestsResults;
END IF;
END
$$
DELIMITER ;
You need to add return type before begin and must return value from the function.
DELIMITER $$
DROP FUNCTION IF EXISTS `InsertCustomerAndInterests`$$
CREATE FUNCTION `InsertCustomerAndInterests`(
newLastName CHAR(25),
newFirstName CHAR(25),
newAreaCode CHAR(3),
newPhoneNumber CHAR(8),
newEmail VARCHAR(100),
newNationality CHAR(30)
) RETURNS INT(11) # you missed return type here.
BEGIN
DECLARE done INT DEFAULT 0;
RETURN done; # must match with return type
END$$
DELIMITER ;
Since all functions need a return value and return type, you are missing the RETURNS clause after declaring your parameters. See CREATE FUNCTION
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 ;
I have 3 tables-
1. Country (CountryName, CID (PK- AutoIncrement))
2. State (SID(PK- AutoIncrement), StateName, CID (FK to Country)
3. City (CityName, CID, SID (FK to State)
Now I need to insert only the name into the three tables with CountryName, StateName and CityName.. The IDs need to get updated.
Create PROCEDURE sp_place(
#CountryName char(50),
#StateName varchar(50),
#CityName nchar(20)
)
AS
DECLARE #CountryID int, #StateID int, #CityID int;
Set NOCOUNT OFF
BEGIN TRANSACTION
INSERT INTO dbo.Country VALUES (#CountryName);
SET #CountryID = SCOPE_IDENTITY();
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
Insert into dbo.State VALUES (#StateName, #CountryID);
SET #StateID = SCOPE_IDENTITY();
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
Insert into dbo.City VALUES (#CityName, #StateID);
SET #CityID= SCOPE_IDENTITY();
Commit
When I Enter Country twice, the value shouldn't get changed.
Eg: If I enter India the value of CountryID=1, when I again enter India, the value of CountryID shouldn't get increased.
How'd I perform that? My SP changes for every insertion.
You can check if the country already exist and retrieve the countryID
IF NOT EXISTS(Select 1 FROM Country Where CountryName=#Country)
BEGIN
INSERT INTO dbo.Country VALUES (#CountryName);
SET #CountryID = SCOPE_IDENTITY();
END
ELSE
Select #CountryID = CountryID From Country Where CountryName=#Country
You can do the same for State and City if required
Hello try with this syntax
IF EXISTS (SELECT * FROM Country WHERE CountryName= #CountryName)
BEGIN
UPDATE dbo.Country
SET CountryName = #CountryName
WHERE CountryId = (SELECT CountryId FROM dbo.Country WHERE CountryName= #CountryName);
END
ELSE
BEGIN
INSERT INTO dbo.Country(CountryName) VALUES (#CountryName);
END
-- For the identity you must just add identity to your column in your creation script
Why dont you set Unique Constraint on CountryName column that won't allow you to insert duplicate countries at all
You need the MERGE syntax
http://technet.microsoft.com/en-us/library/bb510625.aspx
or to check manually (ie: with IF EXISTS (...) ) for the existence of the country before inserting.