Count is not being stored in variable in MySQL Trigger - mysql

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?

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 ;

MySQL : Stored procedure returns null for last_insert_id

I'm facing a problem with SP in mySql when I want to select my identete it gives always null as value.
DELIMITER $$
CREATE PROCEDURE insert_details_facture(IN typefacture INT,
IN codeactivite VARCHAR(255),
IN qte INT,
IN pu DOUBLE,
IN unite VARCHAR(255),
IN montant DOUBLE)
BEGIN
DECLARE identete INT;
SELECT identete = numfacture FROM entetefacture WHERE numfacture = LAST_INSERT_ID();
END$$
When I execute this it gives identite = numfacture as column's name and null as value.
CALL insert_details_facture(10,'l',10,12,'l',20)
Check Here.
With no argument, LAST_INSERT_ID() returns a BIGINT UNSIGNED (64-bit) value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement.
so result you are getting is obvious.
to get last record you can use limit.
SET identete = (SELECT numfacture FROM entetefacture ORDER BY id DESC LIMIT 1);
LAST_INSERT_ID() is not guaranteed to have a valid value. For instance, the documentation states:
If the previous statement returned an error, the value of
LAST_INSERT_ID() is undefined. For transactional tables, if the
statement is rolled back due to an error, the value of
LAST_INSERT_ID() is left undefined.
Similarly, if there have been no database changes for the current session, then the value will be undefined.
Also, if you want to set the value, then use := in a select:
SELECT identete := numfacture
FROM entetefacture
WHERE numfacture = LAST_INSERT_ID();
Why not just get the last row in the table using limit?
SET identete = (SELECT numfacture FROM entetefacture ORDER BY id LIMIT 1);

MySQL Stored Proc Variable returns NULL

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

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.

SELECT...INTO returns null in Stored Procedure

This function:
CREATE FUNCTION `GetCardID`(numId INT) RETURNS int(11)
DETERMINISTIC
BEGIN
DECLARE retcard INT(11);
SELECT id
INTO retcard
FROM cards
WHERE `number` = numId
AND enabled = 1
LIMIT 1;
RETURN retcard;
END
Always returns null even when the query:
SELECT id FROM cards WHERE `number`=<Insert Value Here> AND ENABLED = 1 LIMIT 1;
returns a valid value for the same value used in and the function parameter.
For instance:
SELECT id FROM cards WHERE number=12345 AND ENABLED = 1 LIMIT 1;
-- returns an id, while
GetCardId(12345);
-- returns null
Any ideas what I'm missing here? I consider myself quite skilled at SQL, but a little green on SP's.
How big is the data that you are taking into your function? Is it possible that the number is larger than what will fit into an INT?
Christopher here is your function. Try this and it should work:
CREATE FUNCTION [dbo].[GetCardID]
(
#Num_ID INT
)
RETURNS int
AS
BEGIN
declare #retcard int
select Top 1 #retcard = id
FROM cards
where number = #num_Id
AND enabled = 1
return #retcard
END
Always returns NULL:
Get rid of DETERMINISTIC clause in Procedure definition. MySQL caches the responses from such procedure or functions.
Excerpt from MySQL:
A routine is considered “deterministic” if it always produces the same
result for the same input parameters, and “not deterministic”
otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC is given in
the routine definition, the default is NOT DETERMINISTIC. To declare
that a function is deterministic, you must specify DETERMINISTIC
explicitly
MySQL 5.5 - Creating Procedure or Function