MySQL variable name conflicts with field name - mysql

I am writing a stored procedure for MySQL which needs to have an input parameter that has the same name as a field in a table. I know that I can refer to the field as tableName.fieldName. But how can I refer to the variable in a non-ambiguous way when querying that table within the procedure?
Table files
+----+---------+---------+
| id | ownerId | content |
+----+---------+---------+
CREATE PROCEDURE getFilesOfOwner(IN ownerId INT)
BEGIN
SELECT * FROM files WHERE files.ownerId = ___________ <- ?
...

If the name of a procedure argument is the same as a field name of a table, using that identifier in a query to that table will be interpreted by MySQL as a reference to the variable, i.e. no qualifier is formally needed, however this is a vendor-specific conflict resolution only.
The solution for keeping the argument name the same is to declare an alias variable within the scope of the procedure, but expose it to the caller under the desired name:
CREATE PROCEDURE getFilesOfOwner(IN ownerId INT)
BEGIN
DECLARE _ownerId INT DEFAULT ownerId;
SELECT * FROM files WHERE files.ownerId = _ownerId
...
This requires one additional line of code, but it keeps the procedure signature clean from implementation-specific details.

Related

How to differentiate between local variable and field name?

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();

Stored function returns NULL Mysql

i make this simple STORED FUNCTION in MySql that returns emails sparated with comma:
CREATE FUNCTION get_participantes (id INT) RETURNS VARCHAR(50)
BEGIN
DECLARE par VARCHAR(50) DEFAULT "";
(select GROUP_CONCAT(mail SEPARATOR ',') INTO #par from users where id IN (
select user_id from meeting_participants where meeting_id = id));
RETURN #par;
END
But when i call it using SELECT, i got NULL everytime. The SQL sentence works perfectly but itself.
+----------------------+
| get_participantes(5) |
+----------------------+
| NULL |
+----------------------+
Please help
The name of your function parameter is id, but you also have a column id in your users table, and maybe there's an id column in your meeting_participants table as well.
This creates an ambiguity. The expression doesn't know whether you mean the column id or the function parameter id.
You should give your function parameter a distinct name, to resolve the ambiguity.
CREATE FUNCTION get_participantes (_id INT) RETURNS VARCHAR(50)
READS SQL DATA
BEGIN
DECLARE par VARCHAR(50) DEFAULT "";
(select GROUP_CONCAT(mail SEPARATOR ',') INTO par from users where id IN (
select user_id from meeting_participants where meeting_id = _id));
RETURN par;
END
A couple of other issues that you should know about, even though they are not related to your question:
In MySQL routines (unlike SQL Server for example), your par local variable is not the same as the #var session variable. Your code in this specific case will work, but it's possible some other function you write will be confused. See also my answer to "#" symbol in stored procedure?
You should add the clause READS SQL DATA to your function, or else you may get this error (as I did when I tested your function):
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable)

MySql - Creating Stored Function and Calling It

I need help creating this particular stored function and call it by using the single select statement. Below are the questions with my answer. I think I got the first part right but I'm not sure. Any suggestions/advice? For the second question (part b), I'm calling the function incorrectly and can't get it to appear as specified in question/part b. Any advice? I would really appreciate the assistance.
Part A) Create a stored function called get_customer_balance which will return a customer’s balance from the membership table by passing in a membership number.
My Answer:
DELIMITER $$
CREATE FUNCTION get_customer_balance (membershipNo INT)
RETURNS dec
DETERMINISTIC
BEGIN
DECLARE CustBal dec;
SET CustBal = 0;
SELECT balance INTO CustBal
FROM membership
WHERE membership_id = membershipNo;
RETURN CustBal;
END$$
DELIMITER ;
Part B question
Membership Table. This is the original table of the problem (for reference guide)
create table membership
( membership_id int primary key,
balance decimal(10,2) not null
);
insert membership(membership_id,balance) values (1,1),(102,11),(103,109.25);
select membership_id,format(get_customer_balance(membership_id),2) as theBalance
from membership
where membership_id=102;
+---------------+------------+
| membership_id | theBalance |
+---------------+------------+
| 102 | 11.00 |
+---------------+------------+
Mysql Manual page on Create Proc and Functions
Calling your user defined function (UDF) would be like calling any built-in function. Even if it involved joins on tables with aliases (which the above does not show).
A much better example would be one in which there are two tables. A membership table, and a transaction table that needs summed. But that wasn't your schema.
Would you like to see such a thing?

Stored Procedure has OUT parameter with datatype VARCHAR, would like to remove quotes of it to use it in IN clause for INT type

We have a stored procedure and we call it as
call sp_name(1, 2, #VARCHAR_TYPE_VARIABLE);
Next we are trying to use OUT parameter in a WHERE clause like
SELECT COUNT(*) FROM tbl1 WHERE FIELD_OF_TYPE_INT IN(#VARCHAR_TYPE_VARIABLE);
But the problem is #VARCHAR_TYPE_VARIABLE has value like '1,2,3' (Quoted) and but my WHERE clause expect as WHERE IN (1,2,3);
My question is: how can i remove the quotes of returned VARCHAR OUT parameter to make it run for INT TYPE in WHERE IN clause.
This shows the treatment of an IN variable, not an out, as I was a little confused by the OUT part of what you are saying. Meaning, have an IN for an IN. If you need an OUT, give that separately. In my mind.
If you need to use other parameters inside your prepared statement, see the reference SQL Syntax for Prepared Statements halfway down that page around the area EXECUTE stmt2 USING #a, #b;.
So to be clear, parameters like #a above are great for normal parameters one would like plugged into prepared statements (like in PHP or JAVA). The trick with yours is that lists don't work well in that fashion, and require the prepared statement string to be constructed with concat. One can mix and match the two. Meaning you can put one together that requires a concat in the part that is required, as well as execute it USING ... with the variables that don't require concat.
But here is yours.
Schema
create table thingsCoveted
( id int auto_increment primary key,
thing varchar(100) not null
);
insert thingsCoveted(thing) values ('Fritos'),('crackers'),('gold');
Stored Proc
drop procedure if exists sp_name1;
DELIMITER $$
CREATE procedure sp_name1 (
IN theList varchar(100) -- comes in like '1,3', need to strip off single quotes
)
BEGIN
-- declare preparedSql varchar(100);
declare theSize int;
set theSize=length(theList);
set #preparedSql=concat("select * from thingsCoveted where id in (",substring(theList,2,theSize-2),")");
-- select #preparedSql; -- left here for debug view if you un-rem it
PREPARE stmt FROM #preparedSql;
execute stmt;
END $$
DELIMITER ;
Test It
set #var1="'1,3'";
call sp_name1(#var1);
+----+--------+
| id | thing |
+----+--------+
| 1 | Fritos |
| 3 | gold |
+----+--------+

Is there any way to query a MySQL stored procedure for its returned column names and their data types?

Is there any way to automatically find out the returned column names of a stored procedure and their data types?
Assuming my stored procedure is as follows:
CREATE PROCEDURE `user_countries`()
BEGIN
select m.ID, m.Name, c.Country
from Member AS m, Country AS c
where m.CountryId = c.ID;
END$$
This returns me a table which looks like this:
ID | Name | Country
-------------------------
1 John USA
2 Mary Australia
I need to be able to query my stored procedure so that I can see something like the following
ColName | Data Type
------------------------
ID | INT
Name | Varchar(50)
Country | Varchar(50)
I have not heard of anything that can be done for a stored procedure similar to the table equivalent of
describe Member;
Any suggestions?
PS. This is just a trivial example, I have hundreds of tables and hundreds of stored procedures of varying complexity which I need to analyze.
ANSWER
Thanks to #BishnuPaudel from the comments below.
I am connecting to the db via c# .net so the approach was to query the data which was returned from the stored procedure rather than accessing it via mysql commands.
Using the example from the msdn library
http://msdn.microsoft.com/en-us/library/system.data.datatable.columns(v=vs.110).aspx
I have added the column.DataType print statement to see the Datatypes of the column.
private void PrintValues(DataTable table) {
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
Console.WriteLine(column.DataType);
Console.WriteLine(row[column]);
}
}
}
Thanks again.