How to run select statement after stored procedure run ORACLE - oracle

I am new to Oracle, trying to run select statement after my stored procedure and failing. Here I am trying to return rows or any dummy data after my store procedure is executed, because my end process needs a return data for sure to make it consider as successful run. Is there any way I can trick it here is what I tried and failed.
EX:
BEGIN
note.name;
END;
/
SELECT * from hello.table where rownum=1;
Error:
ERROR [HY000] [Microsoft][ODBC Oracle Wire Protocol driver][Oracle]ORA-06550: line 4, column 1:
PLS-00103: Encountered the symbol "/"
Activity ID: xxxxxx-xxx-xxx-xxx-xxxxxx
Show return a single row after completion of stored procedure

Code you posted looks OK. Demo:
SQL> create or replace procedure p_test as
2 begin
3 null;
4 end;
5 /
Procedure created.
SQL> begin
2 p_test;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> select * from dept where rownum = 1;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
SQL>
Therefore, what exactly is your problem? What result do you expect?
If "at once" (as you commented) means that everything should be part of a PL/SQL block, then you'd declare a variable which is capable of holding the whole row, and then just select into it. rownum = 1 condition prevents too_many_rows error.
SQL> set serveroutput on
SQL>
SQL> declare
2 l_dept dept%rowtype;
3 begin
4 p_test;
5 select * into l_dept from dept where rownum = 1;
6 dbms_output.put_line(l_dept.deptno ||', '|| l_dept.dname ||', '|| l_dept.loc);
7 end;
8 /
10, ACCOUNTING, NEW YORK
PL/SQL procedure successfully completed.
SQL>

Related

create a procedure to create a table in Pl/sql from a select statement

I have a select query
select s.site, s.date, s.loaction, s.modified, sysdate p_run_date
from table s
where s.site = 123 --p_site
and s.date >= sysdate -p_date.
i want to create a pl/sql procedure to create a table where p_date and p_site need to be input to the procedure
Why would you want to do that? We normally do NOT create tables dynamically (which is what you'd use in PL/SQL). That procedure would try to create a table with the same name every time you call it (but with different parameters) and fail because table with such a name already exists (as it was created the first time you ran the procedure). Therefore, having a one-time procedure is pretty much useless.
If it must be done, oh well ...
SQL> create or replace procedure p_test (par_deptno in number, par_job in varchar2)
2 is
3 l_str varchar2(200);
4 begin
5 l_str := 'create table my_test as ' ||
6 'select deptno, ename, job, sal ' ||
7 'from emp ' ||
8 'where deptno = ' || dbms_assert.enquote_literal(par_deptno) ||
9 ' and job = ' || dbms_assert.enquote_literal(par_job);
10 execute immediate l_str;
11 end;
12 /
Procedure created.
Testing:
SQL> exec p_test(10, 'CLERK');
PL/SQL procedure successfully completed.
SQL> select * from my_test;
DEPTNO ENAME JOB SAL
---------- ---------- --------- ----------
10 MILLER CLERK 1300
Let's try it again, with different parameters:
SQL> exec p_test(20, 'MANAGER');
BEGIN p_test(20, 'MANAGER'); END;
*
ERROR at line 1:
ORA-00955: name is already used by an existing object
ORA-06512: at "SCOTT.P_TEST", line 10
ORA-06512: at line 1
SQL>
As I said, it'll fail. What you're trying to do is just wrong. You'd rather create a view.

Oracle: create stored procedure to insert results from another stored procedure into a table

I have an Oracle stored procedure spFinTest that I use in an SSRS report.
I wish to create another stored procedure spFinTestInsert that takes the output of spFinTest and inserts it into a table sbceybudget_financial_year.
I can create an all in one stored procedure that inserts the data into the destination table, but what I am looking to achieve is to just have the one stored procedure that can have code updates for data extracts and not to have to update a second separate insert stored procedure that has the same code.
So, update in one place only and reuse the same stored procedure.
The following is a simplified version of the main stored procedure:
create or replace procedure spFINTEST
(s1 OUT SYS_REFCURSOR)
AS
BEGIN
OPEN s1 FOR
SELECT
FIN_YR + 1 AS FIN_YR,
SCHOOL_YEAR_WEEKS
FROM
sbceybudget_financial_year
WHERE
fin_yr = 2021
;
END spFINTEST;
This stored procedure only has an "out" variable.
The final intention is once I can do this, then I will call spFinTestInsert from an "Execute SQL Task" in an SSIS package.
I'm a bit stumped as to how I create this second stored procedure that calls the first and inserts the results into a named table, so if anyone can help I would be most grateful.
I would do this in a package: it allows you to declare cursor type easily to make it more clear.
Test table:
create table sbceybudget_financial_year(
fin_yr int,
SCHOOL_YEAR_WEEKS int
)
/
Package specification:
create or replace package pkg_spFIN as
type spFIN_RowType is record(
FIN_YR sbceybudget_financial_year.FIN_YR%type,
SCHOOL_YEAR_WEEKS sbceybudget_financial_year.SCHOOL_YEAR_WEEKS%type
);
type spFIN_CurType IS REF CURSOR RETURN spFIN_RowType;
type spFIN_tab is table of spFIN_RowType;
procedure spFINTEST (s1 OUT SYS_REFCURSOR);
procedure spFinTestInsert;
end pkg_spFIN;
/
Package body:
create or replace package body pkg_spFIN as
function get_cursor(n int) return spFIN_CurType is
c spFIN_CurType;
begin
open c for
SELECT
t.FIN_YR + 1 AS FIN_YR,
t.SCHOOL_YEAR_WEEKS
FROM
sbceybudget_financial_year t
WHERE
t.fin_yr = n;
return c;
end;
procedure spFINTEST (s1 OUT SYS_REFCURSOR)
is
begin
s1:=get_cursor(2021);
end spFINTEST;
procedure spFinTestInsert
is
cur spFIN_CurType;
tab spFIN_tab;
begin
pkg_spFIN.spFINTEST(cur);
loop
fetch cur bulk collect into tab limit 100;
exit when tab.count()=0;
for i in 1..tab.count loop
dbms_output.put_line(tab(i).FIN_YR);
dbms_output.put_line(tab(i).SCHOOL_YEAR_WEEKS);
-- or insert:
-- insert into sbceybudget_financial_year(fin_yr, SCHOOL_YEAR_WEEKS)
-- values(tab(i).FIN_YR, SCHOOL_YEAR_WEEKS)
-- you can change it to FORALL insert
end loop;
end loop;
end spFinTestInsert;
end pkg_spFIN;
/
Test data:
begin
insert into sbceybudget_financial_year(fin_yr, SCHOOL_YEAR_WEEKS) values(2019,19);
insert into sbceybudget_financial_year(fin_yr, SCHOOL_YEAR_WEEKS) values(2020,20);
insert into sbceybudget_financial_year(fin_yr, SCHOOL_YEAR_WEEKS) values(2021,21);
commit;
end;
/
And finally test call:
call pkg_spFIN.spFinTestInsert();
Full example on DBFiddle: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=c31a5714e5db74eaa3a83fae03964349
I don't have your tables so I'll use Scott's DEPT for illustration.
This is the "target" table; values fetched by ref cursor will be inserted into it:
SQL> create table test_dept as select deptno, dname from dept where 1 = 2;
Table created.
This is data I expect:
SQL> select deptno, dname from dept where deptno <= 20;
DEPTNO DNAME
---------- --------------
10 ACCOUNTING
20 RESEARCH
This is your current procedure:
SQL> create or replace procedure spfintest (s1 out sys_refcursor)
2 as
3 begin
4 open s1 for select deptno, dname from dept where deptno <= 20;
5 end spfintest;
6 /
Procedure created.
This is a procedure which calls spfintest and inserts values into test_dept:
SQL> create or replace procedure spfitestinsert as
2 rc sys_refcursor;
3 --
4 l_deptno dept.deptno%type;
5 l_dname dept.dname%type;
6 begin
7 spfintest(rc);
8 loop
9 fetch rc into l_deptno, l_dname;
10 exit when rc%notfound;
11
12 insert into test_dept (deptno, dname)
13 values (l_deptno, l_dname);
14 end loop;
15 end;
16 /
Procedure created.
Testing:
SQL> exec spfitestinsert;
PL/SQL procedure successfully completed.
SQL> select * from test_dept;
DEPTNO DNAME
---------- --------------
10 ACCOUNTING
20 RESEARCH
SQL>
Everything is here, so I guess it works.

PLSQL : ORA-14551: cannot perform a DML operation inside a query

I went through some of the already answered questions, mentioned below, but could not find a solution that worked for me.
ORA-14551: cannot perform a DML operation inside a query
ORA-14551: cannot perform a DML operation inside a query error while using Execute immediate
I have written this within a function, that I am calling from a procedure.
OPEN c_rules_details;
LOOP
FETCH c_rules_details INTO rule_conditions_record;
EXIT WHEN c_rules_details %notfound;
dbms_output.put_line('Range and rule is '|| rule_conditions_record.rdr_tmplt_id || rule_conditions_record.rdr_rng_from ||rule_conditions_record.rdr_rng_to);
SELECT COUNT(*) INTO v_balance_records FROM t_scb_temp_objects WHERE RULE_CONDITION=rule_conditions_record.rdr_tmplt_id AND CHARGE is NULL;
dbms_output.put_line('Number of records in rule are '|| v_balance_records);
IF v_balance_records>rule_conditions_record.rdr_rng_from AND v_balance_records<rule_conditions_record.rdr_rng_to THEN
v_ssql_stmnt:='UPDATE t_scb_temp_objects
SET CHARGE='||rule_conditions_record.rfr_chrg_amt||' WHERE RULE_CONDITION='||rule_conditions_record.rdr_tmplt_id;
EXECUTE IMMEDIATE v_ssql_stmnt;
END IF;
END LOOP;
CLOSE c_rules_details;
That's what you've been told - you can't perform DML (in your case, UPDATE t_scb_temp_objects ...) within a function you're (somehow - you didn't show how) calling from a procedure. That might be - for example:
create or replace function f_test (par_deptno in number)
return number
is
...
begin
open c_rules_details;
loop
-- your current code goes here
execute immediate v_sql_stmnt;
end loop;
return 1;
end;
create or replace procedure p_test is
l_ename emp.ename%type;
begin
select e.ename
into l_ename
from emp e
where e.deptno = f_test(e.deptno); --> this will cause the error
end;
So, what to do? Perform UPDATE from within a procedure, not a function.
If it must be a function, make it an autonomous transaction (using PRAGMA), but that's something I wouldn't recommend. You'd rather figure something different out. Here's how, though:
SQL> create table test (col number);
Table created.
SQL> insert into test (col) values (100);
1 row created.
SQL> commit;
Commit complete.
First, a function that'll fail (just like yours):
SQL> create or replace function f_test return number is
2 begin
3 update test set col = 10;
4 commit;
5 return 1;
6 end;
7 /
Function created.
SQL> select f_test from dual;
select f_test from dual
*
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "SCOTT.F_TEST", line 3
Now, the one which will succeed:
SQL> create or replace function f_test return number is
2 pragma autonomous_transaction; --> this
3 begin
4 update test set col = 10;
5 commit;
6 return 1;
7 end;
8 /
Function created.
SQL> select f_test from dual;
F_TEST
----------
1
SQL> select * from test;
COL
----------
10
SQL>
Once again: you probably don't want to do that.

Simple Oracle Procedure Failing

I have a very simple test proc:
create or replace PROCEDURE TestSproc
(userName in VARCHAR2, p_Test OUT SYS_REFCURSOR)IS
BEGIN
OPEN p_Test FOR
SELECT * FROM Test_Table
WHERE name = userName ;
END TestSproc;
When I run the proc (ctrl f10) in sqldeveloper on the proc page I get the result I would expect. But when I try to call the proc with the below query I get the error:
Error starting at line : 1 in command - begin DB.TestSproc('Phil'); end;
Error report - ORA-06550: line 2, column 1:
PLS-00306: wrong number or types of arguments in call to 'TestSproc'
ORA-06550: line 2, column 1: PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
begin
DB.TestSproc('Phil');
end;
Can anyone please point me in the correct direction.
EDIT
In SQL Server I would simply do:
USE DB;
GO
EXEC dbo.TestSproc#Name= 'Phil';
Assuming you are using Oracle 12c with a 12c client:
create or replace procedure testsproc
( username in varchar2 )
as
resultset sys_refcursor;
begin
open resultset for
select * from test_table
where name = username;
dbms_sql.return_result(resultset);
end testsproc;
Then call it with
exec testsproc('Phil')
or
call testsproc('Phil');
or
begin
testsproc('Phil');
end;
depending on what you are calling it from.
Further reading
You have to put the output somewhere, so - declare an appropriate variable:
SQL> create or replace procedure p_test (par_deptno in number, p_emps out sys_refcursor) is
2 begin
3 open p_emps for
4 select deptno, empno, ename
5 from emp
6 where deptno = par_deptno;
7 end;
8 /
Procedure created.
SQL>
SQL> var l_out refcursor
SQL>
SQL> begin
2 p_test(10, :l_out);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL>
SQL> print :l_out;
DEPTNO EMPNO ENAME
---------- ---------- ----------
10 7839 KING
10 7782 CLARK
10 7934 MILLER
SQL>

call procedure inside sqlplus

I am working with a sqlplus code and plsql, my procedure in plsql works fine but when i execute procedure inside sql plus I encounter some error report.
heres my code:
set serveroutput on;
DECLARE
ENDDATE DATE;
BEGIN
SELECT SOME_DATE INTO ENDDATE FROM HEADER WHERE ID=1182446;
IF ENDDATE >= TO_DATE('18-MAY-13') THEN
EXECUTE SOMEPROCEDURE(1182446);
END IF;
END;
Error report -
ORA-06550: line 8, column 8:
PLS-00103: Encountered the symbol "SOMEPROCEDURE" when expecting one of the following:
:= . ( # % ;
The symbol ":=" was substituted for "SOMEPROCEDURE" to continue.
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
IF ENDDATE >= TO_DATE('18-MAY-13') THEN
EXECUTE SOMEPROCEDURE(1182446);
END IF;
Since you are calling the procedure in an anonymous PL/SQL block, EXECUTE command is not required, since it is a SQL*Plus command and not PL/SQL.
You could simply call the procedure as:
IF ENDDATE >= TO_DATE('18-MAY-13') THEN
SOMEPROCEDURE(1182446);
END IF;
If you want to execute the procedure alone in SQL*Plus, then you could use the EXECUTE or EXEC command.
For example,
In SQL*Plus:
SQL> CREATE OR REPLACE
2 PROCEDURE get_emp(
3 emp_no IN emp.empno%type,
4 dept_no OUT emp.deptno%type )
5 AS
6 BEGIN
7 SELECT deptno INTO dept_no FROM emp WHERE empno = emp_no;
8 END;
9 /
Procedure created.
SQL> var dno number
SQL> var eno number
SQL> exec :eno := 7369
PL/SQL procedure successfully completed.
SQL> EXEC get_emp(:eno, :dno);
PL/SQL procedure successfully completed.
SQL> print dno
DNO
----------
20
SQL>
If you want to call the procedure inside another PL/SQL block, then you could do it as:
Anonymous PL/SQL block:
SQL> set serveroutput on
SQL> DECLARE
2 dt DATE;
3 dept_no NUMBER;
4 BEGIN
5 SELECT hiredate INTO dt FROM emp WHERE empno = 7369;
6 IF dt < SYSDATE THEN
7 get_emp(7369, dept_no);
8 DBMS_OUTPUT.PUT_LINE('Department number is '||dept_no);
9 END IF;
10 END;
11 /
Department number is 20
PL/SQL procedure successfully completed.

Resources