how to convert DBMS_METADATA Oracle to Postgres? - oracle

How to convert DBMS_METADATA Procedures and Functions for Submitting XML Data in oracle to postgresql
For example :
SET serveroutput ON;
DECLARE
v_handle NUMBER;
v_transform_handle NUMBER;
v_ddls sys.ku$_ddls;
v_ddl sys.ku$_ddl;
BEGIN
v_handle := DBMS_METADATA.OPEN ('OBJECT_GRANT');
v_transform_handle := DBMS_METADATA.ADD_TRANSFORM(v_handle, 'DDL');
DBMS_METADATA.SET_TRANSFORM_PARAM(v_transform_handle,'PRETTY', TRUE);
DBMS_METADATA.SET_TRANSFORM_PARAM(v_transform_handle,'SQLTERMINATOR',TRUE);
DBMS_METADATA.SET_FILTER(v_handle, 'BASE_OBJECT_NAME', 'TABLE_NAME' );
DBMS_METADATA.SET_FILTER(v_handle, 'BASE_OBJECT_SCHEMA', 'OWNER_NAME' );
DBMS_METADATA.SET_COUNT (v_handle, 10); -- 10 object by call to fetch
v_ddls := DBMS_METADATA.FETCH_DDL(v_handle);
WHILE (v_ddls IS NOT NULL)
LOOP
FOR indx IN 1 .. v_ddls.COUNT
LOOP
v_ddl := v_ddls(indx);
DBMS_OUTPUT.put_line ('Output: ' || v_ddl.ddlText);
END LOOP;
v_ddls := DBMS_METADATA.FETCH_DDL(v_handle);
END LOOP;
DBMS_METADATA.CLOSE (v_handle);
END;
/

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;

Read file and generate query in plsql oracle 11

I am writing a stored procedure where I have to do following: I want to have a file (any format properties, json, xml) which will have information of which columns I want to extract from my table.
For example: my table has columns A,B,C,D,E, and suppose my file.properties has below information
A=1
B=0
C=1
D=1
F=0
So my generated query should be Select A,C,D from my table;
How can I do this in Oracle 11G?
I think you need this
SQL> set serveroutput on;
SQL> create or replace procedure pr_dynamic_sql( v_result out sys_refcursor ) is
v_outfile utl_file.file_type;
v_path varchar2(100) := 'UTL_FILE_DIR';
-- alias for the directory where your text files generated at OS.
v_row varchar2(100);
v_file varchar2(100);
v_letter varchar2(10);
v_number varchar2(10);
v_sql varchar2(100):= 'select ';
begin
v_file := 'myfile.properties';
v_outfile := utl_file.fopen(v_path, v_file, 'r');
loop
begin
utl_file.get_line(v_outfile,v_row);
v_letter := regexp_substr(v_row,'[^=]');
v_number := substr(regexp_substr(v_row,'[^=]+$'),1,1);
if v_number = '1' then
v_sql := v_sql||v_letter||',';
end if;
exception when no_data_found then exit;
end;
end loop;
utl_file.fclose(v_outfile);
v_sql := rtrim(v_sql,',')||' from mytable';
open v_result for v_sql;
end;
and call
SQL> begin
pr_dynamic_sql(v_result => :v_result);
end;
/
to get results as of cursor type.

regex to remove commas between quotes in Oracle 11.2g

My code is:
set serveroutput on size unlimited;
DECLARE
v_line_unclean VARCHAR2(32767); -- 32767 BYTES
v_line_clean VARCHAR2(32767);
v_clean_val VARCHAR2(32767);
SQLSMT VARCHAR2(32767);
v_line_in_record INTEGER;
pattern varchar2(15) := '("[^"]*"|[^,]+)';
v_name VARCHAR2(50);
v_first_column VARCHAR2(200);
EMP_FILE UTL_FILE.FILE_TYPE;
BEGIN
DBMS_OUTPUT.ENABLE(9000000);
EMP_FILE := UTL_FILE.FOPEN('EGIS_FILE_DIR','TEST.csv','R', 32767); -- open the file from oracle directory
v_line_in_record := 0; --we skip the first line
IF UTL_FILE.IS_OPEN(EMP_FILE) THEN
LOOP
v_line_in_record := v_line_in_record + 1;
--DBMS_OUTPUT.PUT_LINE(v_line_in_record);
BEGIN
UTL_FILE.GET_LINE(EMP_FILE,v_line_unclean);
IF v_line_in_record = 1 THEN-- first record here
DBMS_OUTPUT.PUT_LINE('');
ELSIF v_line_in_record = 2 THEN-- second record here (header)
DBMS_OUTPUT.PUT_LINE('');
DBMS_OUTPUT.PUT_LINE(v_line_unclean);
v_first_column := SUBSTR(v_line_unclean,1,instr(v_line_unclean,',',10,1)-1);
dbms_output.put_line('1st '||REGEXP_SUBSTR(v_line_unclean, '[^,]+', 1, 1));
ELSE -- body records here);
SELECT REPLACE(v_line_unclean,'((\)|^).*?(\(|$))|,', '\1')INTO v_line_clean FROM DUAL;
SQLSMT := 'INSERT INTO SITE_CONFIG_2G VALUES('''||v_line_clean||''')';
EXECUTE IMMEDIATE SQLSMT;
END IF;
COMMIT;
DBMS_OUTPUT.PUT_lINE(SQLSMT);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_lINE('NO DATA FOUND EXCEPTION');
EXIT;
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_lINE('TO MANY ROW EXCEPTION');
EXIT;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(sqlcode||sqlerrm);
ROLLBACK;
EXIT;
END;--EXCEPTION
END LOOP;
END IF;
UTL_FILE.FCLOSE(EMP_FILE);
END;
Result :
INSERT INTO SITE_CONFIG_2G VALUES('1,gold,benz,2018,1,blue,"34,000,000",6.4,new,CSV')
INSERT INTO SITE_CONFIG_2G VALUES('2,silver,bmw,2016,1,silver,"51,000,000",6.5,New,CSV')
INSERT INTO SITE_CONFIG_2G VALUES('3,bronze,range,2017,1,light-blue,"24,000,000",7.8,New,RVS')
I would like to remove commas between quotes in "24,000,000" to give me "24000000"
Current result is:
3,bronze,range,2017,1,light-blue,"24,000,000",7.8,New,RVS
Expected result is:
3,bronze,range,2017,1,light-blue,"24000000",7.8,New,RVS
can you try this.
select regexp_replace('1,gold,benz,2018,1,blue,"34,000,000",6.4,new,CSV',
'(")([^"|,]+)(,)([^"|,]+)(,)([^"|,]+)(")',
'\1\2\4\6\7') from dual;

PL/SQL file writing with generic input

I recently created a PL/SQL program that creates five different pipe delimited files from related data in a database.
I could not find a way to dynamically pull different tabular data in this case cursors, into a generic procedure that would create the files.
Instead I had to create five separate procedures, one for each file, that took in five different cursors, one for each file requirement record selection.
I can't help but think that there has to be a better way. I was looking into reference cursors but I don't think they are exactly what I am looking for.
How can I achieve this in PL/SQL?
I think what I am looking for is some generic type that can take any data from a cursor given any amount of records and record columns and have the ability to query itself to find what data is in it.
Pass the cursor into your procedure as a SYS_REFCURSOR. Then, use DBMS_SQL.TO_CURSOR_NUMBER(); to convert the ref cursor to a DBMS_SQL cursor.
Then, use DBMS_SQL.DESCRIBE_COLUMNS to figure out the columns in the cursor and DBMS_SQL.DEFINE_COLUMN, DBMS_SQL.FETCH_ROWS and DBMS_SQL.VALUE to get the data from the cursor into PL/SQL variables. Then, write your PL/SQL variables to your output file.
Here's some code that puts all that together for you.
DECLARE
l_rc SYS_REFCURSOR;
PROCEDURE dump_cursor (p_rc IN OUT SYS_REFCURSOR) IS
-- Dump the results of p_rc to log
l_cursor INTEGER;
l_column_count INTEGER;
l_column_descriptions SYS.DBMS_SQL.desc_tab;
l_status INTEGER;
l_column_value VARCHAR2 (4000);
l_column_width NUMBER;
l_rec_count NUMBER := 0;
l_line VARCHAR2 (4000);
FUNCTION get_length (l_column_def IN SYS.DBMS_SQL.desc_rec)
RETURN NUMBER IS
l_width NUMBER;
BEGIN
l_width := l_column_def.col_max_len;
l_width := CASE l_column_def.col_type WHEN 12 THEN /* DATE */
20 WHEN 2 THEN /* NUMBER */
10 ELSE l_width END;
-- Don't display more than 256 characters of any one column (this was my requirement -- your file writer probably doesn't need to do this
l_width := LEAST (256, GREATEST (l_width, l_column_def.col_name_len));
RETURN l_width;
END get_length;
BEGIN
-- This is the date format that I want to use for dates in my output
EXECUTE IMMEDIATE 'alter session set nls_date_format=''DD-MON-YYYY HH24:MI:SS''';
l_cursor := sys.DBMS_SQL.to_cursor_number (p_rc);
-- Describe columns
sys.DBMS_SQL.describe_columns (c => l_cursor, col_cnt => l_column_count, desc_t => l_column_descriptions);
l_line := '';
FOR i IN 1 .. l_column_count LOOP
l_column_width := get_length (l_column_descriptions (i));
l_line := l_line || RPAD (l_column_descriptions (i).col_name, l_column_width);
l_line := l_line || ' ';
DBMS_SQL.define_column (l_cursor,
i,
l_column_value,
4000);
END LOOP;
DBMS_OUTPUT.put_line (l_line);
l_line := '';
FOR i IN 1 .. l_column_count LOOP
l_column_width := get_length (l_column_descriptions (i));
l_line := l_line || RPAD ('-', l_column_width, '-');
l_line := l_line || ' ';
DBMS_SQL.define_column (l_cursor,
i,
l_column_value,
4000);
END LOOP;
DBMS_OUTPUT.put_line (l_line);
-- l_status := sys.DBMS_SQL.execute (l_cursor);
WHILE (sys.DBMS_SQL.fetch_rows (l_cursor) > 0) LOOP
l_rec_count := l_rec_count + 1;
l_line := '';
FOR i IN 1 .. l_column_count LOOP
DBMS_SQL.COLUMN_VALUE (l_cursor, i, l_column_value);
l_column_value := TRANSLATE (l_column_value, CHR (10), CHR (200));
l_column_width := get_length (l_column_descriptions (i));
IF l_column_value IS NULL THEN
l_line := l_line || RPAD (' ', l_column_width);
ELSE
l_line := l_line || RPAD (l_column_value, l_column_width);
END IF;
l_line := l_line || ' ';
END LOOP;
DBMS_OUTPUT.put_line (l_line);
END LOOP;
IF l_rec_count = 0 THEN
DBMS_OUTPUT.put_line ('No data found.');
ELSE
DBMS_OUTPUT.put_line (l_rec_count || ' rows returned.');
END IF;
sys.DBMS_SQL.close_cursor (l_cursor);
-- It would be better to store the current NLS_DATE_FORMAT on entry and restore it here, instead of assuming that it was
-- set to DD-MON-YYYY.
EXECUTE IMMEDIATE 'alter session set nls_date_format=''DD-MON-YYYY''';
EXCEPTION
WHEN OTHERS THEN
EXECUTE IMMEDIATE 'alter session set nls_date_format=''DD-MON-YYYY''';
-- Add your own handling here.
END dump_cursor;
-- Tester code, make sure server output is on
BEGIN
OPEN l_rc FOR 'SELECT object_id, object_name, object_type FROM dba_objects WHERE rownum <= 15';
dump_cursor(l_rc);
END;

Can you help me write a procedure in Oracle to spool data from a table to a CSV file?

I am writing a procedure to create a CSV file with the data in an Oracle table. I used "spool filename;" but an error is coming. Can I use spool in PL/SQL?
I think that there are better ways to implement this on Oracle 10g/11g, but this should work fine on Oracle 9i or higher:
CREATE OR REPLACE PROCEDURE prc_file_mult_column_generate(
p_file_dir VARCHAR2, -- mandatory (Oracle directory name)
p_file_name VARCHAR2, -- mandatory
p_sql_query VARCHAR2, -- Multiple column SQL SELECT statement that needs to be executed and processed
p_delimiter CHAR -- column delimiter
)
AS
l_cursor_handle INTEGER;
l_dummy NUMBER;
l_col_cnt INTEGER;
l_rec_tab DBMS_SQL.DESC_TAB;
l_current_col NUMBER(16);
l_current_line VARCHAR2(2047);
l_column_value VARCHAR2(300);
l_file_handle UTL_FILE.FILE_TYPE;
l_print_text VARCHAR2(100);
l_record_count NUMBER(16) := 0;
BEGIN
/* Open file for append*/
l_file_handle := UTL_FILE.FOPEN(p_file_dir, p_file_name, 'a', 2047); --Append Mode, 2047 chars per line max, possibly increasable
l_cursor_handle := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(l_cursor_handle, p_sql_query, DBMS_SQL.native);
l_dummy := DBMS_SQL.EXECUTE(l_cursor_handle);
/* Output column names and define them for latter retrieval of data */
DBMS_SQL.DESCRIBE_COLUMNS(l_cursor_handle, l_col_cnt, l_rec_tab); -- get column names
/* Append to file column headers */
l_current_col := l_rec_tab.FIRST;
IF (l_current_col IS NOT NULL) THEN
LOOP
DBMS_SQL.DEFINE_COLUMN(l_cursor_handle, l_current_col, l_column_value, 300);
l_print_text := l_rec_tab(l_current_col).col_name || p_delimiter;
UTL_FILE.PUT (l_file_handle, l_print_text);
l_current_col := l_rec_tab.NEXT(l_current_col);
EXIT WHEN (l_current_col IS NULL);
END LOOP;
END IF;
UTL_FILE.PUT_LINE (l_file_handle,' ');
/* Append data for each row */
LOOP
EXIT WHEN DBMS_SQL.FETCH_ROWS(l_cursor_handle) = 0; -- no more rows to be fetched
l_current_line := '';
/* Append data for each column */
FOR l_current_col IN 1..l_col_cnt LOOP
DBMS_SQL.COLUMN_VALUE (l_cursor_handle, l_current_col, l_column_value);
l_print_text := l_column_value || p_delimiter;
l_current_line := l_current_line || l_column_value || p_delimiter;
END LOOP;
l_record_count := l_record_count + 1;
UTL_FILE.PUT_LINE (l_file_handle, l_current_line);
END LOOP;
UTL_FILE.FCLOSE (l_file_handle);
DBMS_SQL.CLOSE_CURSOR(l_cursor_handle);
EXCEPTION
WHEN OTHERS THEN
-- Release resources
IF DBMS_SQL.IS_OPEN(l_cursor_handle) THEN
DBMS_SQL.CLOSE_CURSOR(l_cursor_handle);
END IF;
IF UTL_FILE.IS_OPEN (l_file_handle) THEN
UTL_FILE.FCLOSE (l_file_handle);
END IF;
--RAISE ;
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.format_error_stack);
END;
/
spool is a sqlplus command. it cannot be used in pl/sql.
it seems that you have been trying a variety of ways to get oracle to do your formatting and file saving. why not have your program that is calling the proc do this work for you?
If you only need the data in a cvs file you can do this:
create a sql file with the query like this:
set feedback off verify off heading off pagesize 0
select field1 || ',' || field2 ... from table;
quit;
/
then call sqlplus from a terminal like this:
sqlplus -S user/password #file.sql> cvsfile.cvs
No, SPOOL is a SQL Plus command so you would have to do this in SQL Plus:
spool myfile.txt
exec myproc
spool off
You would probably also need to set some values before starting the process e.g.
set pagesize 0 linesize 1000 trimspool on
... to get the correct formatting.
Here are a couple of links you might find helpful:
A PL/SQL Tutorial and SQL*Plus User Guide (11g)
Creating an ascii file: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:459020243348 and http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:68212348056 and http://www.oracle-developer.net/display.php?id=425 .

Resources