mysql stored function: how to select multiple results and process them. For example,
create function hello() return decimal(10,2) determistic begin
select value1, value2 from Foo;
// process multiple rows in result set here
for (....) {
}
end
https://dev.mysql.com/doc/refman/8.0/en/create-procedure.html says:
Statements that return a result set can be used within a stored procedure but not within a stored function.
You can't run select ... from Foo in a stored function as you would in a stored procedure, because that select will generate a result set with multiple columns and multiple values.
A stored function can only return a single scalar value. In your example, you are returning a decimal(10,2). So whatever you do with your queries, the result must end up in an expression in a RETURN statement.
If you need to run a select query, you can store the result into a variable and then return that variable.
...
begin
declare d decimal(10,2);
select <expr> into d from Foo limit 1;
return d;
end
Or you can run a cursor (as suggested by the link posted by #stickybit above in a comment), and process the result of the query row-by-row. See an example in that documentation page: https://dev.mysql.com/doc/refman/8.0/en/cursors.html
I can't go into more detail, because you have not described what you're trying to do with your function, and the example you show does not make it clear.
Related
In SQL is there a way to grab the information in a table, but with the table name being specified by a function parameter?
Obviously the following doesn't work, but something along these lines maybe:
CREATE OR REPLACE FUNCTION select_table(table_name TEXT)
RETURNS TABLE (
"ID" TEXT
) AS
$$
SELECT * FROM uploads.<table_name>
$$
LANGUAGE SQL STABLE;
I'm a bit of a rookie when it comes to SQL, so would appreciate any guidance.
Any use of a variable in a query will be as if you had used a string literal, not an identifier.
To use a variable as an identifier, you would have to use dynamic SQL. That is, do string-concatenation of the table_name variable into a string which is your SELECT query, then PREPARE and EXECUTE that query.
But https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html says:
SQL syntax for prepared statements can be used within stored procedures, but not in stored functions or triggers.
This is because if a stored function is running, then by definition, your thread is already running a query. MySQL cannot do that.
You can write your function to do a large CASE statement to do a different fixed query depending on the input variable.
But as P.Salmon comments above, in MySQL you can't return a table from a stored function. Functions can only return a single scalar value, not a result set. So your SELECT would need to query one column and use INTO syntax to save it to a variable. Then return that variable.
Also current versions of MySQL have no "CREATE OR REPLACE FUNCTION" option. You can "CREATE FUNCTION."
DELIMITER //
CREATE FUNCTION select_table(table_name TEXT)
RETURNS TEXT READS SQL DATA
BEGIN
DECLARE result TEXT;
CASE table_name
WHEN 'mytable1' THEN SELECT col1 INTO result FROM mytable1;
WHEN 'mytable2' THEN SELECT col1 INTO result FROM mytable2;
WHEN 'mytable3' THEN SELECT col1 INTO result FROM mytable3;
END CASE;
RETURN result;
END//
DELIMITER ;
Much appreciated if you can have a quick look on the below.
I've created the below stored function in order to format the datetime from a table to mysql format;
(%Y-%m-%d; %h:%i:%s);
Delimiter $$
create function formatdata(dataparameter varchar(20), hourparametru
varchar(20))
begin
DECLARE x time;
declare y date;
set x = (select STR_TO_DATE(Datăcolumn,'%h:%i:%s')from tabelname);
set y = (select STR_TO_DATE(oracolumn,'%Y-%m-%d')from tabelname);
select x,y;
if current_time > time(hourcolumn) then
select STR_TO_DATE(Datăcolumn,'%Y-%m-%d')into x from tabelname;
select STR_TO_DATE(oracolumn,'%h:%i:%s') into y from tabelname;
return(x,y);
end if;
end $$
Delimiter ;
What am I doing wrong here?
The error is You have an error in your sql syntax near first select_Str_to_date.
but I am kind of confused how local variables, IN parameters work together - so I am assuming that here is where I do wrong..
If you set a variable to a result of a scalar SELECT query, you put the query inside parentheses.
This:
set x = select STR_TO_DATE('07:47:20','%h:%i:%s');
Should be:
set x = (select STR_TO_DATE('07:47:20','%h:%i:%s'));
That explains the syntax error.
You also have a few other problems in this function.
Re your comment:
The line:
select x,y;
Would return a result set, but that's not allowed in a stored function (it is allowed in a stored procedure). I think you can just remove this line.
A stored function can only return a single scalar value. You should have a line RETURNS <datatype> before your BEGIN, and you should RETURN a single value somewhere in your function.
Another problem: your assignments are not valid if the table has more than one row. Setting a variable to a scalar SELECT query result is valid only if the query returns a single column and single row.
Another problem:
if current_time > time(hourcolumn) then
What is hourcolumn? It's not a function parameter or a local variable. But if it is a column of a table, there's no syntax to say which table you mean.
Another problem:
return(x,y);
You can't return a pair of variables from a stored function. Only one variable.
Another problem: The only RETURN is inside an IF block. What should the function return if the IF condition isn't true?
I am trying to create an sql trigger statement using phpmyadmin trigger interface.
Trying to do something for table 1 as shown below :
BEGIN
declare #valid_number int ;
select id into #valid_number from table 2 ;
if 10 does not exist in #valid_number then
{do something here}
end if;
END
how to achieve it?
First: a variable in a stored routine can't store multiple values, just a single one. Your statement
select id into #valid_number from table 2 ;
will only work, if the query returns exactly one row. An error will occur, if the query returns multiple rows, a warning, if the query returns no row at all, see the manual page to SELECT ... INTO:
The INTO clause can name a list of one or more variables, which can be
user-defined variables, stored procedure or function parameters, or
stored program local variables. [...]
The selected values are assigned to the variables. The number of
variables must match the number of columns. The query should return a
single row. If the query returns no rows, a warning with error code
1329 occurs (No data), and the variable values remain unchanged. If
the query returns multiple rows, error 1172 occurs (Result consisted
of more than one row).
Solution:
It's not difficult to create a statement that gives you the desired answer in exact one row, i.e.
SELECT COUNT(*) into valid_number FROM example WHERE id = 10;
This query will return 0, if the id 10 does not exists in column id and the count of occurences else. Of course there are several ways to achieve this, this is just one of them. You could rewrite your stored routine to:
BEGIN
-- prefer local variables, don't use user defined, if not needed.
DECLARE valid_number int;
SELECT COUNT(*) into valid_number FROM example WHERE id = 10;
IF valid_number = 0 THEN
-- do something here
END IF;
SELECT result;
END
Note
You could use a cursor to traverse the result of a query, but most times one wants to avoid a cursor. To use a cursor under similar conditions as of this question would not be the SQL way to do it and most times very inefficient.
I have this function that I want to run ... this function needs to return the job_ids that start with A only... I'm confused!
I'm getting this error!
any ideas... What I know that a function needs to have parameters, but I don't know what to pass...
23:47:05 select job_id() LIMIT 0, 1000 Error Code: 1242 Subquery returns more than 1 row
delimiter $
create function Job_id()
returns char
reads sql data
begin
return (select job_id
from job_history
where job_id like 'A%');
end$
delimiter ;
The MySQL documentation for functions says:
Statements that return a result set can be used within a stored
procedure but not within a stored function
If you need a result set then, as told by #Michael Berkowsky, use stored procedures or maybe a view will do the trick for your needs.
I have a user defined function.
In that function I declared a variable of type datetime.
I am assigning the result of a query into this variable. And I am returning this assigned value. It looks like
delimiter$$
drop function if exists getQEDate$$
create function getQEDate() returns datetime
begin
declare qedate datetime;
select date into qedate from qenddates where ....;
return qedate;
end$$
delimiter ;
When accessing this function I am getting an exception like "returns more than a row...".
So I am thinking this error occurred while returning the result. That means the variable qedate can hold more than one row.
Is the above analysis makes sense ?
It's probably that your query is returning more than 1 row and it can't store that into a variable. If you're only expecting 1 row you should check your where clause or add LIMIT 1 to the end of the query in the function.
I'm guessing since I can't see your data or your where clause :)