Merging varchars into one CLOB - plsql

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);

Related

Procedure run details for a day

Please let me know if you can provide the detail of “number of times” a procedure has been called for that particular day, for the all the valid procedures.
You can use your own logging technic. For example first you can create a table under the same schema of your desired procedure. Then after begin statement end before end statement in that invoked procedure, you can insert logs to newly created log table of yours.
CREATE TABLE SCHEMA.LOGTABLE
(
DATECOLUMN DATE DEFAULT SYSTIMESTAMP,
PROCNAME VARCHAR2 (200 CHAR),
TABLENAME VARCHAR2 (200 CHAR),
MESSAGE VARCHAR2 (1000 CHAR),
LOGSEQUENCE NUMBER
);
CREATE OR REPLACE PROCEDURE SCHEMA.PROCNAME IS
BEGIN
INSERT INTO SCHAME.LOGTABLE(DATECOLUMN,
PROCNAME,
TABLENAME,
MESSAGE,
LOGSEQUENCE)
VALUES (SYSTIMESTAMP,
'SCHEMA.PROCNAME',
'SCHEMA.TABLENAME',
'Proc STARTED',
NULL,
SCHEMA.SEQ_SISTEM_LOG.NEXTVAL);
COMMIT;
.....
INSERT INTO SCHAME.LOGTABLE(DATECOLUMN,
PROCNAME,
TABLENAME,
MESSAGE,
LOGSEQUENCE)
VALUES (SYSTIMESTAMP,
'SCHEMA.PROCNAME',
'SCHEMA.TABLENAME',
'Proc ENDED',
NULL,
SCHEMA.SEQ_SISTEM_LOG.NEXTVAL);
COMMIT;
END;

Oracle - store large string in CLOB

I need to save a procedure body into a Clob column with a use of variable. String is longer than 4000 characters, so I can't use VarChar2, but with CLOB variable I receive error "ORA-01422: exact fetch returns more than requested number of rows". Same error appears with Varchar2. My PL/SQL block:
DECLARE
txt_procedure CLOB;
BEGIN
SELECT text INTO txt_procedure
FROM all_source
WHERE name = 'My_procedure'
ORDER BY line;
INSERT INTO TABLE1(ID,DATE,CLOB_COLUMN)
VALUES (my_seq.NEXTVAL,'11.10.2018',txt_procedure);
END;
/
How could I insert procedure body into clob column ?
As you will get multiple rows from your query for every line of your source, the following might help:
DECLARE
txt_procedure CLOB;
BEGIN
FOR source_r IN ( SELECT text
FROM all_source
WHERE name = 'My_procedure'
ORDER BY line
)
LOOP
txt_procedure := txt_procedure || chr(10) || source_r.text;
END LOOP;
INSERT INTO TABLE1(ID,DATE,CLOB_COLUMN)
VALUES (my_seq.NEXTVAL,'11.10.2018',txt_procedure);
END;
/
UPDATE
As an alternative, you might also use the DBMS_METADATA package for this:
DECLARE
txt_procedure CLOB;
BEGIN
txt_procedure := DBMS_METADATA.get_ddl(
object_type => 'PROCEDURE',
name => 'My_procedure',
owner => 'YOUR_SCHEMA'
);
INSERT INTO TABLE1(ID,DATE,CLOB_COLUMN)
VALUES (my_seq.NEXTVAL,'11.10.2018',txt_procedure);
END;
/

Z-ORA-01745: invalid host/bind variable name (PLSQL)

I kind of new on dynamic variables in plsql.
I am getting an error "invalid host/bind variable name" on EXECUTE IMMEDIATE
statement. Thanks in advance.
CREATE OR REPLACE PROCEDURE MY_CLASS_CONFIG_DML (pBuCode VARCHAR2,
pMyPKId VARCHAR2,
pMyName VARCHAR2,
pMyId VARCHAR2,
pRemarks VARCHAR2,
pUserId VARCHAR2)
AS
v_table VARCHAR2 (50);
v_lastdate DATE;
--bindable var.
v_pkey VARCHAR2 (12) := pMyPKId;
v_myname VARCHAR2 (30) := pMyName;
v_bucode VARCHAR2 (4) := pBuCode;
v_myid VARCHAR2 (12) := pMyId;
v_remarks VARCHAR2 (50) := pRemarks;
v_lastid VARCHAR2 (8) := pUserId;
BEGIN
v_lastdate := SYSDATE;
v_table := v_bucode || '_WORKSHEET_CONFIG';
--Error happens on this part
EXECUTE IMMEDIATE
'insert into '
|| v_table
|| '(pk_id,my_name,my_id,remarks,last_user,last_date)
values(:pkey,:myname,:myid,:remarks,:user,:lastdate)'
USING v_pkey,
v_myname,
v_myid,
v_remarks,
v_lastid,
v_lastdate;
--end comment
COMMIT;
RETURN;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
END MY_CLASS_CONFIG_DML;
Replace :user by another keyword: :myuser or :lastid. The colon should make it possible to use the reserved keyword "user", but this is the only problem i see.

What is the difference between Procedures and Functions in 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.

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

Resources