MySQL Stored Proc Variable returns NULL - mysql

I have a stored proc that is setting one of the variables to NULL, though the query returns results.
Here is the SP:
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `test`(IN CLIENT_ID INT)
BEGIN
DECLARE BEGIN_RANGE INT UNSIGNED DEFAULT 0;
select client_id into #CLIENT_ID3 from clients where
client_id = CLIENT_ID limit 1;
SET #BEGIN_RANGE = (select var_value from counter where var_name =
'latest_report_id_summarized' limit 1);
SELECT latest_invoice_id into #LATEST_INVOICE_ID from
SQL_AuditPro.clients where client_id = CLIENT_ID;
END
when I run the sp, then select the results :
select #CLIENT_ID3,#BEGIN_RANGE,#LATEST_INVOICE_ID;
I get :
12345,2342342234,NULL
I have also tried:
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `test`(IN CLIENT_ID INT)
BEGIN
DECLARE BEGIN_RANGE INT UNSIGNED DEFAULT 0;
select client_id into #CLIENT_ID3 from clients
where client_id = CLIENT_ID limit 1;
SET #BEGIN_RANGE = (select var_value from counter where var_name =
'latest_report_id_summarized' limit 1);
SET #LATEST_INVOICE_ID = (SELECT latest_invoice_id from
SQL_AuditPro.clients where client_id = CLIENT_ID);
END
Same result. Obviously I don't need to SET #CLIENT_ID3 it was just in there for testing. Any ideas why this won't set the variable? When I run this query by itself I get a result, and if I run :
SELECT latest_invoice_id into #LATEST_INVOICE_ID from
SQL_AuditPro.clients where client_id = 12345;
select #LATEST_INVOICE_ID;
I get :
2342342234
I have tried declaring the variable, not declaring it, and it just seems like this variable seems to fall out of scope after the SP completes, yet the other two don't.
Thanks for any help you may be able to provide.

select client_id into #CLIENT_ID3 from clients where client_id = CLIENT_ID limit 1;
^---- missing #
SET #LATEST_INVOICE_ID = (SELECT [..snip..] where client_id = CLIENT_ID);
^--missing # as well
As written, both'll be intepreted as a self-equality test, e.g. where 1 = 1. There's no way for mysql to know that the client_id on EITHER side of the = is supposed to be the parameter you passed in to the stored proc, so both client_id will be treated as field names.
Since the second query is likely to return MULTIPLE rows of data, and you're trying to assign that result into a single variable, you'll get NULL as the result.

When you have defined arguments names to match with one or more of a table columns, then in your SQL statements you must use column qualifiers to differentiate with argument names. Otherwise, they will be treated and replaced as and by argument values;
See SQL Fiddle Example
In your case, as the condition client_id = CLIENT_ID was causing to (possibly) fetch multiple records, they are not assignable to a variable of non cursor type. Hence a NULL, the default value for user defined variables, was returned.
Change your procedure body as below:
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `test`(IN CLIENT_ID INT)
BEGIN
DECLARE BEGIN_RANGE INT UNSIGNED DEFAULT 0;
select c.client_id into #CLIENT_ID3
from clients c
where c.client_id = CLIENT_ID limit 1;
SET #BEGIN_RANGE =
(select var_value
from counter
where var_name = 'latest_report_id_summarized' limit 1);
SET #LATEST_INVOICE_ID =
(SELECT c.latest_invoice_id
from SQL_AuditPro.clients c
where c.client_id = CLIENT_ID);
END

Related

How to return boolean based on number of records in database?

Here's what I've tried. My host is returning an error, "Sorry an unexpected error happened!" .
I want it to return true if there is at least 1 record with combination pdriver_id, ptruck_number, and pdate.
DELIMITER %%
CREATE FUNCTION DriverActiveInTruckByDate(
pdriver_id INT,
ptruck_number INT,
pdate DATETIME
)
RETURNS boolean
DETERMINISTIC
BEGIN
DECLARE inDB INT DEFAULT 0;
SET inDB =
SELECT IF(COUNT(*) >= 1,1,0)
FROM
truck_timeline tl
WHERE 1=1
AND tl.driver_id = pdriver_id
AND tl.truck_number = ptruck_number
AND ((pdate BETWEEN tl.begin_date AND tl.end_date) OR (pdate >= tl.begin_date AND tl.end_date IS NULL))
END
%%
DELIMITER ;
Several fixes are needed:
The function is not DETERMINISTIC. This means the result will always be the same given the same inputs. In your case, the result may be different depending on the data in your truck_timeline table. So I would suggest using READS SQL DATA.
If you use SET variable = SELECT... you must put the SELECT in a subquery:
SET inDB = (SELECT ...);
The current manual recommends using SELECT ... INTO variable instead of SET. See https://dev.mysql.com/doc/refman/8.0/en/select-into.html
The INTO position at the end of the statement is supported as of MySQL 8.0.20, and is the preferred position.
SELECT ... INTO inDB;
The function you show doesn't have a RETURN statement. See https://dev.mysql.com/doc/refman/8.0/en/return.html
There must be at least one RETURN statement in a stored function.
Your Full Code could be like this:
DELIMITER %%
CREATE FUNCTION DriverActiveInTruckByDate(
pdriver_id INT,
ptruck_number INT,
pdate DATETIME
)
RETURNS boolean
DETERMINISTIC
BEGIN
DECLARE inDB INT DEFAULT 0;
SET inDB =
(SELECT IF(COUNT(*) >= 1,1,0)
FROM
truck_timeline tl
WHERE 1=1
AND tl.driver_id = pdriver_id
AND tl.truck_number = ptruck_number
AND ((pdate BETWEEN tl.begin_date AND tl.end_date) OR (pdate >= tl.begin_date AND tl.end_date IS NULL))
);
END %%
DELIMITER ;

How stored procedure output instead of rows count?

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?

Count is not being stored in variable in MySQL Trigger

I am getting very weird issue in MySQL trigger.
Count value is not being stored into variable. Below is my code.
DECLARE user_cnt INTEGER;
DECLARE company_id INTEGER;
...
SELECT IF(COUNT(id) > 0, COUNT(id), -1) INTO #user_cnt
FROM user
WHERE user_type = 'admin' AND `status` = 'enabled' AND company_id = #company_id;
Whereas #company_id has a valid integer value.
Here #user_cnt is always returning -1 as value.
What can be done? Am I missing something?

MySql Stored Proc - Select query returns null if using where clause not included in select list?

I have a proc that simply contains the following:
SELECT Col1, Col2 FROM table WHERE Id = 1;
This always returns null values. If I change the statement to:
SELECT Id, Col1, Cold2 FROM table WHERE Id = 1;
The row gets returned as expected. Does mySql procs demand that the where clause columns appear in the select list? It doesn't have this behaviour when running the SQL directly in phpMyAdmin.
Here's the code in question:
CREATE PROCEDURE sp_player_login
(
IN
userGraphId INT(11),
authToken TEXT
)
BEGIN
DECLARE playerId INT;
DECLARE newPlayer BOOLEAN DEFAULT FALSE;
SELECT Id INTO playerId FROM player WHERE FacebookGraphId = userGraphId;
If playerId IS NULL THEN
-- Create the player.
SET newPlayer = TRUE;
-- Get new player defaults.
SELECT NewPlayerTurns, NewPlayerMoney, NewPlayerMorale, NewPlayerMissilePower FROM defaults WHERE Id = 1;
END IF;
END #
The second SELECT NewPlayerTurns... is the one that returns null values if I don't specify the Id column in the select clause. If I remove the first SELECT Id INTO ...the second query works without the Id in the select clause...? confused

Not getting null values when no data available

In my stored procedure, I declared #account_id, which sets as per the serial number.
if there are no matching records for the SERIAL_NUMBER, #account_id is not getting NULL value. WHERE condition is mentioned in section B.
So, when I pass invalid serial number, still records are coming which shouldn't. Please guide me to solve this issue.
Section A:
DECLARE #Account_ID INT
SELECT #Account_ID = ACCOUNT_ID FROM T_ACCOUNT WITH (NOLOCK) WHERE SERIAL_NUMBER = #Serial_Number
Section B:
WHERE
(#Account_ID IS NULL OR Acct.ACCOUNT_ID = #Account_ID)
Try this,
Section A:
DECLARE #Account_ID INT
SELECT #Account_ID = ACCOUNT_ID FROM T_ACCOUNT WITH (NOLOCK) WHERE SERIAL_NUMBER = #Serial_Number
Section B:
WHERE
Acct.ACCOUNT_ID = #Account_ID
In your query you are using OR condition where your query return all the records even if the variable #AccountId is NULL.