Oracle P_cursor to V_cursor empty table - oracle

I want to run filter but with 2 package since both getting different form of input in aspx
So I have this code , when I run it on Toad Oracle, it says error
I think I know the source of error is V_cursor, since I dont know how to store V_cursor on empty table
Can u guys help me please ?
CREATE OR REPLACE PACKAGE BODY GIA.Package_AUTOCOMPLETE IS
procedure get_model
(
P_STRINGMODEL IN VARCHAR2
,P_STRINGMERK IN VARCHAR2
,p_CURSOR OUT Types.ref_cursor
,p_STATUS OUT VARCHAR2
,p_ERROR_MESSAGE OUT VARCHAR2
)
is
BEGIN
PACKAGE_AUTOCOMPLETE.GET_MERK
(
P_STRINGMERK
,V_CURSOR
,p_STATUS
,p_ERROR_MESSAGE
)
Open P_CURSOR FOR
select * from V_CURSOR
WHERE V_CURSOR.MODEL_NAME = P_STRINGMODEL
;
p_status := '1';
p_error_message := 'ok';
EXCEPTION
WHEN OTHERS THEN
p_status := '0';
p_error_message := SUBSTR(SQLERRM, 1, 100);
END get_model;
procedure get_merk
(
P_STRINGMERK IN VARCHAR2
,p_CURSOR OUT Types.ref_cursor
,p_STATUS OUT VARCHAR2
,p_ERROR_MESSAGE OUT VARCHAR2
)
is
BEGIN
open p_cursor for
SELECT MERK_ID, MERK_NAME, TYPE_NAME, MODEL_NAME, MODEL_DESC
FROM TABLE_MERK_MODEL
WHERE MERK_ID=P_STRINGMERK
;
p_status := '1';
p_error_message := 'ok';
EXCEPTION
WHEN OTHERS THEN
p_status := '0';
p_error_message := SUBSTR(SQLERRM, 1, 100);
END get_merk;
end package_AUTOCOMPLETE ;
/

Related

Can i use a BFILENAME within a cursor for multiple images?

Is it possible to concatenate the .jpg filename in order to upload several images to a table?
I want it to do it with a cursor.
Here is the code:
CREATE OR REPLACE PROCEDURE upload_pics AS
CURSOR c_id IS
SELECT DISTINCT id_pic
FROM id_table;
r_id c_id%rowtype;
v_blob BLOB;
v_bfile BFILE;
BEGIN
FOR r_id IN c_id LOOP
v_bfile := bfilename('TMP_DIR', r_id.id_pic || '.jpg');
dbms_lob.open(v_bfile, dbms_lob.lob_readonly);
dbms_lob.loadfromfile(v_blob, v_bfile, dbms_lob.getlength(v_bfile));
UPDATE pic_table
SET
picture = v_blob
WHERE
id = r_id.id_pic;
dbms_lob.close(v_bfile);
END LOOP;
END;
Yes possible, here's is an alternative way which worked for me :
SQL> set serveroutput on;
SQL> Create or Replace Procedure upload_pics As
v_blob blob := null;
Function load_blob_from_file( filename varchar2, directoryname varchar2 ) Return blob Is
filecontent blob := null;
v_bfile bfile := bfilename(directoryname, filename);
v_offset pls_integer := 1;
v_var pls_integer;
Begin
v_var := dbms_lob.fileexists(v_bfile);
if v_var = 1 then
dbms_lob.createtemporary(filecontent, true, dbms_lob.session);
dbms_lob.fileopen(v_bfile, dbms_lob.file_readonly);
dbms_lob.loadblobfromfile(filecontent,v_bfile,dbms_lob.getlength(v_bfile),v_offset,v_offset);
dbms_lob.fileclose(v_bfile);
end if;
Return filecontent;
End;
Begin
for r_id in (
select distinct id_pic
from id_table
)
loop
v_blob := load_blob_from_file(to_char(r_id.id_pic)||'.jpg', 'TMP_DIR');
if v_blob is not null then
update pic_table set picture = v_blob where id = r_id.id_pic; commit;
dbms_output.put_line(to_char(r_id.id_pic)||' is OK');
end if;
end loop;
exception when others then dbms_output.put_line(sqlerrm);
End;
/
SQL> exec upload_pics;

delete from pipeline function return object

I have a pipe line function like below. if I want to delete some rows from the fetched output, how should I do that.
I tried myObjectFormat.delete after the END LOOP in below code.
but it didn't work.
Please let me know what I am doing wrong;
CREATE OR REPLACE TYPE myObjectFormat AS OBJECT
(
A INT,
B DATE,
C VARCHAR2 (25)
)
/
CREATE OR REPLACE TYPE myTableType AS TABLE OF myObjectFormat
/
CREATE OR REPLACE FUNCTION SB360.test_func (P_ID VARCHAR2)
RETURN myTableType
PIPELINED
IS
v_obj myObjectFormat := myObjectFormat (NULL, NULL, NULL);
v_cur SYS_REFCURSOR;
QUERY_STMT VARCHAR2 (32767);
A INT;
B DATE;
C VARCHAR2 (25);
BEGIN
QUERY_STMT := 'select a,b,c from test where id=' || P_ID;
OPEN V_CUR FOR QUERY_STMT;
LOOP
FETCH V_CUR INTO a, b, c;
EXIT WHEN V_CUR%NOTFOUND;
v_obj.A := A;
v_obj.b := b;
v_obj.c := c;
PIPE ROW (v_obj);
END LOOP;
RETURN;
END;
/

data loss with parallel enabled pipelined function

I have a pipelined function that loads data into file.
The following is the code of function.
CREATE OR REPLACE FUNCTION DATA_UNLOAD
( p_source IN SYS_REFCURSOR,
p_filename IN VARCHAR2,
p_directory IN VARCHAR2
) RETURN dump_ntt PIPELINED PARALLEL_ENABLE (PARTITION p_source BY ANY)
AS
TYPE row_ntt IS TABLE OF VARCHAR2(32767);
v_rows row_ntt;
v_file UTL_FILE.FILE_TYPE;
v_buffer VARCHAR2(32767);
v_sid VARCHAR(255);
v_name VARCHAR2(255);
v_lines PLS_INTEGER := 0;
v_start_dttm TIMESTAMP WITH TIME ZONE:= SYSTIMESTAMP;
v_end_dttm TIMESTAMP WITH TIME ZONE;
c_eol CONSTANT VARCHAR2(1) := CHR(10);
c_eollen CONSTANT PLS_INTEGER := LENGTH(c_eol);
c_maxline CONSTANT PLS_INTEGER := 32767;
BEGIN
--v_sid := lpad(sys_context('USERENV', 'sid'), 10, '0');
v_name:=p_filename;
LOOP
if utl_file.is_open(v_file)
then
utl_file.fclose(v_file);
end if;
v_file := UTL_FILE.FOPEN(p_directory, v_name, 'A', c_maxline);
FETCH p_source BULK COLLECT INTO v_rows LIMIT 100;
FOR i IN 1 .. v_rows.COUNT LOOP
IF LENGTH(v_buffer) + c_eollen + LENGTH(v_rows(i)) <= c_maxline THEN
v_buffer := v_buffer || c_eol || v_rows(i);
ELSE
IF v_buffer IS NOT NULL THEN
UTL_FILE.PUT_LINE(v_file, v_buffer);
END IF;
v_buffer := v_rows(i);
END IF;
END LOOP;
v_lines := v_lines + v_rows.COUNT;
EXIT WHEN p_source%NOTFOUND;
END LOOP;
CLOSE p_source;
UTL_FILE.PUT_LINE(v_file, v_buffer);
UTL_FILE.FCLOSE(v_file);
v_end_dttm := SYSTIMESTAMP;
--PIPE ROW (dump_ot(v_name, p_directory, v_lines, v_sid, v_start_dttm, v_end_dttm));
--RETURN ;
END;
i call the function this way.
SELECT * from table(DATA_UNLOAD(
CURSOR(select /*+ PARALLEL */ a || b || c from sample_table),
'sample.txt',
'99_DIR'));
a real life select that i pass as a parameter to function returns 30000 rows, but when i use the function to load the result into a file some rows are lost. During the execution with PARALLEL hint there are 24 parallel sessions, and i dont want to make it less. My guess is that the problem is in parallel execution, because when i dont use PARALLEL hint no data is lost. Can anyone suggest something to get rid of that problem without removing the hint?
Even though you are creating sample.txt with Append mode - you have 24 parallel sessions each writing to it. I always use unique filenames by appending the SID to your variable:
SELECT sid INTO v_sid FROM v$mystat WHERE ROWNUM = 1;
v_name := p_filename || '_' || v_sid || '.dat';
Depending on the # of parallel sessions you should 1 to many files with the format sample_nnnn.txt where nnnn is the SID number.

Oracle procedure to create_person fails with PLS-00306 error

I have a package specification:
G_PKG_NAME CONSTANT VARCHAR2(30) := 'XX_CUST_PKG';
PROCEDURE customer_load
( errbuff OUT NOCOPY VARCHAR2
, retcode OUT NOCOPY VARCHAR2);
And body with procedure which calls to HZ_PARTY_V2PUB API. It uses cursor to take data from a table and then sends it to API :
PROCEDURE create_customer
( errbuff OUT NOCOPY VARCHAR2
, retcode OUT NOCOPY VARCHAR2)
IS
ERR_SOURCE CONSTANT VARCHAR2(100) := G_PKG_NAME ||'.create_customer';
CURSOR c_load
IS
SELECT rowid row_id
, person_first_name
, person_last_name
, title
, known_as
, person_identifier
, gender
FROM xx_customer_info
WHERE NVL(status_flag, 'X') <> 'S';
r_load c_load%ROWTYPE;
--p_init_msg_list VARCHAR2(1) := FND_API.G_TRUE;
v_gender VARCHAR2(30); --hz_parties.sex%TYPE;
v_title VARCHAR2(60); --hz_parties.title%TYPE;
--API record type
person_rec HZ_PARTY_V2PUB.PERSON_REC_TYPE;
-- API output variables
x_return_status VARCHAR2(1);
x_msg_count NUMBER;
x_msg_data VARCHAR2(2000);
x_party_id NUMBER;
x_party_number VARCHAR2(30);
x_profile_id NUMBER;
EXC_VALDN_ERR EXCEPTION;
BEGIN
errbuff := ' ';
retcode := RTN_SUCCESS;
msg_log ('Inside '||ERR_SOURCE);
FOR r_load in c_load LOOP
BEGIN
x_msg_data := NULL;
x_return_status := fnd_api.G_RET_STS_SUCCESS;
fnd_msg_pub.initialize;
-- example validation:
IF r_load.person_first_name IS NULL THEN
x_msg_data := ' "First name" cannot be null';
RAISE EXC_VALDN_ERR;
END IF;
-- Same validation for person_last_name here
-- Record Type:
person_rec.person_first_name := r_load.person_first_name;
person_rec.person_last_name := r_load.person_last_name;
person_rec.person_title := v_title;
person_rec.known_as := null;
person_rec.gender := v_gender;
person_rec.created_by_module := 'TCA_V2_API';
HZ_PARTY_V2PUB.create_person ( p_init_msg_list => FND_API.G_TRUE
, p_person_rec => person_rec
, x_party_id => x_party_id
, x_party_number => x_party_number
, x_profile_id => x_profile_id
, x_return_status => x_return_status
, x_msg_count => x_msg_count
, x_msg_data => x_msg_data);
msg_log('==========================');
msg_log('first name / last_name : '||r_load.person_first_name||' | '||r_load.person_last_name);
msg_log('x_return_status: '||x_return_status);
msg_log('x_msg_count: '||x_msg_count);
msg_log('x_msg_data: '||x_msg_data);
IF NVL(x_return_status, FND_API.G_RET_STS_ERROR) <> FND_API.G_RET_STS_SUCCESS THEN
IF NVL(x_msg_count, 0) > 1 THEN
FOR i IN 1..x_msg_count LOOP
x_msg_data := x_msg_data||i||'. '||substr(fnd_msg_pub.get(p_encoded => fnd_api.g_false ), 1, 255)||' , ';
msg_log(x_msg_data);
END LOOP;
END IF;
END IF;
msg_log('==========================');
EXCEPTION
WHEN OTHERS THEN
x_msg_data := 'EXC: '||NVL(x_msg_data, SQLERRM);
x_return_status := FND_API.G_RET_STS_ERROR;
END;
UPDATE xx_customer_info
SET status_flag = x_return_status
, error_message = x_msg_data
WHERE rowid = r_load.row_id;
END LOOP;
COMMIT;
msg_log ('Exit '||ERR_SOURCE);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
msg_log('ERROR : '||ERR_SOURCE||' : '||NVL(SQLERRM, x_msg_data));
errbuff := 'ERROR : '||ERR_SOURCE||' : '||NVL(SQLERRM, x_msg_data);
retcode := RTN_ERROR;
END create_customer;
It should return errors or success.
When I test and run this in anonymous block:
begin
XX_CUST_PKG.create_customer;
end;
I get error message PLS-00306: wrong number or types of arguments in call to 'CREATE_CUSTOMER'. I can't see clearly where this error is referring to. I only have 2 OUT parameters, it should only give errbuff (which is x_msg_data) and retcode which is RTN_SUCCESS, RTN_WARNING or RTN_ERROR (I have this declared as constants '0', '1', '2') to output.
This was rewritten from initial package to the above example code, so that it handles exceptions, and few things had to be modified, but now I'm confused when testing it.
What did I leave out?
Any help?
The error you get is a PL/SQL compilation error, as you can see the error code starts with PLS-XXXX.. So it is not returned from your procedure. You missed to send the variables to hold the values from your procedure (out arguments)
Declare
errbuf varchar2(4000);
retcode varchar2(10);
begin
XX_CUST_PKG.create_customer(errbuf,retcode);
--printing the values
DBMS_OUTPUT.PUT_LINE(retcode||' '||errbuf);
end;
/

Oracle read nth column using a cursor

can i read column data in a cursor giving the index of the column?
thanks...
From the questioner's comments :
"I need to create a generic procedure which will read a table or view (name of the view or table is the argument of the proc) and encrypt the data in the column and then will write the encrypted data to a OS file. "
This should give you a head start.
Just plug in your encryption code for the column number you want.
I've used VARCHAR everywhere. If you want dates and numbers (or more exotic datatypes), then you'll need to handle the conversion.
create or replace function qry_dump
(p_tab_name in varchar2, p_rownum in number default 5)
return tab_char_4000 AUTHID CURRENT_USER pipelined is
v_line varchar2(2000);
v_col_cnt INTEGER;
v_ind NUMBER;
rec_tab dbms_sql.desc_tab;
v_tab dbms_sql.varchar2a;
v_temp VARCHAR2(32000);
v_cursor NUMBER;
v_clause VARCHAR2(200);
begin
--
-- Initial values
-- v_ind := 1;
v_temp := 'select * from '||p_tab_name||' where rownum <= '||nvl(p_rownum,5);
--
-- Identify the columns in the target and build the new query
--
v_cursor := dbms_sql.open_cursor;
dbms_sql.parse(v_cursor, v_temp, dbms_sql.native);
dbms_sql.describe_columns(v_cursor, v_col_cnt, rec_tab);
--
FOR v_pos in 1..rec_tab.LAST LOOP
v_line := rec_tab(v_pos).col_name;
dbms_sql.define_column( v_cursor, v_pos, v_line, 2000);
END LOOP;
v_ind := dbms_sql.execute( v_cursor );
--
-- Fetch each row from the result set
--
LOOP
v_ind := DBMS_SQL.FETCH_ROWS( v_cursor );
EXIT WHEN v_ind = 0;
pipe row( '=============================================================');
--
-- Go through each column and display it
--
FOR v_col_seq IN 1 .. rec_tab.COUNT LOOP
-- Get the value
dbms_sql.column_value( v_cursor, v_col_seq, v_line );
pipe row( rpad(rec_tab(v_col_seq).col_name,35)||'>'||v_line);
END LOOP;
END LOOP;
return;
end qry_dump;
/
select * from table(qry_dump('DEPT',3));
Additional answer for CLOBs.
Simpler code as I've hardcoded the table/column_name.
The main difference is that v_line is now a CLOB and that the final parameter (length) is dropped from the call to DEFINE_COLUMN since it is only relevant to VARCHAR2.
If you are dealing in very large CLOBs (eg 10s or 100s MB plus), then I can foresee other challenges (memory, performance...).
create or replace function clob_dump
return tab_char_4000 AUTHID CURRENT_USER pipelined is
v_line clob;
v_col_cnt INTEGER;
v_ind NUMBER;
rec_tab dbms_sql.desc_tab;
v_cursor NUMBER;
begin
--
-- Identify the columns in the target and build the new query
--
v_cursor := dbms_sql.open_cursor;
dbms_sql.parse(v_cursor, 'select sql_fulltext from gm_c where rownum <= 5', dbms_sql.native);
dbms_sql.describe_columns(v_cursor, v_col_cnt, rec_tab);
--
FOR v_pos in 1..rec_tab.LAST LOOP
v_line := rec_tab(v_pos).col_name;
dbms_sql.define_column( v_cursor, v_pos, v_line);
END LOOP;
v_ind := dbms_sql.execute( v_cursor );
--
-- Fetch each row from the result set
--
LOOP
v_ind := DBMS_SQL.FETCH_ROWS( v_cursor );
EXIT WHEN v_ind = 0;
pipe row( '=============================================================');
--
-- Go through each column and display it
--
FOR v_col_seq IN 1 .. rec_tab.COUNT LOOP
-- Get the value
dbms_sql.column_value( v_cursor, v_col_seq, v_line );
pipe row( rpad(rec_tab(v_col_seq).col_name,35)||'>'||substr(v_line,1,100));
END LOOP;
END LOOP;
return;
end clob_dump;
/
select * from table(clob_dump);

Resources