I have a stored procedure in SQL server 2008. It takes an email as parameter and then looks up if the user linked to it has rights to access a mobile MVC 5 application. The stored procedure returns either a 1 or a 0. Here is the code for the stored procedure.
-- Add the parameters for the stored procedure here
#email varchar(128)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Check int
SELECT
#Check = (
SELECT P.MobileRights
FROM eMK_Person as P
WHERE P.ID = (SELECT FK_Person FROM eMK_contact WHERE eMK_Contact.Information = #Email)
)
IF (#Check is null) RETURN 0
RETURN (#Check)
END
GO
In the standard mvc5 code of the account controller I added a simple check on this stored procedure, if the outcome is 0 it should just return the view. Here is a the code that I added to the Login task action result:
var test = db.SP_MB_MobileRights(model.Email);
if (db.SP_MB_MobileRights(model.Email) == 0)
{
return View(model);
}
I have two test accounts. One that has the rights and one that does not. If I execute the stored procedure in the management studio with a query it works like it should, returning 0 for one and 1 for the other.
But when I debug the code the test variable always gets filled with -1.
Here is the code that MVC made for me when I added the stored procedure to the model.
public virtual int SP_MB_MobileRights(string email)
{
var emailParameter = email != null ?
new ObjectParameter("email", email) :
new ObjectParameter("email", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("SP_MB_MobileRights", emailParameter);
}
When I debug through it, I can clearly see that the emailParameter variable is filled with the email address:
If the procedure is meant to return a 1 or 0 try changing your procedure to:
AS
BEGIN
IF EXISTS (SELECT P.MobileRights FROM eMK_Person as P WHERE P.ID = (SELECT FK_Person FROM eMK_contact WHERE eMK_Contact.Information = #Email))
RETURN 1
ELSE
RETURN 0
END
You should also change your query to a JOIN rather then a sub query.
Something like:
SELECT P.MobileRights FROM eMK_Person as P
JOIN eMK_contact as C ON c.FK_Person = P.ID WHERE C.Information = #Email
Related
I'm creating a procedure where it needs to check the value of a column IsLoggedIn and send the outparameter with -1 if "IsLoggedIn" is 1 else it needs to send the user information.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_bh_loginverify1`(IN `user_email` VARCHAR(100), OUT `p_islogged` INT)
NO SQL
BEGIN
IF (EXISTS(select * FROM user_details WHERE user_email = user_email))
THEN
SET p_islogged = 1; SELECT 0;
END IF;
(select UD.user_id, UD.user_name, UD.password, UD.password_salt, UD.user_email, R.role_id as role, R.role_name as role_name from user_details UD
JOIN roles R on R.role_id = UD.role
where (UD.user_email = user_email OR UD.user_name = user_email));
END$$
DELIMITER ;
First of all, always name your procedure input parameters something different from the columns of your table. For example you do this:
IF (EXISTS(select * FROM user_details WHERE user_email = user_email))
How is MySQL supposed to know that user_email is the column in the table, but user_email is the procedure parameter of that name? It doesn't -- it assumes both are references to the column. It compares the column user_email to itself, which will return every row where the column is not NULL, because it's always true that user_email = user_email. In other words, that the column is equal to itself (unless it's NULL).
You shoudl name the procedure parameter something distinct from the column name:
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_bh_loginverify1`(IN `p_user_email` VARCHAR(100), OUT `p_islogged` INT)
You used NO SQL which means: "indicates that the routine contains no SQL statements." But that's not true, because you do have SQL statement in this procedure.
You should use:
READS SQL DATA
You said you want to return -1 in the OUT parameter, but you set 1. So you should set -1.
Next you mentioned "else it sends user information" which suggests you want that result set to be returned only conditionally. But your code returns that user information outside the IF/END IF block, so it happens regardless of the condition. You should use an ELSE block to do this.
Notice the use of p_user_email in the queries below, to make it distinct from user_email.
BEGIN
IF (EXISTS(select * FROM user_details WHERE user_email = p_user_email))
THEN
SET p_islogged = -1;
ELSE
SELECT UD.user_id, UD.user_name, UD.password, UD.password_salt, UD.user_email,
R.role_id as role, R.role_name as role_name
FROM user_details UD
JOIN roles R ON R.role_id = UD.role
WHERE UD.user_email = p_user_email OR UD.user_name = p_user_email;
END IF;
END
I don't think you need SELECT 0; at all. MySQL stored procedures can return no result set, or one result set, or multiple result sets.
I have two stored procs which i call from my laravel application.
My laravel application passes in a cID parameter which is then passed to the stored procedure as the "where clause". But it seems something is going astray and possibly my variables arent set up properly.
Also i know that laravel IS passing the correct cID to my stored proc because i enabled the logs for mysql to see if it was passing any params.
Also the stored procedure select statement runs fine as a query if i manually set the ClientID = '';
My stored proc sends ALL clients and cards to the view, totally ignoring the where clause.
Laravel code:
Route::get('/clients/{cID}', function ($cID) {
$details = DB::select('CALL sp_Details(' . DB::raw($cID) . ')');
$cards = DB::select('CALL sp_Cards(' . DB::raw($cID) . ')');
return view('client.show', compact('details','cards'));
});
Any my Stored Proc
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_Details`(IN cID int )
BEGIN
SET #ClientID = cID;
SELECT
ClientID,
Client_Name
FROM accounts
where #ClientID = cID;
END
Stored Proc #2
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_Cards`(cID int)
BEGIN
SET #ClientID = cID;
SELECT
ClientID,
Code
FROM cards
where cID = #ClientID;
END
You are using local variables like #ClientID and you are confusing it to column names, must change your code to avoid them and there is no necessary use the local variable:
CREATE PROCEDURE `sp_Details`(IN cID int )
BEGIN
SELECT
ClientID,
Client_Name
FROM accounts
where ClientID = cID;
END
The other proc:
CREATE PROCEDURE `sp_Cards`(cID int)
BEGIN
SELECT
ClientID,
Code
FROM cards
where ClientID = cID;
END
I have a stored procedure that returns a common query, I need to call it in several functions but some functions may call it through Period Id or others through Header Id, so far I would like to know how can I determine what param to use in order to retrive data properly, I have something like this implemented.
CREATE PROCEDURE dbo.GetTFDRecordInfo
#PeriodId int = null,
#HeaderId int = null
AS
BEGIN
SELECT
-- I have a lot more fields and joins here, that's why I need to get the statement in a single call through either period id or header id
*
From NT_CSRTNVPeriodInfo t
-- how can I make possible something like shown above, can I use a "Case When"?
Where (
/*
if #PeriodId is null
Where t.HeaderId = #HeaderId
if #HeaderId is null
Where t.PeriodId = #PeriodId
*/
)
END
GO
-- swtich between params
Exec NT_CSRTNVPeriodInfo null, 2654
Exec NT_CSRTNVPeriodInfo 196, null
This is the answer:
CREATE PROCEDURE dbo.GetTFDRecordInfo
#PeriodId int = null,
#HeaderId int = null
AS
BEGIN
SELECT
-- I have a lot more fields and joins here, that's why I need to get the statement in a single call through either period id or header id
*
From NT_CSRTNVPeriodInfo t
-- how can I make possible something like shown above, can I use a "Case When"?
Where ((#PeriodId IS NULL) or (t.PeriodId = #PeriodId))
And ((#HeaderId IS NULL) or (t.HeaderId = #HeaderId))
END
GO
You have to use conditional OR to check NULLs, if param is set, the second condition is checked, if not, the procedure will consider always true the statement and go to the next.
It's again PHPMyAdmin... I try to run query on two tables - cards and ownerships (which list all players with the cards they own). And I'd like to create a function which will return (if given the name) the total amount of that card on the market. I defined this in the following way:
CREATE FUNCTION get_card_overall_count (_name TEXT)
RETURNS INT
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE res INT;
SET res = SELECT SUM(`ownerships`.`amount`)
FROM `ownerships` JOIN `cards` ON `ownerships`.`card_ID` = `cards`.`ID`
WHERE `cards`.`name` = _name
GROUP BY `name`;
RETURN res;
END//
The SET syntax wants the right hand side to be a scalar, not a query, but you can convince it to run a scalar subquery:
SET res = (SELECT SUM(`ownerships`.`amount`)
FROM `ownerships` JOIN `cards` ON `ownerships`.`card_ID` = `cards`.`ID`
WHERE `cards`.`name` = _name
GROUP BY `name`);
Does anybody know if this is allowed?
IF CALL GET_RIGHT_NODE(edge) = 15
THEN
SELECT "IT WORKS";
I'm getting an error on this syntax, is it possible any other way?
The return values from stored procedures should be captured in OUT paramters (whereas those from user defined functions can be captured as #returnValue = function()).
So, your GET_RIGHT_NODE should take an OUT parameter and set it to the return value.
CREATE PROCEDURE GET_RIGHT_NODE
(
#edge INT,
#returnValue INT OUTPUT
)
AS
-- Definition of the proc.
then you would call the procedure as follows:
DECLARE #returnValue INT
CALL GET_RIGHT_NODE(#edge, #returnValue)
IF (#returnValue = 15)
THEN
SELECT 'IT WORKS'