SQl Invalid Object - oracle

I am having some trouble with my procedure, I have the code working i think, the procedure runs and asks the user for input, the user enters the data which is stored in variables in the procedure which are then inserted into the table. But when I enter everything I am faced with an error. is it even possible to use an insert in a procedure or should I be going a different route? thanks
My procedure
create or replace PROCEDURE AD_AGENCY_INFO(
v_agency_id IN OUT AD_AGENCY.AGENCY_ID%TYPE,
v_no_of_ad_runs IN OUT AD_AGENCY.NO_OF_AD_RUNS%TYPE,
v_credit_worthy IN OUT AD_AGENCY.CREDIT_WORTHY%TYPE,
v_available_slots IN OUT AD_AGENCY.AVAILABLE_SLOTS%TYPE,
v_status IN OUT AD_AGENCY.STATUS%TYPE
) AS
BEGIN
SELECT AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS
INTO
v_agency_id, v_no_of_ad_runs, v_credit_worthy, v_available_slots, v_status
FROM AD_AGENCY;
INSERT INTO AD_AGENCY (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS)
VALUES (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS);
INSERT INTO AD (AGENCY_ID) VALUES (AGENCY_ID);
END AD_AGENCY_INFO;
How I am calling the procedure
DECLARE
V_AGENCY_ID NUMBER:='&Enter_Agency_ID';
V_NO_OF_AD_RUNS NUMBER:='&Enter_No_of_Ad_Runs';
V_CREDIT_WORTHY CHAR(3):='&Enter_Cedit_Worthy';
V_AVAILABLE_SLOTS NUMBER:='&Enter_Available_Slots';
V_STATUS CHAR(1):='&Enter_Status';
BEGIN
V_AGENCY_ID := NULL;
V_NO_OF_AD_RUNS := 0;
V_CREDIT_WORTHY := NULL;
V_AVAILABLE_SLOTS := NULL;
V_STATUS := NULL;
AD_AGENCY_INFO(
V_AGENCY_ID => V_AGENCY_ID,
V_NO_OF_AD_RUNS => V_NO_OF_AD_RUNS,
V_CREDIT_WORTHY => V_CREDIT_WORTHY,
V_AVAILABLE_SLOTS => V_AVAILABLE_SLOTS,
V_STATUS => V_STATUS
);
END;
/
The error report
Error report -
ORA-06550: line 14, column 3:
PLS-00905: object DT2113A.AD_AGENCY_INFO is invalid
ORA-06550: line 14, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

There are probably some typos here:
INSERT INTO AD_AGENCY (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS)
VALUES (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS);
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Values are ... well values, not column names. Maybe were you thinking to:
INSERT INTO AD_AGENCY (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS)
VALUES (v_agency_id, v_no_of_ad_runs, v_credit_worthy, v_available, v_status);
BTW, the rest of the code probably still need some thoughts ;)
For example, that code will not work as soon as you will have more than one row in your table:
SELECT AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS
INTO
v_agency_id, v_no_of_ad_runs, v_credit_worthy, v_available_slots, v_status
FROM AD_AGENCY;
Maybe the WHERE clause is missing? And even if so, it will overwrite the IN parameter values. Probably not a thing you want at that point...

I'm not TOO familiar with plsql, but it seems that you are incorrectly calling the procedure from your second block. Try writing:
CALL AD_AGENCY_INFO(
...
);
Or use Exec, I'm not too sure which:
EXEC AD_AGENCY_INFO(
...
);

Related

How to print a cursor in a PL/SQL block?

I can't seem to print cursor, what am I doing wrong?
DECLARE
LEADEMAIL VARCHAR2(200);
CLIENTID NUMBER;
v_Return ON24MASTER.WEBCAST_REPORTS.ResultSetCursor;
BEGIN
LEADEMAIL := 'nunyo#business.com';
CLIENTID := 22921;
v_Return := WEBCAST_REPORTS.LEAD_BASIC_INFO(
LEADEMAIL => LEADEMAIL,
CLIENTID => CLIENTID
);
DBMS_OUTPUT.PUT_LINE('v_Return = ' || v_Return);
-- :v_Return := v_Return;
END;
I get the following error:
Error report -
ORA-06550: line 14, column 26:
PLS-00306: wrong number or types of arguments in call to '||'
ORA-06550: line 14, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Most of the code was taken directly from running the function from SQL developer.
This is the package function:
FUNCTION LEAD_BASIC_INFO(
leadEmail VARCHAR2,
clientId NUMBER
) RETURN ResultSetCursor IS
resultSet ResultSetCursor;
email VARCHAR2(1000);
webcastEngagement NUMBER(10,1);
videoEngagement NUMBER(10,1);
documentEngagement NUMBER(10,1);
totalEngagement NUMBER(10,1);
--averageEngagement NUMBER(4,1);
totalWebcastSeconds NUMBER(10);
engagementMinutes NUMBER(10, 1);
last30DaysEM NUMBER(10, 1);
last60DaysEM NUMBER(10, 1);
fromDate DATE;
engagementPrediction NUMBER(10);
BEGIN...
Also, I can't print the result using a select statement because the function has DML as well.
In Oracle 12c, you can use DBMS_SQL.RETURN_RESULT. I.e.,
DECLARE
LEADEMAIL VARCHAR2(200);
CLIENTID NUMBER;
v_Return ON24MASTER.WEBCAST_REPORTS.ResultSetCursor;
BEGIN
LEADEMAIL := 'nunyo#business.com';
CLIENTID := 22921;
v_Return := WEBCAST_REPORTS.LEAD_BASIC_INFO(
LEADEMAIL => LEADEMAIL,
CLIENTID => CLIENTID
);
DBMS_SQL.RETURN_RESULT(v_Return);
END;
SQL*Developer will print the results.
You can't print a cursor like that; it would have to implicitly convert the rows and columns to strings, and that's too much to expect. The dbms_output.put_line() procedure only accepts a string argument - or anything that can be implicitly converted to a string. A cursor cannot.
You would have to loop over the cursor result set, fetching into a suitable record type; and then have a dbms_output call within that loop which concatenates all the column values from the result set (formatted and possibly padded if you're trying to emulate a select) into a single string.
Without know exactly how ON24MASTER.WEBCAST_REPORTS.ResultSetCursor is defined (presumably TYPE ResultSetCursor IS REF CURSOR), or what the query that populates it within your procedure is returning - which column names - it's hard to be more specific.
But since you've tagged this for SQL Developer you can use its built-in handling for ref cursor variables, which is handy:
variable rc refcursor;
DECLARE
LEADEMAIL VARCHAR2(200);
CLIENTID NUMBER;
BEGIN
LEADEMAIL := 'nunyo#business.com';
CLIENTID := 22921;
:rc := WEBCAST_REPORTS.LEAD_BASIC_INFO(
LEADEMAIL => LEADEMAIL,
CLIENTID => CLIENTID
);
END;
/
print rc
Before the block a bind variable rc is declared with the variable command. Inside the block that is used instead of a local v_Return, so that doesn't even need to be declared locally. (Note the colon before :rc in the assignment from the function - that denotes a bind variable). And then after the block the client lets you print the ref cursor. (Those doc links are for SQL*Plus, but they are among the the many commands SQL Developer supports.)
With a dummy package:
create or replace package WEBCAST_REPORTS AS
TYPE ResultSetCursor IS ref cursor;
FUNCTION LEAD_BASIC_INFO(
leadEmail VARCHAR2,
clientId NUMBER
) RETURN ResultSetCursor;
end WEBCAST_REPORTS;
/
create or replace package body WEBCAST_REPORTS AS
FUNCTION LEAD_BASIC_INFO(
leadEmail VARCHAR2,
clientId NUMBER
) RETURN ResultSetCursor IS
resultSet ResultSetCursor;
BEGIN
OPEN resultSet FOR select * from dual;
RETURN resultSet;
END LEAD_BASIC_INFO;
end WEBCAST_REPORTS;
/
then the code I showed above, run as a script, shows this in the script output window:
PL/SQL procedure successfully completed.
D
-
X

How to execute same stored procedure multiple times in Oracle SQL Developer?

I have a stored procedure and I need to call it several times with different sets of input. It looks like a script could do the job. How to generate the script? Ask Oracle SQL Developer (Version 4.2.0.17.089)! , So I bring up the following:
(By the way, what is this window called? And can this be accessible from menu bar?)
I select the right stored procedure, specify the correct parameter and click 'Save File'. Here is the saved SQL file:
DECLARE
I_MENU VARCHAR2(200);
ERRMSG VARCHAR2(200);
P_RETURNCUR SYS_REFCURSOR;
BEGIN
I_MENU := '4';
CMS_ACCESS_CONTROL.GETCMSMENUITEMINFO(
I_MENU => I_MENU,
ERRMSG => ERRMSG,
P_RETURNCUR => P_RETURNCUR
);
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('ERRMSG = ' || ERRMSG);
*/
:ERRMSG := ERRMSG;
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('P_RETURNCUR = ' || P_RETURNCUR);
*/
:P_RETURNCUR := P_RETURNCUR; --<-- Cursor
--rollback;
END;
I want to copy and paste the lines between BEGIN and END several times. Each time specify its set of input parameters (different I_MENU). But before doing so, I try to execute the file in SQL Developer. I have not made any modification but get this error:
Error report -
ORA-06550: Line 20, column 22
PLS-00382: expression is of wrong type
ORA-06550: Line 20, column 4
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Questions: 1) Why do I get this error? 2) How to call same stored procedure multiple times with different set of parameters? I want a script to do so as I have to pass the script to another person to execute.
Here is the stored procedure (there is absolutely no / after end getCMSMenuItemInfo)
Procedure getCMSMenuItemInfo(
i_menu in varchar2,
ERRMSG out varchar2,
P_RETURNCUR out SYS_REFCURSOR)
as
begin
open P_RETURNCUR for
SELECT menu_item, menu_url
FROM someMenu
WHERE menuID = i_menu;
end getCMSMenuItemInfo;
Using :ERRMSG and :P_RETURNCUR leading to your error. You're trying to assign value to variable with syntax :variable_a := variable_b which is not allowed in query worksheet. Uncomment legacy output DBMS_OUTPUT.PUT_LINE(); to testing your procedure.
Looking for another answer.
I am giving this solution based on a assumption that you have certain criteria of selecting different menuid's which you will be passing to your procedure "CMS_ACCESS_CONTROL.GETCMSMENUITEMINFO". I will tell you my approach both theoretically and will provide you the code as well.
Solution:
Theoretical Approach:
You can store your menuid's in a different table and loop over that table while calling the procedure. Now you have to decide how many and what different values you want to pass to your procedure.
Sampe Code:
create table store_id
(
id number
);
insert into store_id select distinct menuID from someMenu;
You can insert the different menuid's based on your business requirement.
DECLARE
I_MENU VARCHAR2(200);
ERRMSG VARCHAR2(200);
P_RETURNCUR SYS_REFCURSOR;
BEGIN
for i in (select id from store_id ) loop
I_MENU := i.id;
GETCMSMENUITEMINFO(
I_MENU => I_MENU,
ERRMSG => ERRMSG,
P_RETURNCUR => P_RETURNCUR
);
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('ERRMSG = ' || ERRMSG);
*/
ERRMSG := ERRMSG;
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('P_RETURNCUR = ' || P_RETURNCUR);
*/
P_RETURNCUR := P_RETURNCUR; --<-- Cursor
--rollback;
end loop;
END;
I hope this helps.

How do I display a nested table in Oracle - PL/SQL?

I have an assignment where I'm supposed to create a user-defined function that will return all employees after 1968. My code is as follows:
First I create a new object, called emp_dobs, to hold the employees' firstname, lastname, and date of birth, using the same data types as the original employee table:
CREATE OR REPLACE TYPE emp_dobs AS OBJECT (
emp_fname VARCHAR2(20),
emp_lname VARCHAR2(20),
emp_dob DATE
);
/
Then I create emp_dobs_nested as a table of emp_dobs:
CREATE OR REPLACE TYPE emp_dobs_nested AS TABLE OF emp_dobs;
/
Lastly, I create a function that's supposed to return an emp_dobs_nested table:
CREATE OR REPLACE FUNCTION get_emp_dobs RETURN emp_dobs_nested
AS
dobs emp_dobs_nested;
BEGIN
SELECT emp_dobs(firstname, lastname, birthdate) BULK COLLECT INTO dobs
FROM employee
WHERE birthdate < TO_DATE('01-JAN-1968', 'DD-MON-YYYY');
RETURN dobs;
END;
/
There is a weird quirk with compiling emp_dob_nested, however, where Oracle SQL Developer will display a new tab labeled "Output Variables - Log," and only show EMP_FNAME and EMP_LNAME. Despite that, everything compiles.
Now I want to test the function and display its results to prove that it works, but when I try this:
DECLARE
dobs emp_dobs_nested;
BEGIN
dobs := get_emp_dobs;
DBMS_OUTPUT.PUT_LINE(dobs);
END;
/
I get this error:
Error report -
ORA-06550: line 5, column 5:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 5, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
What am I missing here? Thanks.
You cannot pass the whole collection to DBMS_OUTPUT, rather you must loop through it and display individual columns at each index.
DECLARE
dobs emp_dobs_nested;
BEGIN
dobs := get_emp_dobs;
FOR i IN 1..dobs.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(dobs(i).emp_fname||','||dobs(i).emp_lname||','||dobs(i).emp_dob);
END LOOP;
END;
/
You can also use TABLE function to unnest a collection of objects into a relational resultset:
select * from table( get_emp_dobs )
Live demo: http://sqlfiddle.com/#!4/8cfb2/1
Another way of display is to use XML, try
DBMS_OUTPUT.PUT_LINE(XMLTYPE(dobs));
why not a create a view instead?
CREATE VIEW emp_view
AS
SELECT firstname, lastname, birthdate
FROM employee
WHERE birthdate < TO_DATE('01-JAN-1968', 'DD-MON-YYYY');
You can also try this,
DECLARE
dobs emp_dobs_nested;
i NUMBER := 0;
BEGIN
dobs := get_emp_dobs;
LOOP
i := dobs.NEXT(i);
DBMS_OUTPUT.PUT_LINE(dobs(i).emp_fname||','||dobs(i).emp_lname||','||dobs(i).emp_dob);
IF i = dobs.LAST THEN
EXIT;
END IF;
END LOOP;
END;
/

i have created stored procedure but can't able to execute same

I defined a stored procedure
create or replace procedure spfirst
(
sp_loc out varchar,
sp_sal out int
)
as
begin
select LOCATION, MONTHLY_SALARY
into sp_loc, sp_sal
from nilesh;
end;
I then call the procedure and get an error
begin
spfirst;
end;
ORA-06550: line 2, column 1:
PLS-00201: identifier 'SPNAME' must be declared
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
Your procedure takes two parameters. You are calling it without any parameters. Oracle thus looks for a procedure named spfirst that takes no parameters, finds no such procedure, and throws an error.
Something like
DECLARE
l_location nilesh.location%type;
l_salary nilesh.monthly_salary%type;
BEGIN
spfirst( l_location, l_salary );
END;
should work. Of course, you'd generally want to do something with the variables that are returned. If you've enabled dbms_output, you could print them out
DECLARE
l_location nilesh.location%type;
l_salary nilesh.monthly_salary%type;
BEGIN
spfirst( l_location, l_salary );
dbms_output.put_line( 'Location = ' || l_location );
dbms_output.put_line( 'Salary = ' || l_salary );
END;
Be aware that your procedure will throw an error unless the nilesh table has exactly one row. It seems likely that you either want the procedure to take an additional parameter that is the key to the table so that the select into always returns a single row or that you want a function that returns a sys_refcursor rather than a procedure that has multiple out parameters.

PL/SQL DBMS_XMLQUERY max size

My oracle version is 11g release 2
Our system is using DBMS_XMLQUERY to transform sql result into xml, but recently the data is becoming large and we get this error: ORA-06502: PL/SQL: numeric or value error
The reason seems to be DBMS_XMLQUERY cannot handle too many records, but oracle's official document doesn't show the limitation. So maybe I have done something wrong. You can reproduce the problem in the following steps:
step1:
create table XMLDATA ( data_id int primary key, data_str
VARCHAR2(100) );
step2:
INSERT INTO XMLDATA values(1, 'test0123456789');
INSERT INTO XMLDATA values(2, 'test0123456789');
INSERT INTO XMLDATA values(3, 'test0123456789');
....
INSERT INTO XMLDATA values(500, 'test0123456789');
step3:
CREATE OR REPLACE
function test(total in int) return clob is
i int;
vn_ctx DBMS_XMLQUERY.ctxHandle;
BEGIN
vn_ctx := DBMS_XMLQUERY.NEWCONTEXT('select data_id, data_str from XMLDATA where rownum <= ' || total);
DBMS_XMLQuery.propagateOriginalException(vn_ctx,true);
DBMS_XMLQUERY.useNullAttributeIndicator(vn_ctx,true);
DBMS_XMLQUERY.SETROWTAG(vn_ctx, 'ITEM');
DBMS_XMLQUERY.SETROWSETTAG(vn_ctx, 'PODATA');
return DBMS_XMLQUERY.GETXML(vn_ctx);
END;
step4:
execute function test with a number greater than 400. Then you'll get 'ORA-06502: PL/SQL: numeric or value error'
thanks in advance
EDIT
Really sorry... I got the old code, someone adds a log statement without noticing me. The log statement can only accept a maximum of 32767 characters in one line, so the error is raised. The above function is executed by a debug tool, which gives the same error, so it's the tool's problem, not oracle.
Thanks for your answering and sorry for my naive mistakes...
I get no errors if the variable to hold the return value is big enough.
declare
rv1 clob;
rv2 varchar2(32000);
begin
rv1 := test(400); -- No error
rv2 := test(200); -- No error - returned XML is < 32000 in length.
rv2 := test(400); -- ORA-06502: PL/SQL: numeric or value error'
end;

Resources