I am trying to figure out how to use APEX_DATA_EXPORT API to store PDF file in database table. I created a table with one column as a blob.
Has anyone tried to use APEX_DATA_EXPORT to store data in database?
DECLARE
l_context apex_exec.t_context;
l_export apex_data_export.t_export;
BEGIN
apex_session.create_session (
p_app_id => 130408,
p_page_id => 1,
p_username => 'EXAMPLE USER' );
l_context := apex_exec.open_query_context(
p_location => apex_exec.c_location_local_db,
p_sql_query => 'select * from emp' );
l_export := apex_data_export.export (
p_context => l_context,
p_format => nvl(:format, apex_data_export.c_format_pdf),
p_file_name => 'employees' );
apex_exec.close( l_context );
apex_data_export.download(
p_export => l_export,
--p_content_disposition => apex_data_export.c_inline,
p_stop_apex_engine => false);
insert into pdf_test4 (pdf) values l_export;
EXCEPTION
when others THEN
apex_exec.close( l_context );
raise;
END;
I managed to get it working for Excel so I guess it would work the same for pdf (change p_format)
DECLARE
v_sql varchar2(32000) := 'select * from my_data_table';
v_sql_trimmed varchar2(32000);
l_query_output CLOB;
p_file_id number;
l_file_name varchar2(200) := 'My File - '||sysdate;
p_status varchar2(100);
p_tag_id number;
l_context apex_exec.t_context;
l_export apex_data_export.t_export;
BEGIN
begin
l_context := apex_exec.open_query_context(
p_location => apex_exec.c_location_local_db,
p_sql_query => v_sql );
l_export := apex_data_export.export (
p_context => l_context,
p_format => apex_data_export.c_format_xlsx,
p_file_name => l_file_name );
apex_exec.close( l_context );
insert into my_files_table columns (file_blob,filename,file_mimetype,TAG,LOG,TAG_ID) values (l_export.content_blob , l_export.file_name,l_export.mime_type,'Latest','Y',1);
EXCEPTION
when others THEN
apex_exec.close( l_context );
raise;
END;
end;
Related
Recently I am trying to expand my knowledge about communication between databases in Oracle and I would like to get answer for few questions:
Problem
I am sending query through one database to another via LINK, for instance:
insert into testme#linkme values (1, ‘Hello World’);
where testme is destination table in second database and linkme is my link.
Questions
When sending query, are my data vulnerable (are they encrypted somehow during this process)?
If yes, could you briefly tell me more?
If no, is there any way to make this process safe?
Also, do you know any tools that I could use to test what happens with my data during sending process?
create or replace PACKAGE BODY "PKG_LOGI_PWD_REG"
as
FUNCTION decrypt_val( p_val IN RAW ) RETURN VARCHAR2
IS
l_decrypted RAW(32);
l_decrypted_string VARCHAR2(32);
L_USER varchar2(32);
L_CHARACTER_SET varchar2(10);
L_STRING varchar2(32);
L_KEY raw(250);
L_ENCRYPTION_TYPE PLS_INTEGER;
BEGIN
L_KEY := UTL_I18N.STRING_TO_RAW
( data => '98345678901234567890123456789012',
DST_CHARSET => 'AL32UTF8' );
L_ENCRYPTION_TYPE := dbms_crypto.encrypt_aes256
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
l_decrypted := dbms_crypto.decrypt
( SRC => P_VAL,
TYP => L_ENCRYPTION_TYPE,
key => L_KEY );
l_decrypted_string := utl_i18n.raw_to_char
( data => l_decrypted ,
src_charset => 'AL32UTF8' );
RETURN l_decrypted_string;
end DECRYPT_VAL;
FUNCTION encrypt_val( p_val IN VARCHAR2 ) RETURN VARCHAR2
is
L_VAL RAW(32);
L_ENCRYPTED raw(32);
L_CHARACTER_SET varchar2(10);
L_STRING varchar2(32);
L_KEY RAW(250);
L_ENCRYPTION_TYPE PLS_INTEGER;
begin
L_KEY := UTL_I18N.STRING_TO_RAW
( data => '98345678901234567890123456789012',
DST_CHARSET => 'AL32UTF8' );
L_ENCRYPTION_TYPE := dbms_crypto.encrypt_aes256
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
L_VAL := utl_i18n.string_to_raw
( data => p_val,
dst_charset => 'AL32UTF8' );
L_ENCRYPTED := dbms_crypto.encrypt
( SRC => L_VAL,
TYP => L_ENCRYPTION_TYPE,
key => L_KEY );
return L_ENCRYPTED;
EXCEPTION when OTHERS then
RETURN SQLCODE||'-'||SQLERRM;
end ENCRYPT_VAL;
end PKG_LOGI_PWD_REG;
I am running a PL/SQL procedure with DBMS_PARALLEL_EXECUTE. I get stuck with ORA-29494: invalid state for run task error. My code is as below:
Below is the sample output for the DBMS_OUTPUT statement:
PROCESSING
5743
PROCESSING
5744
When I individually run the create task, chunk task and run task with input rowid from the user_parallel_execute_chunks, It works just fine for individual chunks. Also without loop, the task runs for all the chunks and ends with an error saying chunk_not_found. To handle that I used the loop, But I am not able to make it work
CREATE OR REPLACE PROCEDURE code_parse_wrapper AS
l_sql_stmt VARCHAR2(32767);
l_chunk_id NUMBER;
l_start_rowid ROWID;
l_end_rowid ROWID;
l_any_rows BOOLEAN;
l_try NUMBER;
l_status NUMBER;
l_stmt CLOB;
V_CHUNK_ID NUMBER;
V_STATUS VARCHAR2(30);
BEGIN
BEGIN
dbms_parallel_execute.drop_task(task_name => 'parallel_processing');
DBMS_OUTPUT.PUT_LINE('TASK DROPPED');
END;
BEGIN
dbms_parallel_execute.create_task(task_name => 'parallel_processing');
DBMS_OUTPUT.PUT_LINE('TASK CREATED');
END;
-- Create Chunks
BEGIN
dbms_parallel_execute.create_chunks_by_rowid
(
'parallel_processing',
'SchemaName',
'ORDER_DETAIL',
FALSE,
50000
);
END;
BEGIN
LOOP
dbms_parallel_execute.get_rowid_chunk
(
task_name => 'parallel_processing',
chunk_id => l_chunk_id,
start_rowid => l_start_rowid,
end_rowid => l_end_rowid,
any_rows => l_any_rows
);
select STATUS INTO V_STATUS from user_parallel_execute_tasks where task_name = 'parallel_processing';
DBMS_OUTPUT.PUT_LINE(V_STATUS);
l_sql_stmt := ' begin CODE_PARSE6_AK( :start_id, :end_id ); end;';
DBMS_OUTPUT.PUT_LINE(l_chunk_id);
-- DBMS_OUTPUT.PUT_LINE(l_sql_stmt);
IF (l_any_rows = false) THEN
EXIT;
END IF;
BEGIN
-- Get next unassigned chunk.
-- EXECUTE IMMEDIATE 'l_sql_stmt USING l_start_rowid, l_end_rowid';
dbms_parallel_execute.run_task('parallel_processing',
l_sql_stmt,
DBMS_SQL.NATIVE,
parallel_level => 10
);
l_try := 0;
l_status := dbms_parallel_execute.task_status('parallel_processing');
WHILE(l_try < 2 and l_status != dbms_parallel_execute.finished) LOOP
l_try := l_try + 1;
dbms_parallel_execute.resume_task('parallel_processing');
l_status := dbms_parallel_execute.task_status('parallel_processing');
dbms_parallel_execute.set_chunk_status
(
task_name => 'parallel_processing',
chunk_id => l_chunk_id,
status => dbms_parallel_execute.processed
);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
-- Record chunk error.
dbms_parallel_execute.set_chunk_status
(
task_name => 'parallel_processing',
chunk_id => l_chunk_id,
status => dbms_parallel_execute.processed_with_error,
err_num => SQLCODE,
err_msg => SQLERRM
);
END;
COMMIT;
END LOOP;
END;
END;
Note sure why are doing get_rowid_chunk, set_chunk_status etc. I would use by_row => TRUE with create_chunks_by_rowid.
I think, you can use a simpler, cleaner piece of code here ... I have been using it for years without any issues. One can reuse this mostly by changing DML in l_sql_stmt.
DECLARE
l_task VARCHAR2(30) := 'parallel_processing';
l_sql_stmt VARCHAR2(32767);
l_try NUMBER;
l_status NUMBER;
BEGIN
DBMS_PARALLEL_EXECUTE.create_task (task_name => l_task);
DBMS_PARALLEL_EXECUTE.create_chunks_by_rowid(task_name => l_task,
table_owner => 'SCHEMANAME',
table_name => 'ORDER_DETAIL',
by_row => TRUE,
chunk_size => 10000);
l_sql_stmt := 'begin CODE_PARSE6_AK( :start_id, :end_id ); end;';
DBMS_PARALLEL_EXECUTE.run_task(task_name => l_task,
sql_stmt => l_sql_stmt,
language_flag => DBMS_SQL.NATIVE,
parallel_level => 10);
-- If there is error, RESUME it for at most 2 times.
l_try := 0;
l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task);
WHILE(l_try < 2 and l_status != DBMS_PARALLEL_EXECUTE.FINISHED)
Loop
l_try := l_try + 1;
DBMS_PARALLEL_EXECUTE.resume_task(l_task);
l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task);
END LOOP;
DBMS_PARALLEL_EXECUTE.drop_task(l_task);
END;
/
Oracle keeps giving me this error:
ORA-30625: method dispatch on NULL SELF argument is disallowed
I trying it with soap_api
The code follows:
FUNCTION add_numbers (p_int_1 IN NUMBER,
p_int_2 IN NUMBER)
RETURN NUMBER
AS
l_request soap_api.t_request;
l_response soap_api.t_response;
l_return VARCHAR2(32767);
l_url VARCHAR2(32767);
l_namespace VARCHAR2(32767);
l_method VARCHAR2(32767);
l_soap_action VARCHAR2(32767);
l_result_name VARCHAR2(32767);
BEGIN
l_url := 'http://192.168.1.23:8080/TestWebservice.asmx';
l_namespace := 'xmlns="http://192.168.1.23:8080/TestWebservice.asmx"';
l_method := 'add';
l_soap_action := 'http://tempuri.org/add';
l_result_name := 'return';
l_request := soap_api.new_request(p_method => l_method,
p_namespace => l_namespace);
soap_api.add_parameter(p_request => l_request,
p_name => 'int1',
p_type => 'xsd:integer',
p_value => p_int_1);
soap_api.add_parameter(p_request => l_request,
p_name => 'int2',
p_type => 'xsd:integer',
p_value => p_int_2);
l_response := soap_api.invoke(p_request => l_request,
p_url => l_url,
p_action => l_soap_action);
l_return := soap_api.get_return_value(p_response => l_response,
p_name => l_result_name,
p_namespace => l_namespace);
RETURN l_return;
END;
Review the return name the next line
l_result_name := 'return';
In my case change this and solved!!
l_result_name := 'Return';
i need to pass array values dynamic at this PL/SQL CODE But the Array Just See The First Value the code : Hint( The code is big so i cut it at the issue part)please
if you need more information Kindly Ask me,Here is my try to pass it Dynamic.
Variable fill code:
FOR ET IN (SELECT EMAIL
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'TO')
LOOP
IF P_TO IS NOT NULL
THEN
P_TO := P_TO || ',''' || ET.EMAIL||'''';
ELSE
P_TO := ''''||ET.EMAIL||'''';
END IF;
END LOOP;
FOR EC IN (SELECT EMAIL
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'CC')
LOOP
IF P_CC IS NOT NULL
THEN
P_CC := P_CC || ',''' || EC.EMAIL||'''';
ELSE
P_CC := ''''||EC.EMAIL||'''';
END IF;
END LOOP;
The Array fill part :
XX_MAIL_PKG.SEND (P_FROM => P_FROM,
P_TO => XX_MAIL_PKG.ARRAY ( P_TO),
P_CC => XX_MAIL_PKG.ARRAY (P_CC),
P_SUBJECT => 'test',
P_HTML_MSG => P_HTML_OUTPUT,
P_SMTP_HOST => P_SMTP_HOST,
P_SMTP_PORT => P_SMTP_PORT,
P_TEXT_MSG => NULL,
X_ERR_MSG => X_ERR_MSG);
COMMIT;
DBMS_OUTPUT.PUT_LINE (X_ERR_MSG);
You appear to be using collections - so (without knowing what is in the XX_MAIL_PKG package) you could try this:
DECLARE
V_TO XX_MAIL_PKG.ARRAY;
V_CC XX_MAIL_PKG.ARRAY;
BEGIN
SELECT EMAIL
BULK COLLECT INTO V_TO
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'TO';
SELECT EMAIL
BULK COLLECT INTO V_CC
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'CC';
XX_MAIL_PKG.SEND (P_FROM => P_FROM,
P_TO => V_TO,
P_CC => V_CC,
P_SUBJECT => 'test',
P_HTML_MSG => P_HTML_OUTPUT,
P_SMTP_HOST => P_SMTP_HOST,
P_SMTP_PORT => P_SMTP_PORT,
P_TEXT_MSG => NULL,
X_ERR_MSG => X_ERR_MSG);
COMMIT;
DBMS_OUTPUT.PUT_LINE (X_ERR_MSG);
END;
/
So, I am trying to replicate the data in tables to another database using Advanced Queuing. I created a table on both databases:
create table test
(
id number(10) primary key,
text varchar2(100)
);
then I created the queue
create type table_repli_payload_type AS OBJECT
( rowid_record varchar2(100)
, tabelle VARCHAR2(255)
, schema VARCHAR2(50)
);
begin
SYS.DBMS_AQADM.create_queue_table(queue_table => 'table_repli_queue_table',
queue_payload_type => 'table_repli_payload_type',
multiple_consumers => TRUE);
SYS.DBMS_AQADM.CREATE_QUEUE (
queue_name => 'table_repli_queue',
queue_table => 'table_repli_queue_table'
);
SYS.DBMS_AQADM.START_QUEUE (
queue_name => 'table_repli_queue'
);
end;
wrote a procedure for the replication
create or replace procedure table_repli_callback(
context RAW,
reginfo SYS.AQ$_REG_INFO,
descr SYS.AQ$_DESCRIPTOR,
payload RAW,
payloadl NUMBER
) AS
r_dequeue_options DBMS_AQ.DEQUEUE_OPTIONS_T;
r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
v_message_handle RAW(16);
o_payload table_repli_payload_type;
v_error varchar2(4000);
BEGIN
insert into log_table values(sysdate, 'start table_repli_callback');
r_dequeue_options.msgid := descr.msg_id;
r_dequeue_options.consumer_name := descr.consumer_name;
DBMS_AQ.DEQUEUE(
queue_name => descr.queue_name,
dequeue_options => r_dequeue_options,
message_properties => r_message_properties,
payload => o_payload,
msgid => v_message_handle
);
insert into log_table values(sysdate, 'ROWID: '||o_payload.rowid_record);
merge into test#test_link a
using (select * from test where rowid=o_payload.rowid_record) b on (a.id=b.id)
when matched then
update set text=b.text
when not matched then
insert values(b.id, b.text);
COMMIT;
exception
when others then
v_error:=sqlerrm;
insert into log_table values(sysdate, 'ERROR: '||v_error);
commit;
END;
/
and subscribed it
BEGIN
DBMS_AQADM.ADD_SUBSCRIBER (
queue_name => 'table_repli_queue',
subscriber => SYS.AQ$_AGENT(
'table_repli_queue_subscriber',
NULL,
NULL )
);
DBMS_AQ.REGISTER (
SYS.AQ$_REG_INFO_LIST(
SYS.AQ$_REG_INFO(
'table_repli_queue:table_repli_queue_subscriber',
DBMS_AQ.NAMESPACE_AQ,
'plsql://table_repli_callback',
HEXTORAW('FF')
)
),
1
);
END;
/
I played around with inserting/updating data in the TEST-table and than executing(with changing ids) this Code
DECLARE
r_enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T;
r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
v_message_handle RAW(16);
o_payload table_repli_payload_type;
v_rowid_record varchar2(100);
BEGIN
select rowid
into v_rowid_record
from test
where id=2;
o_payload := table_repli_payload_type(
v_rowid_record, '', ''
);
DBMS_AQ.ENQUEUE(
queue_name => 'table_repli_queue',
enqueue_options => r_enqueue_options,
message_properties => r_message_properties,
payload => o_payload,
msgid => v_message_handle
);
COMMIT;
END;
/
It's pretty random if it is working. He always seems to write something into TABLE_REPLI_QUEUE_TABLE, but when it is gone, about half the time there doesn't appear anything in LOG_TABLE and the data in the second database hasn't changed.
The error was a strange behavior in TOAD.
I sometimes write test scripts, with ddl, dml, selects, pl/sql-blocks in it and execute them by placing my cursor in a part of the desired command and press shift+F9. It seems like my TOAD just didn't execute the PL/SQL-block although it told me, it did.
I put the PL/SQL-block in another tab and just hit F9 and it worked fine, every time.