Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle SQL creating a function - confusing compile errors

Based off of how to return a dynamic result set in Oracle function

I'm trying to make a function that will return one row with several counts from several tables. Here's what I have so far:

CREATE OR REPLACE TYPE RESULT_ROW is OBJECT
(LOC_TABLE_ENTRY_KY VARCHAR2(50),
LOCATION_NAME VARCHAR2(50),
A_ASSIGN_CNT VARCHAR2(50),
B_ASSIGN_CNT VARCHAR2(50),
C_ASSIGN_CNT VARCHAR2(50),
D_ASSIGN_CNT VARCHAR2(50),
E_ASSIGN_CNT VARCHAR2(50),
F_ASSIGN_CNT VARCHAR2(50),
G_ASSIGN_CNT VARCHAR2(50),
H_ASSIGN_CNT VARCHAR2(50));
/
CREATE OR REPLACE TYPE RESULT_TABLE AS TABLE OF RESULT_ROW;
/
CREATE OR REPLACE FUNCTION LOCATION_RULE_LOOKUP(P_LOCATION_VAR IN NUMBER)
RETURN RESULT_TABLE
IS
OUT_REC RESULT_TABLE;
BEGIN
WITH LOC AS
(SELECT LOC_TABLE_ENTRY_KY,
LOCATION_NAME
FROM LOCATION_CODE
WHERE LOC_TABLE_ENTRY_KY = P_LOCATION_VAR
),
ONE AS
(SELECT COUNT(*) AS A_ASSIGN_CNT
FROM COLLECTOR_ASSIGNMENT
WHERE LOCATION_CODE     = P_LOCATION_VAR
AND FUNCTION_STATE_CODE = '   '
OR FUNCTION_STATE_CODE  = '***'
),
TWO AS
(SELECT COUNT(*) AS B_ASSIGN_CNT
FROM COMM_PLAN_ASSGN_RULE
WHERE LOCATION_CODE = P_LOCATION_VAR
),
THREE AS
(SELECT COUNT(*) AS C_ASSIGN_CNT
FROM INPUT_TRANS_ASGN
WHERE LOCATION_CODE = P_LOCATION_VAR
),
FOUR AS
(SELECT COUNT(*) AS D_ASSIGN_CNT
FROM RECALL_DAYS_ASSGN_RULE
WHERE LOCATION_CODE = P_LOCATION_VAR
),
FIVE AS
(SELECT COUNT(*) AS E_ASSIGN_CNT
FROM SCRIPT_VIEW_ASSIGNMENT
WHERE LOCATION_CODE     = P_LOCATION_VAR
AND FUNCTION_STATE_CODE = '   '
OR FUNCTION_STATE_CODE  = '***'
AND SCRIPT_TYPE         = 'V'
),
SIX AS
(SELECT COUNT(*) AS F_ASSIGN_CNT
FROM SCRIPT_VIEW_ASSIGNMENT
WHERE LOCATION_CODE     = P_LOCATION_VAR
AND FUNCTION_STATE_CODE = '   '
OR FUNCTION_STATE_CODE  = '***'
AND SCRIPT_TYPE         = 'D'
),
SEVEN AS
(SELECT COUNT(*) AS G_ASSIGN_CNT
FROM TSR_ASSGN_RULE
WHERE LOCATION_CODE = P_LOCATION_VAR
),
EIGHT AS
(SELECT COUNT(*) AS H_ASSIGN_CNT
FROM TRAN_STATE_ASSGN_RULE
WHERE LOCATION_CODE = P_LOCATION_VAR
)
SELECT * INTO OUT_REC
FROM ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, LOC;
RETURN OUT_REC;
END LOCATION_RULE_LOOKUP;

But no matter what I do to make this look like existing function examples, both here and on other sites, it doesn't accept anything within the BEGIN block. The SQL inside the BEGIN block works; I can run all those WITH AS SELECT etc. and it'll give me one row as the result with the counts I'm looking for. But this function will just NOT compile. Depending on where I put a space or a semicolon, the errors change. Current errors:

Error(7,3): PL/SQL: SQL Statement ignored
Error(62,3): PL/SQL: ORA-00947: not enough values

Help? D:

like image 611
John D Avatar asked Dec 19 '11 19:12

John D


People also ask

What is function created with compilation errors?

Warning: Function created with compilation errors. Unlike most compilers, which will display a listing of errors found in source code, Oracle stores any errors it finds in a database table named USER_ERRORS. If you want to see the specific details, and you may well, you need to retrieve the error listing yourself.

When writing code you received this message warning created with compilation error which command can you issue to see the actual error message?

You can run show errors; to see what compilation errors are.

How do you compile a function in Oracle SQL Developer?

To edit and recompile an existing function, you follow these steps: First, click the function name that you want to edit. Second, edit the code. Third, click the Compile menu option to recompile the code.

How do I find the compilation error in SQL?

After you use the CREATE command to create a stored procedure, a message is displayed if the stored procedure has any compilation errors. To see the errors, you use SHOW ERRORS. When you specify SHOW ERRORS with no arguments, SQL*Plus shows compilation errors for the most recently created or altered stored procedure.


1 Answers

You're very close, but you didn't follow the linked question quite faithfully enough. The reason for the not enough values message is that you only have one value in your INTO clause, but Oracle is expecting you to have eight, since that's how many expressions are (effectively) in your SELECT *. You need to cast those eight expressions into a single value. To do this, you need to change your WITH ... SELECT * INTO out_rec ... into either SELECT CAST(MULTISET(WITH ... SELECT * ...) AS result_table) INTO out_rec FROM dual or WITH ... SELECT CAST(MULTISET(SELECT * ...) AS result_table) INTO out_rec FROM dual, as you prefer.

Also, you need to put your FROM clause in the right order, with LOC preceding ONE through EIGHT; the cast is performed based on the relative positions of the expressions, not based on the field aliases. (Alternatively, you could change your SELECT * to explicitly identify the fields, in the right order, rather than relying on the FROM-clause order.)

like image 145
ruakh Avatar answered Sep 22 '22 11:09

ruakh