I have this header of a stored procedure
PROCEDURE CONSULTAR_PR(
piinRegion IN NUMBER,
pistIdTramite IN VARCHAR2,
pistFolio IN NUMBER,
pistFzaVta IN VARCHAR2,
pistTipoTramite IN VARCHAR2,
pistCurp IN VARCHAR2,
potyTramite OUT PRE_TRAMITE_TYP,
potyCanal OUT NOCOPY PRE_CANAL_TYP,
potyCliente OUT NOCOPY PRE_CLIENTE_TYP,
potyContrato OUT NOCOPY PRE_CONTRATO_TYP,
potyDomicilios OUT NOCOPY SYS_REFCURSOR,
potyEquipo OUT NOCOPY PRE_EQUIPO_TYP,
potyFinanciamiento OUT NOCOPY PRE_FINAN_TYP,
potyCreditcheck OUT NOCOPY SYS_REFCURSOR,
potyFacturacion OUT NOCOPY PRE_FACTURACION_TYP,
potySuplementarios OUT NOCOPY SYS_REFCURSOR,
potyReferencias OUT NOCOPY SYS_REFCURSOR,
potyResumen OUT NOCOPY PRE_RESUMEN_TYP,
potyMigracion OUT NOCOPY PRE_MIGRACION_TYP) IS
...
and I'm trying to test with this script
set autoprint on;
VAR cursortemp1 PRE_TRAMITE_TYP;
VAR cursortemp2 PRE_CANAL_TYP;
VAR cursortemp3 PRE_CLIENTE_TYP;
VAR cursortemp4 PRE_CONTRATO_TYP;
VAR cursortemp5 REFCURSOR;
VAR cursortemp6 PRE_EQUIPO_TYP;
VAR cursortemp7 PRE_FINAN_TYP;
VAR cursortemp8 REFCURSOR;
VAR cursortemp9 PRE_FACTURACION_TYP;
VAR cursortemp10 REFCURSOR;
VAR cursortemp11 REFCURSOR;
VAR cursortemp12 PRE_RESUMEN_TYP;
VAR cursortemp13 PRE_MIGRACION_TYP;
EXEC PKG.CONSULTAR_PR(123, null, null, 'qwer', 'asdf', 'xxxxx',:cursortemp1,:cursortemp2 ,:cursortemp3,:cursortemp4,:cursortemp5,:cursortemp6,:cursortemp7,:cursortemp8,:cursortemp9,:cursortemp10,:cursortemp11,:cursortemp12,:cursortemp13);
However, some outputs are objects like the following
create TYPE PRE_RESUMEN_TYP AS OBJECT
(
COL1 VARCHAR2(50 Byte),
COL2 NUMBER,
COL3 NUMBER,
COL4 NUMBER,
COL5 NUMBER,
COL6 VARCHAR2(50 Byte),
COL7 NUMBER,
COL8 NUMBER,
COL9 NUMBER,
COL10 NUMBER,
COL11 NUMBER,
COL12 NUMBER,
COL13 NUMBER,
COL14 VARCHAR2(40 Byte)
);
I'm not an expert in SQL but I would like to know if it's possible to use objects as output, I have tested script where outputs are varchar, number or refcursor but this one I can't get it
You need an anonymous block to catch the output variables,eg
declare
l_potyTramite PRE_TRAMITE_TYP;
l_potyCanal PRE_CANAL_TYP;
l_potyCliente PRE_CLIENTE_TYP;
l_potyContrato PRE_CONTRATO_TYP;
l_potyDomicilios SYS_REFCURSOR;
l_potyEquipo PRE_EQUIPO_TYP;
l_potyFinanciamiento PRE_FINAN_TYP;
l_potyCreditcheck SYS_REFCURSOR;
l_potyFacturacion PRE_FACTURACION_TYP;
l_potySuplementarios SYS_REFCURSOR;
l_potyReferencias SYS_REFCURSOR;
l_potyResumen PRE_RESUMEN_TYP;
l_potyMigracion PRE_MIGRACION_TYP;
begin
CONSULTAR_PR(
piinRegion =>123
pistIdTramite =>'x'
pistFolio =>123
pistFzaVta =>'x'
pistTipoTramite =>'x'
pistCurp =>'x'
potyTramite => l_PRE_TRAMITE_TYP;
potyCanal => l_PRE_CANAL_TYP;
potyCliente => l_PRE_CLIENTE_TYP;
potyContrato => l_PRE_CONTRATO_TYP;
potyDomicilios => l_SYS_REFCURSOR;
potyEquipo => l_PRE_EQUIPO_TYP;
potyFinanciamiento => l_PRE_FINAN_TYP;
potyCreditcheck => l_SYS_REFCURSOR;
potyFacturacion => l_PRE_FACTURACION_TYP;
potySuplementarios => l_SYS_REFCURSOR;
potyReferencias => l_SYS_REFCURSOR;
potyResumen => l_PRE_RESUMEN_TYP;
potyMigracion => l_PRE_MIGRACION_TYP;
dbms_output.put_line(...);
end;
/
and then output them in a way the matches the object attributes
Related
I want to know if there exists something like Reflection API in PL/SQL or not.
I have a table like
create table my_table (
id number,
value1 number,
value2 number,
value3 number,
value4 number,
value5 number);
And I have a variable as
rec as my_table%rowtype
... fill rec
insert into my_table values rec;
is there any way I can populate rec field dynamically by its name.
I mean I know the index (in this case something between 1 and 5), so I want to set 'value'||index to something.
As in my real case the last index is much more than 5, using a set of if/elsif is not proper. By the way number of fields is increased in long term (for example value6, value7 ma be added next year and so on, so I wan to write some kind of code not to be changed on every new column).
You can access variables in a program using dynamic SQL only if they are available globally. If you declare you record in the spec you can build utility functions that will use EXECUTE IMMEDIATE to build a small PL/SQL block to set the value. Here is a simple example of what you are looking for. Notice you can overload the set procedure to keep your datatypes intact.
CREATE TABLE my_table (
value1 NUMBER,
value2 VARCHAR2(100),
value3 DATE);
CREATE OR REPLACE PACKAGE pkg_my_table IS
my_table_rec my_table%ROWTYPE;
FUNCTION build_statement(i_record IN VARCHAR2,
i_field IN VARCHAR2) RETURN VARCHAR2;
PROCEDURE set_value(i_record IN VARCHAR2,
i_field IN VARCHAR2,
i_value IN VARCHAR2);
PROCEDURE set_value(i_record IN VARCHAR2,
i_field IN VARCHAR2,
i_value IN NUMBER);
PROCEDURE set_value(i_record IN VARCHAR2,
i_field IN VARCHAR2,
i_value IN DATE);
PROCEDURE insert_a_row;
END pkg_my_table;
/
CREATE OR REPLACE PACKAGE BODY pkg_my_table IS
FUNCTION build_statement(i_record IN VARCHAR2,
i_field IN VARCHAR2) RETURN VARCHAR2 IS
BEGIN
RETURN 'BEGIN ' || lower($$PLSQL_UNIT) || '.' || i_record || '.' || i_field || ' := :x; END;';
END build_statement;
PROCEDURE set_value(i_record IN VARCHAR2,
i_field IN VARCHAR2,
i_value IN VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE build_statement(i_record => i_record,
i_field => i_field)
USING i_value;
END set_value;
PROCEDURE set_value(i_record IN VARCHAR2,
i_field IN VARCHAR2,
i_value IN NUMBER) IS
BEGIN
EXECUTE IMMEDIATE build_statement(i_record => i_record,
i_field => i_field)
USING i_value;
END set_value;
PROCEDURE set_value(i_record IN VARCHAR2,
i_field IN VARCHAR2,
i_value IN DATE) IS
BEGIN
EXECUTE IMMEDIATE build_statement(i_record => i_record,
i_field => i_field)
USING i_value;
END set_value;
PROCEDURE insert_a_row IS
BEGIN
my_table_rec := NULL;
set_value(i_record => 'my_table_rec',
i_field => 'value1',
i_value => 42);
set_value(i_record => 'my_table_rec',
i_field => 'value2',
i_value => 'forty-two');
set_value(i_record => 'my_table_rec',
i_field => 'value3',
i_value => to_date('1/1/1942',
'mm/dd/yyyy'));
INSERT INTO my_table
VALUES my_table_rec;
END insert_a_row;
END pkg_my_table;
/
BEGIN
pkg_my_table.insert_a_row;
END;
/
SELECT *
FROM my_table;
-- 42 forty-two 1/1/1942
Beware globals: you need to reset them correctly before using them again or you might get data carried over from previous invocations. Setting an entire record type variable to NULL will reset all the underlying fields (handy).
You will also be prone to ORA-04068: existing state of packages has been discarded errors should you compile PL/SQL with globals where there are active sessions referencing your code. Generally this is not a problem, but it is a behavioral difference.
I'm new in oracle pl/sql. I've created new package procedure list then I wanted to realise each procedure in seperate block. Here is list of procedures that I wanted creat for now it's only one.
create or replace package listProcedures is
procedure bss_claim12
( o_claim_id out number,
o_error_code out varchar2,
o_error_msg out varchar2,
i_card_number varchar2,
i_phone_number varchar2,
i_product_id number,
i_summ_loan number,
client_code number,
mfo varchar2
);
Then I wanted to create it's body but it's giving following errors.
Compilation errors for PACKAGE BODY IBS.LISTPROCEDURES
Error: PLS-00103: Encountered the symbol "end-of-file" when expecting
one of the following:
create or replace package body ibs.listprocedures is
procedure bss_claim12
( o_claim_id out number,
o_error_code out varchar2,
o_error_msg out varchar2,
i_card_number varchar2,
i_phone_number varchar2,
i_product_id number,
i_summ_loan number,
client_code number,
mfo varchar2
) is
begin
dbms_output.put_line(o_claim_id);
dbms_output.put_line(o_error_msg);
dbms_output.put_line(client_code);
end bss_claim12;
What should i do in body of this procedure to make it work well.
You should end both specification and body parts of the package :
SQL> create or replace package listProcedures is
procedure bss_claim12
( o_claim_id out number,
o_error_code out varchar2,
o_error_msg out varchar2,
i_card_number varchar2,
i_phone_number varchar2,
i_product_id number,
i_summ_loan number,
client_code number,
mfo varchar2
);
end listProcedures;
/
SQL> create or replace package body listProcedures is
procedure bss_claim12
( o_claim_id out number,
o_error_code out varchar2,
o_error_msg out varchar2,
i_card_number varchar2,
i_phone_number varchar2,
i_product_id number,
i_summ_loan number,
client_code number,
mfo varchar2
) is
begin
dbms_output.put_line(o_claim_id);
dbms_output.put_line(o_error_msg);
dbms_output.put_line(client_code);
end bss_claim12;
end listProcedures;
/
I'm creating Update Stored Procedure in Toad. When I'm executing the query it returns me an error like this.
1/51 PLS-00103: Encountered the symbol "(" when expecting one of the following:
:= . ) , # % default character
Heres my Code:
I've tried to change the AS to IN but still same error
Create Or Replace Procedure SP_EMPLOYEE_UPDATE(P_EMPLOYEEID VARCHAR2(20 CHAR),
P_EMPLOYEENAME VARCHAR2(100 CHAR),
P_STATUS VARCHAR2(50 CHAR),
P_SUPERIORID VARCHAR2(20 CHAR),
P_MANAGERSUPERIORID VARCHAR2(20 CHAR),
P_BFG VARCHAR2(10 CHAR),
P_DATEHIRED Date,
P_DESIGNATION VARCHAR2(100 CHAR),
P_JOBGRADE NUmber,
P_EMAILADDRESS VARCHAR2(100 CHAR),
P_PRODUCTLINE VARCHAR2(80 BYTE),
P_STATION VARCHAR2(80 BYTE),
P_MACHINE VARCHAR2(80 BYTE),
P_OPERATIONGROUP VARCHAR2(80 BYTE),
P_ISACTIVE VARCHAR2(1 BYTE))
AS
Begin
Update REFEMPLOYEES set REFEMPLOYEES.EMPLOYEENAME = P_EMPLOYEENAME , REFEMPLOYEES.STATUS= P_STATUS,REFEMPLOYEES.SUPERIORID = P_SUPERIORID,REFEMPLOYEES.MANAGERSUPERIORID= P_MANAGERSUPERIORID,REFEMPLOYEES.BFG = P_BFG,
REFEMPLOYEES.DATEHIRED = P_DATEHIRED,REFEMPLOYEES.DESIGNATION = P_DESIGNATION,REFEMPLOYEES.JOBGRADE = P_JOBGRADE,REFEMPLOYEES.EMAILADDRESS = P_EMAILADDRESS,REFEMPLOYEES.PRODUCTLINE = P_PRODUCTLINE,REFEMPLOYEES.STATION = P_STATION,
REFEMPLOYEES.MACHINE = P_MACHINE,REFEMPLOYEES.OPERATIONGROUP = P_OPERATIONGROUP,REFEMPLOYEES.ISACTIVE = P_ISACTIVE
Where REFEMPLOYEES.EMPLOYEEID = P_EMPLOYEEID;
End
Your code should look like following ideally:
CREATE OR REPLACE PROCEDURE SP_EMPLOYEE_UPDATE (
P_EMPLOYEEID VARCHAR2,
P_EMPLOYEENAME VARCHAR2,
P_STATUS VARCHAR2,
P_SUPERIORID VARCHAR2,
P_MANAGERSUPERIORID VARCHAR2,
P_BFG VARCHAR2,
P_DATEHIRED DATE,
P_DESIGNATION VARCHAR2,
P_JOBGRADE NUMBER,
P_EMAILADDRESS VARCHAR2,
P_PRODUCTLINE VARCHAR2,
P_STATION VARCHAR2,
P_MACHINE VARCHAR2,
P_OPERATIONGROUP VARCHAR2,
P_ISACTIVE VARCHAR2
) AS
BEGIN
UPDATE REFEMPLOYEES
SET
REFEMPLOYEES.EMPLOYEENAME = P_EMPLOYEENAME,
REFEMPLOYEES.STATUS = P_STATUS,
REFEMPLOYEES.SUPERIORID = P_SUPERIORID,
REFEMPLOYEES.MANAGERSUPERIORID = P_MANAGERSUPERIORID,
REFEMPLOYEES.BFG = P_BFG,
REFEMPLOYEES.DATEHIRED = P_DATEHIRED,
REFEMPLOYEES.DESIGNATION = P_DESIGNATION,
REFEMPLOYEES.JOBGRADE = P_JOBGRADE,
REFEMPLOYEES.EMAILADDRESS = P_EMAILADDRESS,
REFEMPLOYEES.PRODUCTLINE = P_PRODUCTLINE,
REFEMPLOYEES.STATION = P_STATION,
REFEMPLOYEES.MACHINE = P_MACHINE,
REFEMPLOYEES.OPERATIONGROUP = P_OPERATIONGROUP,
REFEMPLOYEES.ISACTIVE = P_ISACTIVE
WHERE
REFEMPLOYEES.EMPLOYEEID = P_EMPLOYEEID;
END SP_EMPLOYEE_UPDATE;
/
Cheers!!
EXEC USP_USER_INSERT (P_ID = '2', P_FIRST_NAME = 'A', P_LAST_NAME = 'BALAJI', P_SALARY = '50000', P_CITY = 'CHENNAI');
EXEC USP_USER_INSERT #P_ID = '2', #P_FIRST_NAME = 'A', #P_LAST_NAME = 'BALAJI', #P_SALARY = '50000', #P_CITY = 'CHENNAI';
Both are showing error, how to call this SP.
create or replace procedure USP_USER_INSERT
(
P_FIRST_NAME in varchar default null,
P_LAST_NAME in varchar default null,
P_SALARY in number default null,
P_CITY in varchar default null,
P_EMAIL_ID in varchar default null,
P_EMP_ID in number default null,
P_ADDED_BY in number default null,
P_WINDOWS_ID in varchar2 default null,
P_USER_TYPE in number default null,
P_PASSWORD in varchar2 default null,
P_ROLE in varchar2 default null,
RES OUT SYS_REFCURSOR
)
as
P_ID NUMBER;
begin
select NVL(max(ID),0)+1 into P_ID from USER_MASTER ;
insert into USER_MASTER
(
ID,FIRST_NAME,
LAST_NAME,
SALARY,
CITY,
EMAIL_ID,
EMP_ID,
ADDED_ON,
ADDED_BY,
WINDOWS_ID,
IS_ACTIVE,
USER_TYPE,
PASSWORD,
role
)
values (
P_ID,P_FIRST_NAME,
P_LAST_NAME,
P_SALARY,
P_CITY,
P_EMAIL_ID,
P_EMP_ID,
Systimestamp,
P_ADDED_BY,
P_WINDOWS_ID,
1,
P_USER_TYPE,
P_PASSWORD,
P_ROLE
);
open RES for
SELECT P_ID "P_ID" FROM DUAL;
END;
Define a cursor bind variable and then wrap the procedure call in an anonymous PL/SQL block:
VARIABLE cur REFCURSOR;
BEGIN
USP_USER_INSERT (
P_EMP_ID => '2', -- P_ID is not an argument to the procedure
P_FIRST_NAME => 'A',
P_LAST_NAME => 'BALAJI',
P_SALARY => '50000',
P_CITY => 'CHENNAI',
RES => :cur
);
END;
/
PRINT cur;
try this
Procedure has not return value, if you need you can use function
exec USP_USER_INSERT ( par1,par2,....)
if you are running it on command line, you should have / at the end of sql code.
try this use single quotes if 2 is of varchar else leave as it is,
EXEC USP_USER_INSERT '2','A','BALAJI','50000','CHENNAI'
How can i call procedure inside another procedure in Oracle?I'm trying as follow but i am getting that error "PLS-00306 (325: 13): PLS-00306: wrong number or types of arguments in call to 'TITLE_CRUD'"
PROCEDURE create_title(
P_TITLE varchar2,
P_USER varchar2,
P_ERR OUT VARCHAR2
)
IS
BEGIN
IF P_TITLE IS NULL THEN
P_ERR := 'Null value';
ELSE
title_crud('I',NULL,P_TITLE,P_USER);
END IF;
END;
PROCEDURE title_crud(
P_OP_TYPE VARCHAR2,
P_ID number,
P_TITLE varchar2,
P_USER varchar2,
P_ERR OUT VARCHAR2
)...
See the change below, the call to title_crud doesn't have a variable to hold what is being returned by it (p_err)
PROCEDURE create_title(
P_TITLE varchar2,
P_USER varchar2,
P_ERR OUT VARCHAR2
)
IS
BEGIN
IF P_TITLE IS NULL THEN
P_ERR := 'Null value';
ELSE
title_crud('I',NULL,P_TITLE,P_USER,P_ERR); -- Extra Parameter
END IF;
END;
PROCEDURE title_crud(
P_OP_TYPE VARCHAR2,
P_ID number,
P_TITLE varchar2,
P_USER varchar2,
P_ERR OUT VARCHAR2
)...
An easy mistake to make but I find easier to avoid when calling a procedure you pass parameters by named notation. Your call to title_crud becomes
...
title_crud(P_OP_TYPE => 'I',
P_ID => NULL,
P_TITLE => P_TITLE,
P_USER => P_USER,
P_ERR => P_ERR);
...