How to differentiate between local variable and field name? - mysql

I have a stored procedure in MySQL (actually MariaDB 10.3), and I have a variable declared, let's call it name.
Later in my procedure, I want to use my name variable to filter a table. This table has a field also called name.
How can I use my name variable to filter my table on the name field?
Here is an example:
DELIMITER //
CREATE PROCEDURE doSomething()
BEGIN
-- Declare a variable and load a value into it
DECLARE name CHAR(6) DEFAULT NULL;
SELECT value FROM tableA WHERE id = 6 INTO name;
-- Use the variable in a query
SELECT * FROM tableB WHERE name = name;
END; //
DELIMITER ;
CALL doSomething();
As you can see, I load the name variable with a value from tableA. Then I want to filter tableB using this name variable. Obviously, WHERE name = name doesn't work.
How do I refer to my variable alongside the field name? Something like:
WHERE name = _variables_.name

The docs are clear that locally declared variables take scope precedence over column names. So, with respect, your SP suffers from ambiguity. It's confusing and wrong.
But if you qualify your column name with a table name in your SELECT, it works. Like so.
SELECT * FROM tableB WHERE tableB.name = name;

never use variables that are the same as column names mysql gets confused
DELIMITER //
CREATE PROCEDURE doSomething()
BEGIN
-- Declare a variable and load a value into it
DECLARE _name CHAR(6) DEFAULT NULL;
SELECT value FROM tableA WHERE id = 6 INTO _name;
-- Use the variable in a query
SELECT * FROM tableB WHERE name = _name;
END; //
DELIMITER ;
CALL doSomething();

Related

MYSQL SELECT statement returns null when called inside a Stored Procedure

Hi I am trying to create a simple procedure with a select statement inside it :
DELIMITER //
CREATE PROCEDURE testProcedure(OUT login_id VARCHAR(30))
BEGIN
SELECT LOGIN_ID INTO login_id FROM USER_REG_MST WHERE USER_MOBILE_NO = 123;
END//
DELIMITER ;
The select satatement when called out side the proedure independently returns a value, but when the select is called inside a stored procedure it returns a null.
SELECT LOGIN_ID INTO login_id FROM mystrodb.USER_REG_MST WHERE USER_MOBILE_NO = 123;
Gives me a value.
But,
CALL testProcedure(#out);
SELECT #out;
returns a NULL.
Note: the columns is of type VARCHAR(30) (additional info)
The problem is that for MySQL LOGIN_ID and login_id are the same variable, so it's not recommended to name parameters and variables as the name of their objects or entities (tables, columns, etc.) of your database, see C.1 Restrictions on Stored Programs :: Name Conflicts within Stored Routines.
A couple of options: 1) Change the name of the output parameter of the stored procedure. 2) Include a qualifier to LOGIN_ID column, see 9.2.1 Identifier Qualifiers.
...
SELECT `USER_REG_MST`.`LOGIN_ID` INTO `login_id` ...
...
See dbfiddle.
You need to set OUT parameter and make sure to distinguish between column name vs parameter name:
DELIMITER //
CREATE PROCEDURE testProcedure(OUT login_id VARCHAR(30))
BEGIN
SET login_id = (SELECT u.LOGIN_ID
FROM USER_REG_MST u WHERE USER_MOBILE_NO = 123);
END//
DELIMITER ;
DBFiddle Demo

Simple sql function with SELECT

I try to understand how functions work. I can make the equivalent in procedure but I can't create a simple function with select.
element is UNIQUE and
thing is PRIMARY
CREATE DEFINER=`root`#`localhost`
FUNCTION `get_element_by_thing`(`thing` VARCHAR(255))
RETURNS VARCHAR(255)
CHARSET utf8
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
DECLARE #return_element VARCHAR(255);
SET #return_element = (
SELECT
`element`
FROM
`table1`
WHERE
`thing` = thing
);
RETURN #return_element;
I use the phpmyadmin interface.
1) Don't declare user-defined variables.
The name of a local variable in MySQL stored program does not start with an at sign #. As an example:
DECLARE stored_program_local_variable VARCHAR(255);
SET stored_program_local_variable = 'somevalue';
The name of a user-defined variables start with an at sign #. (The at sign character is what distinguishes user-defined variables from other identifiers.) It's not valid to declare a user-defined variable in a stored program. To create a user-defined variable, just assign a value to it. For example:
SET #user_defined_variable = 'somevalue';
2) If we don't need to persist variables beyond the scope of a stored program, we typically use local variables, which exist only for the duration of the stored program execution. (Which is different behavior than user-defined variables which are at the session level.)
3) Use the SELECT ... INTO syntax to retrieve scalar values into user-defined or local variables. https://dev.mysql.com/doc/refman/5.7/en/select-into.html
Try:
DELIMITER $$
CREATE DEFINER=`root`#`localhost`
FUNCTION `get_element_by_thing`(`thing` VARCHAR(255))
RETURNS VARCHAR(255)
...
BEGIN
DECLARE return_element VARCHAR(255) ;
SELECT t1.element
INTO return_element
FROM table1 t1
WHERE t1.thing = thing
LIMIT 1 ;
RETURN return_element ;
END $$
DELIMITER ;
Note: with ambiguous identifiers (i.e. routine parameter and column with the same name in a SQL statement, the routine parameter takes precedence over the column name. Qualify the column reference with the table name or table alias so it's not ambiguous. I prefer to assign routine parameters (and local variables) names that do not match column names.
If for some reason you need to assign a value to a user-defined variable in a SQL statement, you can use the := assignment operator. This is also valid outside the context of a stored program.
SELECT #user_defined_variable := t.somecolumn
FROM mytable t
WHERE somecondition
ORDER BY someexpression
LIMIT 1

MYSQL stored procedure for update variables are 0

I have the following stored procedure in a MYSQL database. The stored procedure gets lon,lat and than I'm doing an update on a different database and table.
DROP PROCEDURE IF EXISTS annuals.updateSalesFlorida;
CREATE DEFINER=`dddd`#`%` PROCEDURE `updateSales`(propertyId int)
BEGIN
DECLARE lat FLOAT;
DECLARE lon FLOAT;
SELECT SitusLongitude,SitusLatitude
INTO lon,lat
FROM annuals.florida
WHERE PropertyID=propertyId
LIMIT 1 FOR UPDATE;
UPDATE sales.florida
SET
`SitusLongitude` = lon,
`SitusLatitude` = lat
WHERE PROPERTYUNIQUEID=propertyId;
END;
Every time I run the stored procedure the SitusLongitude and SitusLatitude columns are 0. I know for a fact that the previous selected SitusLongitude and SitusLatitude have actual values in there. For some reason the variables are not being set in lat,lon. Any idea what I'm dong wrong?
The problem is that the procedure parameter has the same name as a column in the tables. When you refer to propertyid in the queries, it uses the column, not the parameter. Column and variable names are case-insensitive, so it doesn't matter that you spelled one of them PropertyID and the other propertyId.
Use a different name for the parameter, e.g. p_propertyId
Also, there's no need for two queries, you can do it in one with a JOIN.
UPDATE sales.florida AS s
CROSS JOIN (
SELECT *
FROM annuals.florida
WHERE propertyId = p_propertyId
LIMIT 1) AS a
SET s.SitusLongitude = a.SitusLongitude, s.SitusLatitude = a.SitusLatitude
WHERE s.PROPERTYUNIQUEID = p_propertyId
Note that using LIMIT without ORDER BY means that the row that's selected will be unpredictable.

MySQL stored procedure: OUT parameter not being set

I've got a stored procedure in MySQL that gets the next unique ID from a table, to use as an ID for 2 other tables (not the best way to do it, I'm sure, but I'm modifying someone else's code here). The procedure is as follows:
DELIMITER $$
CREATE DEFINER=`root`#`%` PROCEDURE `GetNextID`( OUT id bigint )
BEGIN
DECLARE uid VARCHAR(255);
SET uid = uuid();
INSERT INTO `ident_column_generator` (u) VALUES (uid);
SELECT ID INTO id FROM `ident_column_generator` WHERE u = uid;
DELETE FROM `ident_column_generator` WHERE u = uid;
END$$
When I call the procedure from MySQL Workbench:
CALL GetNextID( #id );
SELECT #id;
#id is NULL. I can't work out what's going wrong? Even if I run SET #id = 0; before calling the procedure, it ends up as NULL afterwards. If I call the functions within the procedure manually from MySQL Workbench, #id outputs fine, e.g.:
SET #uid = uuid();
INSERT INTO `ident_column_generator` (u) VALUES (#uid);
SELECT ID INTO #id FROM `ident_column_generator` WHERE u = #uid;
DELETE FROM `ident_column_generator` WHERE u = #uid;
SELECT #id;
This outputs #id as being a valid number.
Any ideas why id isn't being set properly?
Typically, spent 3 hours on this, then JUST after I posted the question I find the problem. So, for future reference: It appears MySQL is case insensitive where variables are concerned. The ID column name and id variable apparently completely confused it.
I changed the procedure's input parameter name to retId and then it worked perfectly.
Thanks Nick, I also had same issue. The column name and variable name were same due to which we were getting the issue.

MySQL stored procedure select returning incorrect values

I noticed that a select statement inside my stored procedure is always returning the same value, no matter what parameter I'm calling my stored procedure with. Here's the code:
DELIMITER $$
CREATE PROCEDURE TEST(IN id INT)
BEGIN
DECLARE x INT DEFAULT 0;
select id;
SELECT paper_id
INTO x
FROM Paper
WHERE ID = id
limit 1;
select x;
END$$
x always returns the same value no matter what id I call test with. I noticed the value of x is always the value of paper_id in the first row of my Paper table.
However, if I run the same query outside of the stored procedure, I get the expected value.
What is going wrong inside the stored procedure which skews that value?
I'm not that familiar with MySQL's stored procedures, but could it be that the expression WHERE ID = id is evaluated as "all rows from Paper where the value in the column ID equals the value in the column ID" and simply ignores your parameter?
Try to rename your parameter to something that is different from the column name in your query.