The following code works fine when put it outside a function and return 1 if it exists at the table.
SET #Result = (SELECT (
CASE WHEN NOT EXISTS(SELECT 1 FROM `Member` WHERE Username = 'username') THEN 10
ELSE 1
END) r);
SELECT #Result;
But it returns 10 when I am passing the value 'username' to a function like below
CREATE DEFINER=`root`#`localhost` FUNCTION `FN_CheckUsername`(
Username VARCHAR(128)
) RETURNS int
READS SQL DATA
BEGIN
SET #Result = (SELECT (
CASE WHEN NOT EXISTS(SELECT 1 FROM `Member` WHERE Username = Username) THEN 10
ELSE 1
END) r);
RETURN #Result;
END
Please try naming your username parameter to the FN_CheckUsername function something other than Username:
CREATE DEFINER=`root`#`localhost` FUNCTION `FN_CheckUsername`(uname VARCHAR(128))
RETURNS int
READS SQL DATA
BEGIN
SET #Result = (SELECT (
CASE WHEN NOT EXISTS(SELECT 1 FROM `Member` WHERE Username = uname)
THEN 10 ELSE 1 END) r);
RETURN #Result;
END
The parameter and column name could be masking each other, which would result in the exists clause always being true.
Related
My stored procedure always returns 0. I tried unique data and duplicated but the insert is done with success but the return value is always the same #new_identity = 0
CREATE PROCEDURE [dbo].[spAddAuthor]
#Author tyAuthor READONLY,
#new_identity INT = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
-- check if the author exists
IF NOT EXISTS (SELECT Id_Author FROM dbo.Authors
WHERE (dbo.Authors.Username = (SELECT Username FROM #Author)
OR dbo.Authors.phone = (SELECT phone FROM #Author)
OR dbo.Authors.email = (SELECT email FROM #Author)))
BEGIN
INSERT INTO dbo.Authors (Username, sexe, email, phone, address)
SELECT [Username], [sexe], [email], [phone], [address]
FROM #Author
-- output the new row
SELECT #new_identity = ##IDENTITY;
END
ELSE
BEGIN
-- get the author Id if already exists
SELECT #new_identity = (SELECT TOP 1 Id_Author
FROM dbo.Authors
WHERE (dbo.Authors.Username = (SELECT Username FROM #Author)
OR dbo.Authors.phone = (SELECT phone FROM #Author)
OR dbo.Authors.email = (SELECT email FROM #Author)))
END
END
I found that in the declaration of the parameters I put null beside the output and that what caused the problem.
#new_identity INT = NULL OUTPUT
but I don't understand why, I thought the 'null' was like the default value, or when you try to make the parameter optional you add null as default value.
can someone explain, please?
I have this sql query:
CREATE DEFINER=`root`#`localhost` FUNCTION `user_login_fn`(username varchar(32),pass varchar(128),actual_user int) RETURNS tinyint(1)
BEGIN
declare compareResult boolean;
declare user_id int;
if (select EXISTS(SELECT * FROM `user` WHERE `username`= username and `password` = sha2(pass, 512) and `status`='A')) THEN
SELECT id_user into user_id FROM `user` WHERE `username`= username and `password` = sha2(pass, 512) and `status`='A';
SET compareResult = register_insert_fn(actual_user, 5, Concat("Login user with ID: ", user_id));
return true;
else
SELECT id_user into user_id FROM `user` WHERE `username`= username;
SET compareResult = register_insert_fn(actual_user, 5, Concat("Failed login user with ID: ", user_id));
return false;
END IF;
END
The problem is always returns TRUE, even if i pass a null parameters.
I test the Select stament like this:
select EXISTS(SELECT * FROM `user` WHERE `username`= 'prueba' and `password` = sha2('123', 512) and `status`='A')
And work fine, but in the function always return True or 1.
The function returns either true or false because in the true branch of the if the code returns true, while in the else branch the code returns false. There are no other return values. If you would like the function to return some other values, then you need to change the implemented logic and make sure that other values are also returned.
I'm trying to find if the user has been allotted shares using mySql query. I have those queries in a function and it return 'No' all the time. However If I run the following queries at mySql command prompt I get 'Yes'. I have been breaking my head over this.. Very silly though.. Not able able to crack it. Any help would be appreciated. Thx!
//This returns 0 because the employee has been allotted shared now
//THIS IS THE MOST RECENT RECORD
SELECT ISNULL(NewEquityShares) INTO #PRESENT FROM System_Users_Share_Allotment_Info WHERE UserID = 'xyz' AND MostRecentRecord = 'Yes';
//This returns 1 because the employee was not allotted shared before
//THIS IS ONE RECORD BEFORE THE MOST RECENT RECORD
SELECT ISNULL(NewEquityShares) INTO #PREVIOUSLY FROM System_Users_Share_Allotment_Info WHERE UserID = 'xyz' AND MostRecentRecord = 'No';
//
SELECT IF ( #PRESENT = 0 AND #PREVIOUSLY = 1,'Yes','No');
mySQL Function:
DELIMITER $$
CREATE FUNCTION `fn_isNewSharesAlloted`(UserID VARCHAR(36)) RETURNS VARCHAR(3) CHARSET utf8
BEGIN
DECLARE strResponse VARCHAR(3) DEFAULT NULL;
DECLARE strUserID VARCHAR(36) DEFAULT NULL;
SET strUserID = UserID;
-- This returns 0 because the employee has been allotted shared now
SELECT ISNULL(NewEquityShares) INTO #PRESENT FROM System_Users_Share_Allotment_Info WHERE UserID = strUserID AND MostRecentRecord = 'Yes';
-- This returns 1 because the employee was not allotted shared before
SELECT ISNULL(NewEquityShares) INTO #PREVIOUSLY FROM System_Users_Share_Allotment_Info WHERE UserID = strUserID AND MostRecentRecord = 'No';
SELECT IF ( #PRESENT = 0 AND #PREVIOUSLY = 1,'Yes','No') INTO strResponse;
RETURN strResponse;
END$$
DELIMITER ;
When i run this code, it gives me error. From this code, there's several task to do:
(1) update tble customer by setting the address to '90 TYT' if c_id= 1
(2) view order_no,status,c_id,item_total remarks.
(3) if item_total 0, then update table order_status by setting remarks = 'UNAVAILABLE', else select order_no,status,item_total,remarks where status = 'waiting'.
Please help me fix the error. I'm new to SQL.
#drop procedure if exists usp_GetAnything;
delimiter //
create procedure usp_GetAnything()
begin
select c_id,lname,address,city
from customer;
update customer
set address = '90 TYT'
where c_id = 1;
select o.order_no,o.o_status,c.c_id,o.item_total,o.remarks
from customer c, order_status o
where c.c_id=o.c_id;
if (o.item_total > 0) then
update order_status o
set remarks = 'UNAVAILABLE'
where order_no > '123';
else
select order_no,o_status,item_total,remarks
from order_status
where o_status = 'waiting';
end if;
end
It's failing on the line:
if (o.item_total > 0)
o is unidentified outside of the previous select clause including all the selected variables.
In order to use the results that returned from the previous select you should select ... INTO...
(select the result arguments into declared local variables).
You can find here the following example:
DELIMITER //
CREATE PROCEDURE `proc_WHILE` (IN param1 INT)
BEGIN
DECLARE variable1, variable2 INT;
SET variable1 = 0;
WHILE variable1 < param1 DO
INSERT INTO table1 VALUES (param1);
SELECT COUNT(*) INTO variable2 FROM table1;
SET variable1 = variable1 + 1;
END WHILE;
END //
You can see that variable1 and variable2 are declared in the beginning of the procedure and later on used with select ... INTO ....
I am working Login Authentication with Stored Procedures in MySQL Database.
Below is the code, i wrote but its not working. Let me know, what is wrong.
I have below questions
How to check, whether CURSOR is empty or null
Is there any way, we write the procedure.
What I am doing..
Taking two input parameters and two parameters for ouput.
Check if the user or password is not valid, stored those values in OUT parameters
SELECT 'Invalid username and password', 'null' INTO oMessage, oUserID;
If user and password in valid, but isActive column is 0 then
SELECT 'Inactive account', 'null' INTO oMessage, oUserID;
If success,
SELECT 'Success', v_UserID INTO oMessage, oUserID;
SQL Code
DELIMITER $$
USE `acl`$$
CREATE
DEFINER = `FreeUser`#`localhost`
PROCEDURE `acl`.`checkAuthenticationTwo`(
IN iUsername VARCHAR(50),
IN iPassword VARCHAR(50),
OUT oMessage VARCHAR(50),
OUT oUserID INT
)
BEGIN
DECLARE v_isActive INT;
DECLARE v_UserID INT;
DECLARE v_count INT;
DECLARE cur1 CURSOR FOR SELECT UserID, IsActive FROM m_users WHERE (LoginName = TRIM(iUsername) OR Email = TRIM(iUsername)) AND `Password` = iPassword;
OPEN cur1;
SET v_count = (SELECT FOUND_ROWS());
IF (v_count > 0)
FETCH cur1 INTO v_UserID, v_isActive;
IF (v_isActive = 0) THEN
SELECT 'Inactive account', 'null' INTO oMessage, oUserID;
ELSE
SELECT 'Success', v_UserID INTO oMessage, oUserID;
END IF;
ELSE
SELECT 'Invalid username and password', 'null' INTO oMessage, oUserID;
END IF;
END$$
DELIMITER ;
You definitely don't need CURSORs for that; use plain simple SELECT. A more concise version of your SP might look like
DELIMITER $$
CREATE DEFINER = `FreeUser`#`localhost` PROCEDURE `acl`.`checkAuthenticationTwo`
(
IN iUsername VARCHAR(50),
IN iPassword VARCHAR(50),
OUT oMessage VARCHAR(50),
OUT oUserID INT
)
BEGIN
SELECT CASE WHEN IsActive = 0 THEN 'Inactive account' ELSE 'Success' END,
CASE WHEN IsActive = 0 THEN NULL ELSE UserID END
INTO oMessage, oUserID
FROM m_users
WHERE (LoginName = TRIM(iUsername)
OR Email = TRIM(iUsername))
AND `Password` = iPassword
LIMIT 1; -- you better protect yourself from duplicates
SET oMessage = IFNULL(oMessage, 'Invalid username and password');
END$$
DELIMITER ;
What it does it tries to select a row where username or email equals to iUsername and password equals to iPassword and outputs two values to output variables. Along the way it uses CASE to look at isActive value. If it's 0 then sets a message to 'Inactive' and NULL for userid. Otherwise it returns 'Success' message and real userid that has been found. Now, if a user has not been found both variables will be set to NULL. We can leverage that and use IFNULL() function to detect that fact and set a message to 'Invalid username and password'.
Here is SQLFiddle demo
Personally I'd go further and simplify it a bit more and make it a one-statement SP with the following interface:
Returns:
userid (which is > 0) if a user with username and password if found
0 - username and(or) password incorrect
-1 - a user is inactive
The idea is that it's a presentation layer's task to produce appropriate messages for the user and not scatter all those message literals across data layer.
CREATE DEFINER = `FreeUser`#`localhost` PROCEDURE `acl`.`checkAuthenticationThree`
(
IN iUsername VARCHAR(50),
IN iPassword VARCHAR(50),
OUT oUserID INT
)
SET oUserID = IFNULL(
(
SELECT CASE WHEN IsActive = 0 THEN -1 ELSE UserID END
FROM m_users
WHERE (LoginName = TRIM(iUsername)
OR Email = TRIM(iUsername))
AND `Password` = iPassword
LIMIT 1 -- you better protect yourself from duplicates
), 0);
Here is SQLFiddle demo