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;
/
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 have this procedure into a package, and I need to return the count of a table, but I don't know how do this. I have this and it doesn't work.
PROCEDURE OBTENER_TOTALCAMPAĆA(TOTAL OUT NUMBER)
IS
row_count number;
BEGIN
SELECT COUNT(*) AS TOTAL_CARTERA INTO row_count FROM CLIENTE
RETURNING row_count INTO TOTAL;
END;
Try this. You don't need to say returning in this case. Returning is typically used in inserts that you need to get the id from after the row is inserted. In your case, just fill the output param with the select ... INTO from ....
PROCEDURE OBTENER_TOTALCAMPAĆA(TOTAL OUT NUMBER)
IS
BEGIN
SELECT COUNT(*) AS TOTAL_CARTERA INTO TOTAL FROM CLIENTE;
END;
Buena suerte
try this. it works for me. create oracle package
create or replace PACKAGE LEVEL_CRUD AS
PROCEDURE INSERT_LEVEL_DATA (
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
P_LEVEL_NAME IN APP_LEVEL_MASTER.LEVEL_NAME%TYPE,
P_CREATED_BY IN APP_LEVEL_MASTER.CREATED_BY%TYPE,
P_CREATE_DATE IN VARCHAR2,
P_UPDATE_DATE IN VARCHAR2
);
PROCEDURE FETCH_LEVEL_DATA (
LEVEL_C OUT SYS_REFCURSOR
);
PROCEDURE UPDATE_LEVEL_DATA (
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
P_LEVEL_NAME IN APP_LEVEL_MASTER.LEVEL_NAME%TYPE,
P_CREATED_BY IN APP_LEVEL_MASTER.CREATED_BY%TYPE,
P_CREATE_DATE IN APP_LEVEL_MASTER.CREATE_DATE%TYPE,
P_UPDATE_DATE IN varchar2,
P_UPDATE_COUNT OUT NUMBER
);
PROCEDURE GET_LEVEL_RECORD_ID_WISE(
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
LEVEL_C OUT SYS_REFCURSOR
);
PROCEDURE DELETE_LEVEL_DATA(
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
DELETE_C OUT NUMBER
);
END LEVEL_CRUD;
create package body where actual procedure is available and sql query will return count and data
create or replace PACKAGE BODY LEVEL_CRUD AS
PROCEDURE INSERT_LEVEL_DATA (
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
P_LEVEL_NAME IN APP_LEVEL_MASTER.LEVEL_NAME%TYPE,
P_CREATED_BY IN APP_LEVEL_MASTER.CREATED_BY%TYPE,
P_CREATE_DATE IN VARCHAR2,
P_UPDATE_DATE IN VARCHAR2
) AS
BEGIN
INSERT INTO APP_LEVEL_MASTER
( LEVEL_ID,LEVEL_NAME,CREATED_BY,CREATE_DATE,UPDATE_DATE,STATUS)
VALUES ( ESC_LEVEL_ID.NEXTVAL,P_LEVEL_NAME,P_CREATED_BY,SYSDATE,SYSDATE,1);
END INSERT_LEVEL_DATA;
PROCEDURE FETCH_LEVEL_DATA (
LEVEL_C OUT SYS_REFCURSOR
) AS
BEGIN
open LEVEL_C FOR
SELECT * FROM APP_LEVEL_MASTER where STATUS = 1;
END FETCH_LEVEL_DATA;
PROCEDURE UPDATE_LEVEL_DATA (
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
P_LEVEL_NAME IN APP_LEVEL_MASTER.LEVEL_NAME%TYPE,
P_CREATED_BY IN APP_LEVEL_MASTER.CREATED_BY%TYPE,
P_CREATE_DATE IN APP_LEVEL_MASTER.CREATE_DATE%TYPE,
P_UPDATE_DATE IN varchar2,
P_UPDATE_COUNT OUT NUMBER
) AS
BEGIN
UPDATE APP_LEVEL_MASTER AUM
SET
AUM.LEVEL_NAME = P_LEVEL_NAME,
AUM.CREATED_BY = P_CREATED_BY,
AUM.CREATE_DATE= TO_DATE(P_CREATE_DATE,'DD/MM/YYYY'),
AUM.UPDATE_DATE=TO_DATE(sysdate)
WHERE AUM.LEVEL_ID = P_LEVEL_ID;
P_UPDATE_COUNT:=SQL%ROWCOUNT;
END UPDATE_LEVEL_DATA;
PROCEDURE GET_LEVEL_RECORD_ID_WISE(
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
LEVEL_C OUT SYS_REFCURSOR
)AS
BEGIN
OPEN LEVEL_C FOR
SELECT * FROM APP_LEVEL_MASTER WHERE LEVEL_ID=P_LEVEL_ID;
END GET_LEVEL_RECORD_ID_WISE;
PROCEDURE DELETE_LEVEL_DATA(
P_LEVEL_ID IN APP_LEVEL_MASTER.LEVEL_ID%TYPE,
DELETE_C OUT NUMBER
)AS
BEGIN
UPDATE APP_LEVEL_MASTER SET STATUS='0' WHERE LEVEL_ID=P_LEVEL_ID;
DELETE_C:=SQL%ROWcOUNT;
END DELETE_LEVEL_DATA;
END LEVEL_CRUD;
I have a procedure that takes some input variables with these names:
KEYWORD1 IN VARCHAR2,
KEYWORD1_VAL IN VARCHAR2,
KEYWORD2 IN VARCHAR2,
KEYWORD2_VAL IN VARCHAR2,
KEYWORD3 IN VARCHAR2,
KEYWORD3_VAL IN VARCHAR2,
KEYWORD4 IN VARCHAR2,
KEYWORD4_VAL IN VARCHAR2,
KEYWORD5 IN VARCHAR2,
KEYWORD5_VAL IN VARCHAR2,
KEYWORD6 IN VARCHAR2,
KEYWORD6_VAL IN VARCHAR2,
KEYWORD7 IN VARCHAR2,
KEYWORD7_VAL IN VARCHAR2,
KEYWORD8 IN VARCHAR2,
KEYWORD8_VAL IN VARCHAR2,
KEYWORD9 IN VARCHAR2,
KEYWORD9_VAL IN VARCHAR2,
KEYWORD10 IN VARCHAR2,
KEYWORD10_VAL IN VARCHAR2
I want to loop through 1-10 and do something like this:
FOR X IN 1..10
LOOP
IF KEYWORDX = 'CLI_RID' THEN
UPDATE FD_TABLE FD_CLI_RID = TO_NUMBER(KEYWORDX_VAL) WHERE FD_RID = RetVal;
END IF;
END LOOP;
Where X would be the loop variable. How could I do that in Oracle? DO I have to use Dynamic SQL? If so, how do I check the KEYWORD for 'CLI_RID'?
I don't think there's really anyway to do that in a loop. You could maybe do it with a case expression:
UPDATE FD_TABLE FD_CLI_RID = TO_NUMBER(CASE
WHEN KEYWORD1 = 'CLI_RID' THEN KEYWORD1_VAL
WHEN KEYWORD2 = 'CLI_RID' THEN KEYWORD2_VAL
WHEN KEYWORD3 = 'CLI_RID' THEN KEYWORD3_VAL
...
END)
WHERE FD_RID = RetVal
AND CASE
WHEN KEYWORD1 = 'CLI_RID' THEN KEYWORD1_VAL
WHEN KEYWORD2 = 'CLI_RID' THEN KEYWORD2_VAL
WHEN KEYWORD3 = 'CLI_RID' THEN KEYWORD3_VAL
...
END IS NOT NULL;
The case in the where clause stops it updating an existing value to null if there os no CLI_RID passed.
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);
...
CREATE or REPLACE PROCEDURE SP_INSERT_OVERSEAS_COMPANY
(
COMPANY_CODE IN NUMBER,
COMPANY_NAME IN VARCHAR2,
STREET_ADDR IN VARCHAR2,
COMPANY_STATE IN VARCHAR2,
ZIP_CODE IN VARCHAR2,
COUNTRY IN VARCHAR2,
CONTACT_PERSON IN VARCHAR2,
CONTACT_NUMBER IN VARCHAR2
)
AS
BEGIN
IF sysdate between trunc(sysdate,'DD')+interval '9' hour and trunc(sysdate,'DD')+interval '17' hour
THEN
INSERT INTO Overseas_Company
VALUES
(COMPANY_NAME,COMPANY_NAME,STREET_ADDR,COMPANY_STATE,ZIP_CODE,COUNTRY,CONTACT_PERSON,CONTACT_NUMBER);
ELSE
dbms_output.put_line ('Process is outside of normally working hours');
END IF;
END SP_INSERT_OVERSEAS_COMPANY;
/
Should COMPANY_NAME,COMPANY_NAME,... be COMPANY_CODE,COMPANY_NAME,...? The parameter COMPANY_CODE is not used in the procedure. Are you getting numeric conversion errors?