Weird Return value: mySQL - mysql

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 ;

Related

Stored procedure not updating table

Hi still trying to debug this issue so I've stripped things down to the bare basics, following the PHP manual.
SP:
DROP IF EXISTS(`login_validator`);
CREATE PROCEDURE `login_validator` (
IN Username VARCHAR(75),
OUT ReturnValue VARCHAR(1000)
)
BEGIN
END
PHP call:
$SP1SQL = 'call login_validator(:Username, :ReturnValue)';
$Stmt = $DBConnection->Prepare($SP1SQL);
$Stmt->BindParam('Username', $Name, PDO::PARAM_STR);
$Return = null;
$Stmt->BindParam(':ReturnValue', $Return, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 1000);
$Stmt->Execute();
I get:
SQLSTATE[42000]: Syntax error or access violation: 1414 OUT or INOUT argument 2 for routine myDB.login_validator is not a variable or NEW pseudo-variable in BEFORE trigger
Everything I read says this should work...
I'm trying to get this sp to update the user_login_attempts tbl if the user enters the wrong username and return some values to the calling script.
When called The SP runs without errors and returns only one value
I expect it's some flaw in my logic, but I can't spot it...
I'm calling it like this
$SP1 = 'call login_authentication(:Username, :LoginIP, :IPGeoLocation, #ReturnStatus)';
// binding variables
// execute
If I vardump
$SP1RS = $Stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($SP1RS);
I get back the correct value of v_Username and all the other values are set to SP's default declarations
If I call it the usual way
$SP1 = 'call login_authentication(:Username, :LoginIP, :IPGeoLocation, :ReturnStatus)';
I get the error MySQL :: Error 1414 OUT or INOUT argument 4 for routine login_authentication is not a variable or NEW pseudo-variable in BEFORE trigger.
CREATE PROCEDURE `login_authentication`(
IN `v_Username` VARCHAR(75),
IN `v_LoginIP` VARBINARY(16),
IN `v_IPGeoLocation` VARCHAR(30),
INOUT `v_ReturnStatus` VARCHAR(1000)
)
BEGIN
DECLARE v_QueryDB BOOLEAN DEFAULT 1;
DECLARE v_Error BOOLEAN DEFAULT 0;
DECLARE v_ErrorMsg VARCHAR(250) DEFAULT null;
DECLARE v_Attempts TINYINT(1) DEFAULT 0;
DECLARE v_LastAttempt TIMESTAMP DEFAULT null;
DECLARE v_Hash VARBINARY(256) DEFAULT null;
# DECLARE v_LoginIP VARBINARY(16) DEFAULT INET_ATON(v_LoginIP);
SET v_LoginIP = INET_ATON(v_LoginIP);
# Check if user has any previous unsuccessful login attempts
IF EXISTS(SELECT Username FROM users_login_attempts WHERE Username = v_Username AND Attempts > 4) THEN
SELECT Attempts INTO v_Attempts FROM users_login_attempts WHERE Username = v_Username;
SELECT LastAttempt INTO v_LastAttempt FROM users_login_attempts WHERE Username = v_Username; # Get time of last users last login
# User has been timed out
IF (v_Attempts = 5 AND v_LastAttempt > (NOW() - INTERVAL 10 minute)) THEN
SET v_Error = 1;
SET v_ErrorMsg = 'Sorry, you are still timed out!';
SET v_QueryDB = 0;
END IF;
# other conditions
END IF;
# Query DB for valid username
IF (v_QueryDB = 1) THEN
# Query DB for password hash
IF EXISTS(SELECT Password FROM users WHERE(Email = v_Username || Mobile = v_Username)) THEN
SELECT Password INTO v_Hash FROM users WHERE(Email = v_Username || Mobile = v_Username);
ELSE
# Username not found in DB
# Update user logins table with failed attempt if not already locked
IF (v_Attempts < 7) THEN
INSERT INTO users_login_attempts(
Username,
Attempts,
IPAddress,
IPGeoLocation)
VALUES(
v_Username,
v_Attempts,
v_LoginIP,
v_IPGeoLocation)
ON DUPLICATE KEY UPDATE
Attempts = Attempts +1,
IPAddress = VALUES(IPAddress),
IPGeoLocation = VALUES(IPGeoLocation);
# Update Attempts from DB
SELECT Attempts INTO v_Attempts FROM users_login_attempts WHERE Username = v_Username;
END IF;
END IF;
# Set error messages for failed login attempts
IF (v_Attempts > 0) THEN
SET v_ErrorMsg = 'The supplied credentials were not recognised'; # Default msg
IF (v_Attempts = 5) THEN
SET v_Error = 1;
SET v_ErrorMsg = 'Due to repeated failed login attempts, Your account has been temporarily locked for 10 minutes!';
END IF;
# more conditions
END IF;
END IF;
# set output result
IF (v_Hash != null) THEN
SELECT v_Hash AS PasswordHash;
ELSE
SELECT v_ErrorMsg AS ErrorMsg,
v_Attempts AS LoginAttempts,
INET_NTOA(v_LoginIP) AS IPAddress,
v_Username AS Username;
END IF;
END
check this line:
$Stmt->BindParam(':Username', $Name, PDO::PARAM_STR);
especially ':Username'

Parameter name conflict with column name in MySQL

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.

Calling stored procedure from nodejs return error

I'm studying NodeJS with expressjs and so far, so good, but I have this little issue: calling a stored procedure from Workbench everything runs OK, but same sentence (copy/paste) within express shows error from MySQL engine.
{
"desc_status": {
"code": "ER_BAD_NULL_ERROR",
"errno": 1048,
"sqlMessage": "Column 'id_color' cannot be null",
"sqlState": "23000",
"index": 0,
"sql": "CALL pinturas.add_inventory('101', '3');"
},
"code_status": 409
}
Here's my NodeJS call:
let sql = "CALL pinturas.add_inventory(101, 3);";
conn.query(sql, true, (err, filas) => {
if(err){
//next(err);
res.status(409).json({
desc_status: err,
code_status: 409,
});
return;
}
(...)
});
Call from Workbench
CALL `pinturas`.`add_inventory`('101', '3');
and finally, stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `add_inventory`(
IN _id_color INT(11),
IN _cant INT(11)
)
BEGIN
set #numRows = (select count(*) from stock_colores where id_pintura = 1 and id_color = #_id_color);
if #numRows > 0 then
set #oldCant = (select cant from stock_colores where id_pintura = 1 and id_color = #_id_color);
set #_stock_id = (select stock_id from stock_colores where id_pintura = 1 and id_color = #_id_color);
update stock_colores set cant = (_cant + #oldCant) where stock_id = #_stock_id;
else
insert into stock_colores (id_pintura, id_color, cant) values (1, #_id_color, _cant);
end if;
END
I appreciate any guidance. Cheers.
So guys, after a few checks and attempts, I managed to solve my problem, that actually was pretty simple and all entirely in my Stored Procedure script. I was calling parameters with # but actually those are for variables declared within the code, not input parameters.
Here's my updated code.
CREATE DEFINER=`root`#`localhost` PROCEDURE `add_inventory`(
IN _id_pintura INT(2),
IN _id_color INT(2),
IN _cant INT(2)
)
BEGIN
set #numRows = (select count(*) from stock_colores where id_pintura = _id_pintura and id_color = _id_color);
if #numRows > 0 then
set #oldCant = (select cant from stock_colores where id_pintura = _id_pintura and id_color = _id_color);
set #_stock_id = (select stock_id from stock_colores where id_pintura = _id_pintura and id_color = _id_color);
update stock_colores set cant = (_cant + #oldCant) where stock_id = #_stock_id;
else
insert into stock_colores (id_pintura, id_color, cant) values (_id_pintura, _id_color, _cant);
end if;
END

What is the error in mysql procedure I am Getting Error in my code is anyone

BEGIN
DECLARE i INT DEFAULT 0;
DECLARE J INT DEFAULT 0;
DECLARE msg varchar(255) DEFAULT null;
DECLARE msg1 varchar(255) DEFAULT null;
DECLARE s VARCHAR(255) DEFAULT null;
set i = select em_DOJ
from employee_master
where MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW());
set j = (select TIMESTAMPDIFF(year,i,now()));
set msg1 = 'Congrats';
set msg = concat(msg1, j, 'Years Completed');
INSERT INTO time_line( tl_name, tl_dob, tl_message)
select em_first_name, em_DOJ, msg
from employee_master;
end
Why am I getting errors for this code. My intention is to transfer data from one table to another and to calculate the year at the same time. I am getting the error in this line.
set i = select em_DOJ
from employee_master
where MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW());
Thanks For Solution.
You don't have a WHERE clause in the INSERT ... SELECT ... query, so it's selecting all rows from employee_master, and inserting a row into time_line for each of them with msg.
You don't need multiple queries. You should combine them all into a single SELECT so that the number of years in the message matches that employee.
INSERT INTO time_line (tl_name, tl_dob, tl_message)
SELECT em_first_name, em_DOJ,
CONCAT('Congrats on ', TIMESTAMPDIFF(year, em_DOJ, ,now()), ' Years Completed')
FROM employee_master
WHERE MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW());
You need to wrap the SELECT with braces:
set i = (select em_DOJ
from employee_master
where MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW()));
Additionally, this select does potentially return more than one result which would then cause an error.

mysql stored function simple login, extract int from set

this is my first mySQL stored-function 'cause i've always managed such things with php.
I want a function that checks if a user can log in my client-area.
I wrote the code above:
DELIMITER $$
CREATE FUNCTION `A05`.`login` (user VARCHAR(64),pass VARCHAR(64)) RETURNS INT
BEGIN
declare num_rows int;
declare id int;
SELECT (#num_rows:=COUNT(*)),(#id:=`Credential_id`) FROM `A05`.`Credentials` where `Credential_UserName` = user;
if num_rows = 0 then
-- user not present
return (-1);
end if;
-- user present, checking password
SELECT (#num_rows:=COUNT(*)),(#id:=`Credential_id`) FROM `A05`.`Credentials` where `Credential_id` = id AND `Credential_PASSWORD` = SHA1(pass);
if num_rows = 0 then
-- user presente, password incorrect
INSERT INTO `a05`.`Events` (
`Event_id` ,
`Event_RegistrationDate` ,
`Event_VariationDate` ,
`Event_State`,
`Event_Notes`,
`Event_SenderId`,
`Event_Type`
)
VALUES (
NULL , NOW(), NOW(), 'wp', NULL, id, 1
);
return (-2);
end if;
-- user present, password correct
UPDATE `A05`.`Credentials` SET `Credential_LastAccess`=NOW() where `Credential_id` = id;
INSERT INTO `a05`.`Events` (
`Event_id` ,
`Event_RegistrationDate` ,
`Event_VariationDate` ,
`Event_State`,
`Event_Notes`,
`Event_SenderId`,
`Event_Type`
)
VALUES (
NULL , NOW(), NOW(), 'ok', NULL, id, 0
);
return id;
END
I think that the syntax should be right except for the last statement return id cause i return a set instead of an integer.
The problem is that when i try to store this function on mysql i get this error:
Error 1415: Not allowed to return a result set from a function
Then i changed the last statement from 'return id' to 'return 0' for testing purpose but i keep getting the same error.
Probably is a newbie error cause it's the very first time for me on sql "advanced" scripting.
Thank you very much in advance!