问题
I'm trying to create a function that return a varchar, one of the fields form a select, the aggregation field. I'm getting the next error:
ORA-01422: exact fetch returns more than requested number of rows
What I understand is that the select produce more than one row before aggregating and this triggers the error when trying to put them 'into k, s, categories'
Here is the function:
FUNCTION get_cat(kind_id IN varchar, system_id IN Number) RETURN VARCHAR2
AS categories VARCHAR2(2000);
k STANDARDS.KIND_ID%TYPE;
s SEEDTEST_RESULT.SLRN_ID%TYPE;
BEGIN
SELECT STANDARDS.KIND_ID, SEEDTEST_RESULT.SLRN_ID,
listagg(CAT_LEVEL, ' ' ) within group (order by cat_level)
INTO k, s, categories
FROM STANDARDS, SEEDTEST_RESULT
WHERE STANDARDS.CL_PRIORITY = SEEDTEST_RESULT.CL_PRIORITY
AND SEEDTEST_RESULT.RESULT = 1
AND SEEDTEST_RESULT.TEST_TYPE = 'C'
AND STANDARDS.KIND_ID = trim(kind_id)
AND SEEDTEST_RESULT.SLRN_ID = system_id
GROUP BY STANDARDS.KIND_ID, SEEDTEST_RESULT.SLRN_ID;
RETURN categories;
END get_cat;
The select statement works outside the function when I run it with specific values for kind_id and system_id.
I've been trying to create a temp table so I can get the initial rows from the select and then return categories, but so far I haven't been able to find any helpful information for this particular case. Does anyone knows how can I do this, please?
Thank you.
回答1:
The problem is with your variable names:
FUNCTION get_cat(kind_id IN varchar, ...
...
AND STANDARDS.KIND_ID = trim(kind_id)
You have a column called kind_id and the query will use that in preference to the PL/SQL variable of the same name.
From the documentation:
If a SQL statement references a name that belongs to both a column and either a local variable or formal parameter, then the column name takes precedence.
So you aren't matching the passed-in value, you're actually finding all rows which match system_id for any value of kind_id. (Except null, and if they have leading/trailing whitespace...)
Change your variable names so they do not clash and there is no confusion. It's common to prefix passed-in argument with, say, a p prefix so you'd be comparing with = p_kind_id, and local variables with an l prefix.
If you really want to keep the names you have, you can also prefix the references to those with the function name:
AND STANDARDS.KIND_ID = trim(get_cat.kind_id)
来源:https://stackoverflow.com/questions/51307830/return-one-variable-from-a-select-inside-a-function