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.
Related
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>
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.
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.
I am trying to do a stored procedure in SQL Developer, which returns multiple records from a single table. But when I call the procedure, it returns the empty variables (taking into account that the table has records).
CREATE OR REPLACE PROCEDURE PURE_ENC_SELECCIONAR_INTERACCIONES(
startDate IN varchar2,
endDate IN varchar2,
o_interactionId OUT PURE_ENC_INTERACTION.INTERACTIONID%TYPE,
o_interactionDate OUT PURE_ENC_INTERACTION.INTERACTIONDATE%TYPE,
o_queueId OUT PURE_ENC_INTERACTION.QUEUEID%TYPE,
o_personId OUT PURE_ENC_INTERACTION.PERSONID%TYPE,
o_numSolicitud OUT PURE_ENC_INTERACTION.NUMSOLICITUD%TYPE,
o_customerDni OUT PURE_ENC_INTERACTION.CUSTOMERDNI%TYPE,
o_customerName OUT PURE_ENC_INTERACTION.CUSTOMERNAME%TYPE,
o_ani OUT PURE_ENC_INTERACTION.ANI%TYPE,
o_dnis OUT PURE_ENC_INTERACTION.DNIS%TYPE,
o_custom1 OUT PURE_ENC_INTERACTION.CUSTOM1%TYPE,
o_custom2 OUT PURE_ENC_INTERACTION.CUSTOM2%TYPE,
o_custom3 OUT PURE_ENC_INTERACTION.CUSTOM3%TYPE,
o_custom4 OUT PURE_ENC_INTERACTION.CUSTOM4%TYPE,
o_custom5 OUT PURE_ENC_INTERACTION.CUSTOM5%TYPE)
IS
BEGIN
FOR loop_int IN (
SELECT INTERACTIONID, INTERACTIONDATE, QUEUEID, PERSONID, NUMSOLICITUD, CUSTOMERDNI,
CUSTOMERNAME, ANI, DNIS, CUSTOM1, CUSTOM2, CUSTOM3, CUSTOM4, CUSTOM5
INTO o_interactionId, o_interactionDate, o_queueId, o_personId, o_numSolicitud,
o_customerDni, o_customerName, o_ani, o_dnis, o_custom1, o_custom2, o_custom3,
o_custom4, o_custom5
FROM PURE_ENC_INTERACTION )
--WHERE INTERACTIONDATE >= startDate AND INTERACTIONDATE < endDate )
LOOP
DBMS_OUTPUT.PUT_LINE('InteractionID: '|| o_interactionId);
END LOOP loop_int;
END;
I execute the procedure:
SET serveroutput ON
DECLARE
o_interactionId VARCHAR2(200);
o_interactionDate VARCHAR2(200);
o_queueId VARCHAR2(200);
o_personId VARCHAR2(200);
o_numSolicitud VARCHAR2(200);
o_customerDni VARCHAR2(200);
o_customerName VARCHAR2(200);
o_ani VARCHAR2(200);
o_dnis VARCHAR2(200);
o_custom1 VARCHAR2(200);
o_custom2 VARCHAR2(200);
o_custom3 VARCHAR2(200);
o_custom4 VARCHAR2(200);
o_custom5 VARCHAR2(200);
BEGIN
PURE_ENC_SELECCIONAR_INTERACCIONES(
'2019-10-20T12:30:03',
'2019-10-29T03:30:03',
o_interactionId,
o_interactionDate,
o_queueId,
o_personId,
o_numSolicitud,
o_customerDni,
o_customerName,
o_ani,
o_dnis,
o_custom1,
o_custom2,
o_custom3,
o_custom4,
o_custom5);
END;
When I run it, returns:
Procedimiento PL/SQL terminado correctamente.
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
When I run this sample:
SELECT INTERACTIONID, INTERACTIONDATE, QUEUEID , PERSONID , NUMSOLICITUD , CUSTOMERDNI , CUSTOMERNAME , ANI , DNIS , CUSTOM1,CUSTOM2 ,CUSTOM3 ,CUSTOM4 ,CUSTOM5
FROM PURE_ENC_INTERACTION;
It returns all the registers fine.
What could be the problem?
Well, you didn't post what you exactly have. How do I know? Because the procedure has syntax errors. You can't use cursor FOR loop like that; INTO is required for SELECT statements in PL/SQL, but not where you used it.
Simplified, on Scott's schema, this is what you did:
SQL> create or replace procedure p_test (par_deptno in number, par_ename out varchar2) is
2 begin
3 for cur_r in (select ename from emp into par_ename
4 where deptno = par_deptno)
5 loop
6 dbms_output.put_line('Ename: ' || par_ename);
7 end loop;
8 end;
9 /
Warning: Procedure created with compilation errors.
SQL> show err
Errors for PROCEDURE P_TEST:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/17 PL/SQL: SQL Statement ignored
3/39 PL/SQL: ORA-00933: SQL command not properly ended
SQL>
As I said: your code is invalid.
This, on the other hand, is valid:
SQL> create or replace procedure p_test (par_deptno in number, par_ename out varchar2) is
2 begin
3 for cur_r in (select ename from emp
4 where deptno = par_deptno)
5 loop
6 par_ename := cur_r.ename;
7 dbms_output.put_line('Ename from P_TEST: ' || par_ename);
8 end loop;
9 end;
10 /
Procedure created.
SQL> declare
2 l_ename varchar2(20);
3 begin
4 p_test (10, l_ename);
5 dbms_output.put_line('Ename from anonymous PL/SQL block: ' || l_ename);
6 end;
7 /
Ename from P_TEST: CLARK
Ename from P_TEST: KING
Ename from P_TEST: MILLER
Ename from anonymous PL/SQL block: MILLER
PL/SQL procedure successfully completed.
SQL>
But, it is wrong (logically). The procedure fetched all employees (Clark, King, Miller), but the caller (i.e. the anonymous PL/SQL block) got only one value: the last one fetched by the cursor.
I doubt that this is what you want; doesn't make sense.
I don't know what you really want; perhaps it is to return all rows that satisfy certain condition. If that's the case, you can't return scalar values, that should be *something
else*. Ref cursor is one option, but - you don't need a procedure with bunch of parameters, then - maybe a function is a better option. For example:
SQL> create or replace function f_test (par_deptno in number)
2 return sys_refcursor
3 is
4 l_rc sys_refcursor;
5 begin
6 open l_rc for select ename from emp where deptno = par_deptno;
7 return l_rc;
8 end;
9 /
Function created.
SQL> select f_test(10) from dual;
F_TEST(10)
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ENAME
----------
CLARK
KING
MILLER
SQL>
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>