Hi
I'm very very new at MySQL and was wondering if anyone could help me out.
I'm trying to build a procedure for my database and am using the following code.
CREATE PROCEDURE `createuser`(username VARCHAR(100), password VARCHAR(100), email VARCHAR(100)) BEGIN
DECLare returnValue int;
IF EXISTS(SELECT 'True' FROM User_Table WHERE(User_Username = username OR User_Email = email))
BEGIN
SET returnValue = 0;
END;
ELSE
BEGIN
SET returnValue = 1;
INSERT into User_Table(User_Username, User_Password,User_Email) VALUES(username, password,email)
END; END;
I'm getting a error on the BEGIN after the if statement. The error is "Bad syntax near "BEGIN SET returnvalue = 0; END ELSE;
Could you please tell me if im using the IF statement correctly in a mysql sence. It seems to work fine on a MSSql server but not on a Mysql.
Would it also be possible to point me in the direction of some good tutorials for this kinda stuff as the main MYSQL website isn't particularity user friendly.
Cheers
Instead of
IF statement
BEGIN
commands;
END
ELSE
BEGIN
commands;
END
use
IF statement THEN
commands;
ELSE
commands;
END IF;
Here is how I would write your procedure (changes may be a mixture of cosmetic changes and actual changes; suggest experimenting to find out which are which)
CREATE PROCEDURE `createuser` ( IN username VARCHAR(100),
IN password VARCHAR(100),
IN email VARCHAR(100)
)
BEGIN
DECLARE returnValue INT;
IF EXISTS (
SELECT 1
FROM User_Table
WHERE User_Username = username OR User_Email = email
) THEN
SET returnValue = 0;
ELSE
SET returnValue = 1;
INSERT INTO User_Table
(User_Username, User_Password, User_Email)
VALUES
(username, password, email);
END IF;
END;
You don't appear to be doing anything with the variable returnValue. You might need to declare this as OUT or INOUT, depending on what you want to do with it. I haven't got experience of using return values for stored procedures.
Related
This is my first time creating a sql procedure, and i need some help.
What i am trying to do is to create a procedure that returns true or false if the user has correctly inputed his email and password
DELIMITER $$
CREATE PROCEDURE login(IN email varchar(50), IN password varchar(30))
BEGIN
DECLARE #email VARCHAR(50);
DECLARE #password VARCHAR(50);
IF((SELECT COUNT(id) FROM users WHERE email = #email AND password = #password) = 0, 'true', 'false');
END$$
DELIMITER ;
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '#email VARCHAR(50);
DECLARE #password VARCHAR(50);
IF((SELECT COUNT(id' at line 3
This is the error message, i am using phpMyAdmin
Maybe this example will help you:
create table Test(Pass varchar(100), Mail varchar(100));
insert into Test(Pass, Mail) values('Pass1', "Email1");
insert into Test(Pass, Mail) values('Pass2', "Email2");
insert into Test(Pass, Mail) values('Pass3', "Email3");
DROP FUNCTION IF EXISTS loginFunction;
DELIMITER go
CREATE FUNCTION login(p_Pass char(100), p_Mail char(100)) RETURNS boolean
BEGIN
declare countUser int;
DECLARE flag boolean;
SET flag = IF( (select count(*)
from Test
where Pass = p_Pass and Mail = p_Mail) > 0, 1, 0);
RETURN flag;
END;
go
DELIMITER ;
SELECT login('Pass1', 'Email1');
Demo:
https://paiza.io/projects/sioJelUeAuqfrStgCe2h5w?language=mysql
You want your procedure to return something but you don't use 'return' in it
https://wiki.ispirer.com/sqlways/mysql/techniques/return-value-from-procedure
beside that, your code look very much vulnerable to SQL Injection
https://security.stackexchange.com/questions/68701/how-does-stored-procedure-prevents-sql-injection
Maybe you could consider doing this check in your application instead of inside the database
I have a stored routine that is meant to create a new desktop login token for my application, that verifies if the user has to relogin (anyway that's not important).
What is important is that the SQL I'm using doesn't seem to like me.
I only ever use T-SQL because I'm a .NET developer who focuses with SSMS for databases, but this time I stupidly decided to use MySQL with no experience XD
Here's the code:
CREATE PROCEDURE `insertNewToken`(IN `Username` VARCHAR(150), IN `Token` VARCHAR(500))
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
IF EXISTS(SELECT *
FROM desktopTokens
WHERE desktopTokens.AssignedUsername = Username) THEN
BEGIN
UPDATE desktopTokens
SET desktopTokens.TokenValue = Token
WHERE desktopTokens.AssignedUsername = Username
END
ELSE
BEGIN
INSERT INTO desktopTokens
VALUES
(Username, Token)
END
I keep getting errors at LINE 2 and LINE 15 but have no idea why!
NOTE: Token and Username are SP variables
Try:
DELIMITER $$
CREATE PROCEDURE `insertNewToken`(
IN `Username` VARCHAR(150),
IN `Token` VARCHAR(500)
)
BEGIN
IF EXISTS(SELECT *
FROM desktopTokens
WHERE desktopTokens.AssignedUsername = Username) THEN
UPDATE desktopTokens
SET desktopTokens.TokenValue = Token
WHERE desktopTokens.AssignedUsername = Username
;
ELSE
INSERT INTO desktopTokens
VALUES
(Username, Token)
;
END IF;
END $$
DELIMITER ;
The below is my Stored Procedure(Routine) to check whether or not a user with Username(input) exists in the database.
Inside the database, I already have a user with Username - 'dev'.
However, when I ran the below routine, it returned me with res = 1, which I expected it to be -1.
I called the routine this way. Please correct me too if I am calling it the wrong way. I am really new to MySQL Routines.
CALL usp_GetUserValidation ('dev', #ErrorCode)
Can any MySQL Routine pros here enlighten me on this? Thank you in advance guys :)
DELIMITER $$
CREATE PROCEDURE usp_GetUserValidation(IN `#Username` VARCHAR(255), OUT `#ErrorCode` INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'To validate user login'
BEGIN
IF EXISTS
(SELECT UserID
FROM mt_User
WHERE UserName = #Username)
THEN
SET #ErrorCode = -1;
ELSE
SET #ErrorCode = 1;
END IF;
SELECT #ErrorCode AS res;
END$$
DELIMITER ;
It was simply your naming conventions for the parameters. It is finicky and does not like User Variable # signs in them.
You are just testing I can see, as you are returning both a resultset with the info and the OUT variable.
drop procedure if exists usp_GetUserValidation;
DELIMITER $$
CREATE PROCEDURE usp_GetUserValidation(IN pUsername VARCHAR(255), OUT pErrorCode INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'To validate user login'
BEGIN
IF EXISTS
(SELECT UserID
FROM mt_User
WHERE UserName = pUsername)
THEN
SET pErrorCode = -1;
ELSE
SET pErrorCode = 1;
END IF;
SELECT pErrorCode AS res;
END$$
DELIMITER ;
Schema:
-- drop table if exists mt_user;
create table mt_User
( UserID int auto_increment primary key,
UserName varchar(100) not null,
unique key(UserName)
);
insert mt_User(UserName) values ('dev');
select * from mt_User;
Test:
set #var1:=-4;
call usp_GetUserValidation('dev',#var1);
-- returns (-1) ---- Yea, we like that
select #var1;
-- (-1)
set #var1:=-4;
call usp_GetUserValidation('dev222',#var1);
-- returns 1 ---- Yea, we like that
select #var1;
-- 1
I have a stored function in MySQL and it works partially.
DELIMITER $$
DROP FUNCTION IF EXISTS `getsubdomain`$$
CREATE FUNCTION getsubdomain(page_id int(11))
RETURNS CHAR(255)
DETERMINISTIC
READS SQL DATA
SQL SECURITY INVOKER
BEGIN
declare current_p_id int(11);
declare current_p_parent_id int(11);
declare current_p_address_type char(255);
declare current_p_adress char(255);
SET current_p_id = page_id;
WHILE (current_p_id) <> 0
DO
select p_parent_id, p_address_type, p_adress from opu_pages where p_id = current_p_id into current_p_parent_id, current_p_address_type, current_p_adress;
IF current_p_address_type <> ''
THEN
IF current_p_address_type = 'subdomain'
THEN
RETURN current_p_adress;
ELSE
SET current_p_id = current_p_parent_id;
END IF;
ELSE
RETURN NULL;
END IF;
END WHILE;
RETURN NULL;
END$$
DELIMITER ;
If I call in query SELECT getsubdomain(p_id) FROM opu_pages; it works Ok. But if I call it in SELECT * FROM opu_pages WHERE getsubdomain(p_id)='library'; the database is collapsed and freezing.
Query and function work with one table.
What did I do wrong?
I thought that it can be caused by the table format MyISAM. But I can't change it to InnoDB because I use FULLTEXTFORMAT fields in this table.
Table opu_pages (MyISAM) scheme
p_id INT
p_parent_id INT
p_address_type ENUM (path, subdomain)
p_adress VARCHAR
Based on your post I would say that your code is entering an infinite loop for some of your input parameters.
In particular the case where p_id = p_parent_id in the opu_pages table and the current_p_address_type = 'subdomain'
I'm trying to make a routine that first checks a users password, if it's correct it shall return some values from a different table or change some values in a row.
Is this even possible without making two queries that you handle in PHP? First call for the password, check if its correct then allow the user to make the name change.
Here an example of getting the Rows in User with email and password.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `get_user_info`(
IN in_Email VARCHAR(45),
IN in_Pass VARCHAR(45)
)
BEGIN
SELECT * FROM User WHERE Email = in_Email AND Pass = in_Pass;
END
And this is what Ive got so far:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `change_pass`(
in_Email VARCHAR(45),
in_PassOld VARCHAR(45),
in_PassNew VARCHAR(45)
)
BEGIN
SET #PassOld = (SELECT Pass From User WHERE Email = in_Email);
IF(#PassOld = in_PassOld) THEN
UPDATE User SET Pass = in_PassNew WHERE Email = in_Email;
END IF;
ENDND IF;
END
Thanks for all the help!
You should really hash those passwords, use the following code
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `change_pass`(
in_Email VARCHAR(45),
in_PassOld VARCHAR(45),
in_PassNew VARCHAR(45)
)
BEGIN
DECLARE KnowsOldPassword INTEGER;
SELECT count(*) INTO KnowsOldPassword
FROM User
WHERE Email = in_Email AND passhash = SHA2(CONCAT(salt, in_PassOld),512);
IF (KnowsOldPassword > 0) THEN
UPDATE User
SET Passhash = SHA2(CONCAT(salt, inPassNew),512)
WHERE Email = in_Email;
END IF;
END $$
DELIMITER ;
The salt is an extra field in table user that is more or less random, but does not need to be secret. It serves to defeat rainbow tables.
You can set salt to a short string char(10) or randomish data. e.g.
salt = ROUND(RAND(unix_timestamp(now())*9999999999);
You don't need to update the salt, just generate it once and then store it.
For more on this issue see:
Salting my hashes with PHP and MySQL
How should I ethically approach user password storage for later plaintext retrieval?
A comment on your code
IF(#PassOld == in_PassOld) THEN //incorrect
IF(#PassOld = in_PassOld) THEN //correct, SQL <> PHP :-)