What is the difference between Procedures and Functions in PLSQL? - plsql

I am trying to Insert a line into a table using PLSQL. The table name is DOCUMENT_ISSUE_HISTORY. I am using an API Procedure name PROCEDURE
Insert_New_Line_ (
doc_class_ IN VARCHAR2,
doc_no_ IN VARCHAR2,
doc_sheet_ IN VARCHAR2,
doc_rev_ IN VARCHAR2,
info_category_db_ IN VARCHAR2,
note_ IN VARCHAR2 );
I am confused if PRECEDURE can return value like function does.
I am doing this:
DECLARE
doc_class_ varchar2(4000) := 'CVS FILE';
doc_no_ varchar2(4000) := '01004901.DWG-DWF';
doc_sheet_ varchar2(20) := 1;
doc_rev_ varchar2(20) := -1;
info_category_db_ VARCHAR2(20) := NULL;
note_ VARCHAR2(4000) := 'TEXTING TO UPDATE or FIeld to update';
BEGIN
Document_Issue_History_API.Insert_New_Line__ (doc_class_ ,doc_no_,doc_sheet_,doc_rev_ ,info_category_db_,note_);
end;
How can I can insert the line in the table?

Functions have return values and hence may appear anywhere an expression may be used (such as to the right of the assignment operator, or as a column expression in a SQL statement) while Procedures do not have return values and may not be used as expressions.
This is not to say that procedures can't return values, because they can as long as they are OUT or IN/OUT parameters. You just can't use the procedure directly in an expression.
Similarly since Functions do have a return value (other than those parameters specified as OUT or IN/OUT parameters) they must be used in an expression and can't be called directly.

Related

How to pass bind variable as IN OUT parameter in PLSQL procedure

I want to use 1st parameter of my procedure EMP_ID as IN OUT parameter. Originally it's IN parameter and this procedure is working fine, but as the last line concern
htp.p('Inserted for Employee-id '||EMP_ID);
I want to use this line in anonymous block and most importantly it should be a bind variable because I am creating the REST API in which user will only enter values and it will be taken as bind variable in oracle Apex and the below procedure is working fine with respect of IN parameter.
create or replace procedure att_time_ins (EMP_ID in varchar2, ORG_ID in number,V_TIME_STATUS in number) is
BEGIN
INSERT INTO TIME_ATTENDANCE_POOL
(EMPLOYEE_ID, ATTENDANCE_DATE,TIME_HOURS,TIME_MINUTES,TIME_STATUS,LOCATION_ID,ORG_ID,PREPARED_ON )
VALUES
(EMP_ID, to_date(sysdate,'DD/MM/YYYY'),to_char(sysdate,'HH24') ,to_char(sysdate,'MI'),V_TIME_STATUS,null,ORG_ID,
to_date(sysdate,'DD/MM/YYYY') );
COMMIT;
time_management.create_attendance_sheet(v_org_id => ORG_ID,
v_employee_id => EMP_ID,
target_date => to_date(sysdate,'DD/MM/YYYY'));
htp.p('Inserted for Employee-id '||EMP_ID);
end att_time_ins;
I am calling my procedure in this way
begin
att_time_ins(:employee_id,:org_id,:time_status);
end;
Please help me to modify this stuff according to IN OUT Parameter i.e Employee_id should be IN OUT parameter. There is no proper documentation regarding passing bind variables as in out prameter in PLSQL Block.
Let us say you have a procedure named PR_PROC, you can use VARIABLE statement for passing IN OUT or OUT kind of variables.
CREATE OR REPLACE PROCEDURE PR_PROC (EMP_NAME IN VARCHAR2,
EMP_ID IN OUT VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE (EMP_NAME||EMP_ID);
END;
VARIABLE KURSOR VARCHAR2
BEGIN
:KURSOR:='4';
PR_PROC('SENIOR',:KURSOR);
END;
Note: If you are using TOAD Editor you can press F5 to make it work.
Oracle VARIABLE

Merging varchars into one CLOB

I have the following procedure for merging 10 varchar variables of length 4000 characters into one CLOB:
procedure insert_iec_by_parts(p_header_id in number,
p_contents_part1 in varchar2,
p_contents_part2 in varchar2,
p_contents_part3 in varchar2,
p_contents_part4 in varchar2,
p_contents_part5 in varchar2,
p_contents_part6 in varchar2,
p_contents_part7 in varchar2,
p_contents_part8 in varchar2,
p_contents_part9 in varchar2,
p_contents_part10 in varchar2,
o_cur_results out sys_refcursor,
result_code out number) is
l_clob clob;
begin
l_clob:=p_contents_part1||p_contents_part2||p_contents_part3||p_contents_part4||p_contents_part5||
p_contents_part6||p_contents_part7||p_contents_part8||p_contents_part9||p_contents_part10;
insert_iec(p_header_id, l_clob, o_cur_results, result_code );
end;
procedure insert_iec(p_header_id in number,
p_contents in clob,
o_cur_results out sys_refcursor,
result_code out number) is
id_temp number;
l_id number;
procedure SetError(pErrCode number) is
-- A centralised sub proc could allow for a quick change to raise_application_error at any time.
begin
result_code := pErrCode;
end;
begin
select count(*) into l_id from log_sync_calls_headers
where log_sync_calls_headers.id =p_header_id;
case
when (p_header_id is null) or (l_id <= 0) then SetError(9804);
when p_contents is null then SetError(9805);
else
-- fetch sequence number
id_temp := iec_seq.nextval;
result_code:=0;
open o_cur_results for
select id_temp as id
from dual;
insert into log_sync_calls_iecs
(id, header_id, contents)
values
(id_temp, p_header_id, p_contents );
commit;
end case;
exception when others then
result_code :=9701;
rollback;
pkg_common.insert_log_record(p_source => 'insert_iec',
p_type => 'Er',
p_message => sqlerrm);
end;
Procedure works fine when merging 10 varchar variables of 4000 characters each. However, I want to extend it to 20 varchar variables of length 4000 characters.
When I try that, it gives me the following error:
ORA 06502: character string buffer too small.
Could someone show me how to be able to extend this procedure to 20 varchar variables of length 4000 characters?
Use DBMS_LOB.APPEND function like in this question (or just search for DBMS_LOB.APPEND in SO): how to insert long string oracle clob or blob
you should use the DBMS_LOB package.
first you should create a clob object otherwise you variable is not initialized
dbms_lob.createtemporary(l_clob ,true);
now you can use append procedure
dbms_lob.append(l_clob, p_contents_part1 );
after you are finished , don't forget to release a clob Memory and destroy you clob object
dbms_lob.freetemporary(l_clob);

Can we use a parameter in a pl sql subprogram other than in where clause

Can we use the parameters in a pl sql subprogram other than in where clause
Yes. Once you declare the variables in a PLSQL program, you can use it anywhere in the program. See below an example
DECLARE
var VARCHAR2 (100); -- Variable declared
BEGIN
var := 'My name is jack'; -- Assigning a string to the varibale
DBMS_OUTPUT.put_line (var); -- Displaying it.
SELECT 'My name is Mack' INTO var FROM DUAL;
DBMS_OUTPUT.put_line (var);
END;
I hope this helps.
Yes, you surely can.
Create or replace procedure test(a_param_1 in int, a_param_2 out int)
as
v_var int;
begin
dbms_output.put_line(a_param);--you can print the param
v_var := a_param ;-- you can assign it to some other value
a_param_2 := 1; --Out parameter can be assigned a value.
end;

How to convert VARCHAR2 to BLOB inside Oracle 11g PL/SQL after ORA-06502

I have a function, that calculates hash value of big string! First of all I wrote a cursor T1_CUT, which can include variable count of SELECT statements, something like:
SELECT T1.COL1||T1.COL2||...||T1.COLn FROM T1 WHERE id=documentid
SELECT T2.COL1||T2.COL2||...||T2.COLn FROM T2 WHERE id=documentid
...
SELECT Tn.COL1||Tn.COL2||...||Tn.COLn FROM Tn WHERE id=documentid
Each SELECT can contain one or more rows. So, I concat ALL values in rows in each SELECT and ALL SELECTs values in one big string V_RESULT with type VARCHAR2(32767). After that I get hash value (S_HASH_RESULT) of this big string using MD5. It works fine about 8 monthes, but few days ago I've got ORA-06502 (no surprise). It means, that my final big string have more than 32K symbols (we use 1byte character set - CL8MSWIN1251).
Friends, how can I rewrite my function for using BLOB data type to V_RESULT variable, not VARCHAR2(32767).
Below, text of my function:
FUNCTION CALC_HASH (P_PARTAB_ID IN NUMBER, P_DOC_ID IN NUMBER)
RETURN VARCHAR2
IS
S_HASH_RESULT VARCHAR2(1000);
V_RESULT VARCHAR2(32767);
CURSOR T1_CUT IS
...
/*BIG COMPLAIN SELECT*/
...
T1 T1_CUT%ROWTYPE;
TYPE VALUES_T IS TABLE OF VARCHAR2(32767);
L_VALUES VALUES_T;
BEGIN
OPEN T1_CUT;
FETCH T1_CUT INTO T1;
WHILE T1_CUT%FOUND
LOOP
EXECUTE IMMEDIATE
T1.TEXT
BULK COLLECT INTO L_VALUES;
FOR INDX IN 1 .. L_VALUES.COUNT
LOOP
V_RESULT := V_RESULT || '' ||TO_CHAR(L_VALUES (INDX));
END LOOP;
FETCH T1_CUT INTO T1;
END LOOP;
CLOSE T1_CUT;
S_HASH_RESULT := DBMS_OBFUSCATION_TOOLKIT.MD5(input_string=>V_RESULT);
RETURN S_HASH_RESULT;
END CALC_HASH;
Thanks in advance!
there is a function called utl_raw.cast_to_raw(vc) which transforms a varchar2 into a BLOB value.
However, I recommend to use CLOB to store string values. BLOB has no character semantics at all, i.e., NLS_LANG settings are ignored.
EDIT:
if you want to transform VARCHAR2 to CLOB, simply use TO_CLOB

PLSQL procedure error

I get the below error while executing code
create or replace
function contact_restriction_function(obj_schema varchar2, obj_name varchar2)
return varchar2 is
v_contact_info_visible hr_user_access.contact_info_visible%type;
begin
-- Here you can put any business logic for filtering
select nvl(max(contact_info_visible),'N')
into v_contact_info_visible
from hr_user_access
where user_name = user;
-- SQL filter / policy predicate
return ''''||v_contact_info_visible||''' = ''Y'' ';
end;
/
after show erros command i got this
show errors
Errors for FUNCTION CONTACT_RESTRICTION:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/1 PLS-00103: Encountered the symbol "?" when expecting one of the
following:
begin function pragma procedure subtype type
current cursor delete
exists prior external language
This is the remaining code:
begin
dbms_rls.add_policy(object_schema => 'HR' ,
object_name => 'EMPLOYEES' ,
policy_name => 'Contact_Restriction_Policy' ,
policy_function => 'contact_restriction_function' ,
sec_relevant_cols=>'EMAIL,PHONE_NUMBER'Contact Info ,
sec_relevant_cols_opt=>dbms_rls.all_rows);
end;
below is the actual code which i am executing before show errors:
create or replace function contact_restriction(obj_schema varchar2, obj_name varchar2)
return varchar2
is
v_contact_info_visible IN user_access.contact_info_visible%type;
begin
select nvl(max(contact_info_visible),'N')
into v_contact_info_visible
from user_access where username = user;
return 'v_contact-info_visible ='|| 'Y';
end;
Your original question shows an error message referring to "?", but the code yout posted a as comment would raise a similar error for `"IN"' instead:
2/24 PLS-00103: Encountered the symbol "IN" when expecting one of the following:
That is because you've used IN for a local variable; but IN, OUT and IN OUT are only applicable to stored procedure parameters. You could have declared the function with an explicit IN for example, though it is the default anyway:
create or replace function contact_restriction(obj_schema IN varchar2, ...
So that needs to be removed from the v_contact_info_visible declaration. You've linked to an example you're working from, but you've removed a lot of important quotes from that, which will still cause it to fail when executed as a part of a VPD; because v_contact_info_visible will be out of scope to the caller. And you have a typo, with a hyphen instead of an underscore.
You need something like:
create or replace function contact_restriction(obj_schema varchar2,
obj_name varchar2)
return varchar2 is
v_contact_info_visible user_access.contact_info_visible%type;
begin
select nvl(max(contact_info_visible),'N')
into v_contact_info_visible
from user_access
where username = user;
return ''''||v_contact_info_visible ||''' =''Y''';
end;
/
When called, that will return a string which is either 'N'='Y' or 'Y'='Y'. VPD will include that as a filter in the original query, which will either prevent any rows being returned (in the first case) or have no effect and allow all rows that match any other existing conditions to be returned (in the second case).
The syntax of the function header is incorrect. It should be:
create or replace function contact_restriction(obj_schema IN varchar2, obj_name IN varchar2)
return varchar2
is

Resources