can i run a group by statement within stored procedure and return the output as variable - mysql

Hi All,
i am a nub to mysql and i am experimenting with stored procedure, i have written a script to calculate count of Respondent id, for now stored procedure returns a cumulative number however i would like resultant grouped by each city. when i attempt that i get an error message stating "Result consisted of more than one row error"
Note: i am aware that i can query using where statement for each city however that method is in-efficient as i have to manually key in each distinct city name hence i am looking for alternatives to efficiently tackle this
any help would be greatly appreciated
regards
Sri
Stored Procedure code
DROP PROCEDURE IF EXISTS `Total_grpby`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE
`total_grpby
`(
OUT ex_total INT
)
BEGIN
SELECT COUNT(rsp_id) As total INTO ex_total
FROM test.`jnk_test`
GROUP BY Dmc_Cty;
END$$
desired output
dmc_cty Total
Chennai 337
Delhi 263
Gurgaon 53
Hyderabad 406
Mumbai 482
Noida 464
Pune 522

No, it's not possible in MySql.
OUT ex_total INT declares a variable of type INT.
The type Int can hold one - and only one value - it is a scalar variable.
However your query returns many values, not one.
To store many values you need something like an array, or a collection.
Unfortunately, MySql doesn't support array nor collection datatypes, so in MySql you cannot store many values in one variable and return them as OUT parameter from the procedure.
This is possible in other databases, like PostgreSQL, Oracle, SQL-Server, they support collection datatypes.
In MySql, an ordinary SELECT (without INTO clause), which is execuded in the procedure, creates a resultset and returns it from the procedure to the client.
Unfortunately MySql is not able to read this resultset - for example if you call a procedura A, that returns a resultset, from another procedure B, then the procedure B is not able to retrieve data from the resultset returned by the procedure A.
This resultset can be read only by some clients, for example JDBC or ODBC connectors, SQLPlus or MySQLWorkbench etc.

Related

MYSQL - Parameter being lost when using it in SQL statement

I have a stored procedure in MYSQL where I am passing one parameter which is passed into an SQL statement as you can see below however the result is returning a count of 0 where I am expecting a count of 2.
Stored Procedure:
CREATE DEFINER=`admin`#`%` PROCEDURE `EmployeesRecords`(IN employee_id varchar (1000))
BEGIN
--
declare v_count int ;
--
select count(*)
into v_count
from employees
where employees_id IN (employee_id);
--
END
One or many employee Id's can be passed into the parameter employee_id.
when Calling Stored Procedure like this : CALL EmployeesRecords('2,3'); This returns a count of 0 where I am expecting a count of 2
As for the parameter itself, I have tried various methods including changing it in the procedure to have it as "IN ('2','3') in the SQL condition however it still does not work.
However what I have noticed is that when passing one employee Id, it works successfully such as CALL EmployeesRecords('2');
Can anyone guide me to what I am doing wrong please?

Go (golang) retrieving results from last statement in multiple statement mysql stored procedure

I am calling a mysql 5.7 stored procedure which has two statements with go mysql driver.
First statement only assigns values to variables from database
E.g: select #location=location, #stat=stat from user where ...
Second statement
Select id, name, ... from user where ..
I have no control over the procedure and need to use the results of the second statement.
How can I access the results in go?

MySQL Stored Procedures: Using a result set returned from a stored procedure in another stored procedure with MYSQL 5.6

In our MySql database there are 3 stored procedures Sp1(), Sp2() and Sp3() . There is logic in Sp3() which I want to use in the stored procedures Sp1() and Sp2(), I know that using a temporary table in Sp3() and using that temporary table in Sp1() and Sp2() works.
To save time and memory it is preferred not to create a temporary table.
One extra piece of info is I can return a result set from a stored procedure to my client. But I am unable to make this store procedure (SP3) work like a subquery, where the result set is returned from the Stored procedure Sp3() and can be compared with another table in Sp2() and Sp1() based on a id key.
I want to try something like below, which can be used in stored procedures Sp1() and Sp2():
Assuming Sp3() returns an id field along with other fields:
Select
id
from
EmployeeTable e
where 5000 >
(Select salary from (call Sp3()) where id= e.id);

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.

mysql stored procedure is slower 20 times than standard query

i have 10 tables with same structure except table name.
i have a sp (stored procedure) defined as following:
select * from table1 where (#param1 IS NULL OR col1=#param1)
UNION ALL
select * from table2 where (#param1 IS NULL OR col1=#param1)
UNION ALL
...
...
UNION ALL
select * from table10 where (#param1 IS NULL OR col1=#param1)
I am calling the sp with the following line:
call mySP('test') //it executes in 6,836s
Then I opened a new standard query window. I just copied the query above. Then replaced #param1 with 'test'.
This executed in 0,321s and is about 20 times faster than the stored procedure.
I changed the parameter value repeatedly for preventing the result to be cached. But this did not change the result. The SP is about 20 times slower than the equivalent standard query.
Please can you help me to figure out why this is happening ?
Did anybody encounter similar issues?
I am using mySQL 5.0.51 on windows server 2008 R2 64 bit.
edit: I am using Navicat for test.
Any idea will be helpful for me.
EDIT1:
I just have done some test according to Barmar's answer.
At finally i have changed the sp like below with one just one row:
SELECT * FROM table1 WHERE col1=#param1 AND col2=#param2
Then firstly i executed the standart query
SELECT * FROM table1 WHERE col1='test' AND col2='test' //Executed in 0.020s
After i called the my sp:
CALL MySp('test','test') //Executed in 0.466s
So i have changed where clause entirely but nothing changed. And i called the sp from mysql command window instead of navicat. It gave same result. I am still stuck on it.
my sp ddl:
CREATE DEFINER = `myDbName`#`%`
PROCEDURE `MySP` (param1 VARCHAR(100), param2 VARCHAR(100))
BEGIN
SELECT * FROM table1 WHERE col1=param1 AND col2=param2
END
And col1 and col2 is combined indexed.
You could say that why dont you use standart query then? My software design is not proper for this. I must use stored procedure. So this problem is highly important to me.
EDIT2:
I have gotten query profile informations. Big difference is because of "sending data row" in SP Profile Information. Sending data part takes %99 of query execution time. I am doing test on local database server. I am not connecting from remote computer.
SP Profile Informations
Query Profile Informations
I have tried force index statement like below in my sp. But same result.
SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=#param1 AND col2=#param2
I have changed sp like below.
EXPLAIN SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=param1 AND col2=param2
This gave this result:
id:1
select_type=SIMPLE
table:table1
type=ref
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL
rows:292004
Extra:Using where
Then i have executed the query below.
EXPLAIN SELECT * FROM table1 WHERE col1='test' AND col2='test'
Result is:
id:1
select_type=SIMPLE
table:table1
type=ref
possible_keys:col1_co2_combined_index
key:col1_co2_combined_index
key_len:76
ref:const,const
rows:292004
Extra:Using where
I am using FORCE INDEX statement in SP. But it insists on not using index. Any idea? I think i am close to end :)
Just a guess:
When you run the query by hand, the expression WHERE ('test' IS NULL or COL1 = 'test') can be optimized when the query is being parsed. The parser can see that the string 'test' is not null, so it converts the test to WHERE COL1 = 'test'. And if there's an index on COL1 this will be used.
However, when you create a stored procedure, parsing occurs when the procedure is created. At that time, it doesn't know what #param will be, and has to implement the query as a sequential scan of the table.
Try changing your procedure to:
IF #param IS NULL
THEN BEGIN
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
...
END;
ELSE BEGIN
SELECT * FROM table1 WHERE col1 = #param
UNION ALL
SELECT * FROM table2 WHERE col1 = #param
...
END;
END IF;
I don't have much experience with MySQL stored procedures, so I'm not sure that's all the right syntax.
Possible character set issue? If your table character set is different from your database character set, this may be causing a problem.
See this bug report: http://bugs.mysql.com/bug.php?id=26224
[12 Nov 2007 21:32] Mark Kubacki Still no luck with 5.1.22_rc - keys
are ingored, query takes within a procedure 36 seconds and outside
0.12s.
[12 Nov 2007 22:30] Mark Kubacki After having changed charsets to UTF-8 (especially for the two used), which is used for the
connection anyways, keys are taken into account within the stored
procedure!
The question I cannot answer is: Why does the optimizer treat charset
conversions an other way within and outside stored procedures?
(Indeed, I might be wrong asking this.)
Interesting question, because I am fond of using stored procedures. Reason is maintenance and the encapsulation principle.
This is information I found:
http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html
It states that the query cache is not used for queries that
1. are a subquery that belong to an outer query, and
2. are executed within the body of a stored procedure, trigger or event.
This implies that it works as designed.
I had seen this behavior, but it wasn't related to the character set.
I had a table that held self-referencing hierarchical data (a parent with children, and some children had children of their own, etc.). Since the parent_id had to reference the primary id's (and the column specified a constraint to that effect), I couldn't set the parent id to NULL or 0 (zero) to disassociate a child from a parent, so I simply referenced it to itself.
When I went to run a stored procedure to perform the recursive query to find all children (at all levels) of a particular parent, the query took between 30 & 40 times as long to run. I found that altering the query used by the stored procedure to make sure it excluded the top-level parent record (by specifying WHERE parent_id != id) restored the performance of the query.
The stored procedure I'm using is based on the one shown in:
https://stackoverflow.com/questions/27013093/recursive-query-emulation-in-mysql.