Check if a file exists? - sql

trying to check whether the file I want to read exists or not.

Here are another approaches:
Using BFILE and fileexists function of dbms_lob package:
create or replace function FileExists(
p_DirName in varchar2, -- schema object name
p_FileName in varchar2
) return number
is
l_file_loc bfile;
begin
l_file_loc := bfilename(upper(p_DirName), p_FileName);
return dbms_lob.fileexists(l_file_loc); -- 1 exists; 0 - not exists
end;
Using fgetattr function of utl_file package:
create or replace function FileExists(
p_DirName in varchar2, -- schema object name
p_FileName in varchar2
) return number
is
l_fexists boolean;
l_flen number;
l_bsize number;
l_res number(1);
begin
l_res := 0;
utl_file.fgetattr(upper(p_DirName), p_FileName, l_fexists, l_flen, l_bsize);
if l_fexists
then
l_res := 1;
end if;
return l_res;
end;

Use UTL_FILE.FGETATTR function.
This function is designed specifically for this purpose.
Syntax:
UTL_FILE.FGETATTR(
location IN VARCHAR2,
filename IN VARCHAR2,
fexists OUT BOOLEAN,
file_length OUT NUMBER,
block_size OUT BINARY_INTEGER);
Example:
DECLARE
fexists BOOLEAN;
file_length NUMBER;
block_size BINARY_INTEGER;
BEGIN
UTL_FILE.FGETATTR('MY_ORA_DIRECTORY', 'my_file_name.csv', fexists, file_length, block_size);
IF fexists THEN
-- Do something
-- ...
END IF;
END IF;
Oracle documentation:
https://docs.oracle.com/database/121/ARPLS/u_file.htm#ARPLS70915
One more useful link:
https://www.foxinfotech.in/2018/09/how-to-check-if-file-exists-in-pl-sql.html

Creating a function that checks if a file exists is fairly easy by just trying to open it and catching any exceptions (this example function taken from AskTom)
CREATE OR REPLACE FUNCTION file_exists(p_fname IN VARCHAR2) RETURN BOOLEAN
AS
l_file UTL_FILE.FILE_TYPE;
BEGIN
l_file := UTL_FILE.FOPEN(SUBSTR( p_fname, 1, instr(p_fname,'/',-1) ),
SUBSTR( p_fname, instr( p_fname, '/', -1)+1 ), 'r' );
UTL_FILE.FCLOSE( l_file );
RETURN TRUE;
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN RETURN FALSE;
WHEN UTL_FILE.INVALID_OPERATION THEN RETURN FALSE;
END;
/
Then you can just use;
IF ( file_exists( 'MED_LIST_19_OCT_12.csv' ) )
...

Related

How convert long text to UTF8 in Oracle 11g?

I have large text around 20000 I need convert to UTF8.
select convert('large text','UTF8') from dual
I get error:
ORA-01704: string literal too long
Try this get another error
declare
v_hugetxt varchar2(32767);
begin
v_hugetxt:='huge text'
select convert(v_hugetxt,'UTF8') into v_hugetxt
from dual;
end;
I get error
ORA-01460: unimplemented or unreasonable conversion requested tips ยท
Incompatible character sets can cause an ORA-01460
I found solution but worked
FYI
create or replace function v_blobtoclob(v_blob_in in blob) return clob is
v_file_clob clob;
v_file_size integer := dbms_lob.lobmaxsize;
v_dest_offset integer := 1;
v_src_offset integer := 1;
v_blob_csid number := dbms_lob.default_csid;
v_lang_context number := dbms_lob.default_lang_ctx;
v_warning integer;
v_length number;
begin
dbms_lob.createtemporary(v_file_clob, true);
dbms_lob.converttoclob(v_file_clob,
v_blob_in,
v_file_size,
v_dest_offset,
v_src_offset,
v_blob_csid,
v_lang_context,
v_warning);
return v_file_clob;
exception
when others then
dbms_output.put_line('Error found');
end;
CREATE OR REPLACE FUNCTION clob_to_blob (p_clob CLOB, p_charsetname VARCHAR2)
RETURN BLOB
AS
l_lang_ctx INTEGER := DBMS_LOB.default_lang_ctx;
l_warning INTEGER;
l_dest_offset NUMBER := 1;
l_src_offset NUMBER := 1;
l_return BLOB;
BEGIN
DBMS_LOB.createtemporary (l_return, FALSE);
DBMS_LOB.converttoblob (
l_return,
p_clob,
DBMS_LOB.lobmaxsize,
l_dest_offset,
l_src_offset,
CASE WHEN p_charsetname IS NOT NULL THEN NLS_CHARSET_ID (p_charsetname) ELSE DBMS_LOB.default_csid END,
l_lang_ctx,
l_warning);
RETURN l_return;
END;
declare
v_hugetxt clob;
v_hugetxt2 blob;
v_hugetxt3 clob;
offset int;
clobsize number;
begin
v_hugetxt:='huge text';
select bnf.clob_to_blob(v_hugetxt,'UTF8') into v_hugetxt2 from dual;
select bnf.v_blobtoclob(v_hugetxt2) into v_hugetxt3 from dual;
dbms_output.put_line('Print CLOB');
offset:=1;
loop
exit when offset > dbms_lob.getlength(v_hugetxt3);
dbms_output.put_line(dbms_lob.substr(v_hugetxt3, 255, offset));
offset := offset + 255;
end loop;
DBMS_OUTPUT.PUT_LINE('clob out = ' || v_hugetxt3);
end;
That's it

A functions code is written in oracle. I am unable to understand what it is doing

Here is the function:
create or replace FUNCTION FUNC_PART(
p_TEXT varchar2,
p_COLUMN number,
p_SEPARATOR varchar2
) RETURN varchar2 AS
v_POS_ number;
v_POS2 number;
V_COLUMN NUMBER;
BEGIN
V_COLUMN:=p_COLUMN;
v_POS_ := 1;
v_POS2 := INSTR(p_TEXT, p_SEPARATOR, v_POS_);
WHILE (V_COLUMN >1 AND v_POS2> 0) LOOP
v_POS_ := v_POS2 + 1;
v_POS2 := INSTR(p_TEXT, p_SEPARATOR, v_POS_);
V_COLUMN :=V_COLUMN - 1;
END LOOP;
IF V_COLUMN > 1 THEN
v_POS_ := LENGTH(RTRIM(p_TEXT)) + 1;
END IF;
IF v_POS2 = 0 THEN
v_POS2 := LENGTH(RTRIM(p_TEXT)) + 1;
END IF;
RETURN SUBSTR (p_TEXT, v_POS_, v_POS2 - v_POS_);
END;
I did not understand this code carefully, but from the results, the following two pieces of code have the same meaning.
select FUNC_PART('asdfghsdfg', 3, 's')
from dual;
select regexp_substr('asdfghsdfg', '[^s]+', 1, 3)
from dual;
This is likely to be migrated from other databases to the code in oracle, because oracle does not need such a custom function

passing sys_refcursor from function to sys_refcursor out parameter in procedure

I have problem with outputting results from the sys_refcursor returned from the function stored in the variable crs_scenarios. I then want to pass this collection of data to the output parameter pout_result. I get the error PLS-00487: Invalid reference to variable 'POUT_RESULT'. Can you advise me please, how to solve this issue?
Thanks a lot!
declare
pin_scenarioName scenarios.scen_name%TYPE := 'zz_berlin_testen';
pin_scenarioRegion inf_ausbaugebiete.ausg_name%TYPE DEFAULT NULL;
pin_scenarioCutOffDate scenarios.scen_cut_off_date%TYPE DEFAULT NULL;
pin_scenarioStatus scenario_status.scst_name%TYPE DEFAULT NULL;
pout_result SYS_REFCURSOR;
pout_strerrorcode VARCHAR2(1000);
pout_strerrormessage VARCHAR2(1000);
BEGIN
pout_result := funk30.pbi$capi_export_pck.cfn_getscenarios(pin_scenarioName => pin_scenarioName,
pin_scenarioRegion => pin_scenarioRegion,
pin_scenarioCutOffDate => pin_scenarioCutOffDate,
pin_scenarioStatus => pin_scenarioStatus,
pout_strerrorcode => pout_strerrorcode,
pout_strerrormessage => pout_strerrormessage);
dbms_output.put_line(pout_result.ID || ' ' ||pout_result.NAME || ' ' ||pout_result.CUT_OFF || ' ' ||pout_result.STATUS ||
' ' || pout_result.PRIORITY || ' ' ||pout_result.PARENT_SCENARIO|| ' ' ||pout_result.REGION|| ' ' || pout_result.REMARK);
END cpr_getscenarios;
Function:
FUNCTION mfn_getscenarios(pin_scenarioName IN scenarios.scen_name%TYPE DEFAULT NULL,
pin_scenarioRegion IN inf_ausbaugebiete.ausg_name%TYPE DEFAULT NULL,
pin_scenarioCutOffDate IN scenarios.scen_cut_off_date%TYPE DEFAULT NULL,
pin_scenarioStatus IN scenario_status.scst_name%TYPE DEFAULT NULL,
pout_strerrorcode OUT VARCHAR2,
pout_strerrormessage OUT VARCHAR2)
RETURN SYS_REFCURSOR IS
crs_scenarios SYS_REFCURSOR;
n_cnt_exists NUMBER;
ex_scennotexists EXCEPTION;
strprocedurename VARCHAR2(128) := package_name || '.mfn_getScenarios';
BEGIN
BEGIN
SELECT 1 INTO n_cnt_exists FROM scenarios WHERE rownum = 1;
EXCEPTION
WHEN no_data_found THEN
RAISE ex_scennotexists;
END;
OPEN crs_scenarios FOR
SELECT scen.scen_id id,
scen.scen_name NAME,
scen.scen_cut_off_date cut_off,
scst.scst_name STATUS,
scen.scen_priority PRIORITY,
parent.scen_name PARENT_SCENARIO,
ausg.ausg_name REGION,
scen.scen_comment REMARK
FROM scenarios scen,
scenarios parent,
scenario_status scst,
inf_ausbaugebiete ausg
WHERE scen.scen_scst_id = scst.scst_id
AND scen.scen_parent_scen_id = parent.scen_id(+)
AND scen.scen_ausg_id= ausg.ausg_id(+)
AND lower(scen.scen_name) like nvl(lower('%'||pin_scenarioName||'%'), lower(scen.scen_name))
AND NVL(ausg.ausg_name, 'xxxxx') = nvl(pin_scenarioRegion, NVL(ausg.ausg_name, 'xxxxx'))
AND scen.scen_cut_off_date = nvl(pin_scenarioCutOffDate, scen.scen_cut_off_date)
AND scst.scst_name = nvl(pin_scenarioStatus, scst.scst_name);
pout_strerrorcode := '0';
pout_strerrormessage := '';
RETURN crs_scenarios;
EXCEPTION
WHEN ex_scennotexists THEN
pout_strerrorcode := 'API-00239';
pout_strerrormessage := rtrim(api_err_pck.apierrormsg('API-00239', strprocedurename), ' #');
RETURN NULL;
WHEN OTHERS THEN
pout_strerrorcode := '-1';
pout_strerrormessage := substr(SQLERRM, instr(SQLERRM, 'ORA') + 11, length(SQLERRM));
RETURN NULL;
END mfn_getscenarios;
Sys_refcursor is only a SQL definition. If you want to run it, you have to FETCH data.
So pout_result varible has no data itself.
-------- function -----
create or replace FUNCTION mfn
RETURN SYS_REFCURSOR IS
crs_scenarios SYS_REFCURSOR;
BEGIN
OPEN crs_scenarios FOR
SELECT dummy from dual;
RETURN crs_scenarios;
END ;
-- execution
set serveroutput on
declare
pout_result SYS_REFCURSOR;
type pout_result_tab is table of dual%rowtype; -- cursor datatype
pout_result_t pout_result_tab;
BEGIN
pout_result := mfn;
fetch pout_result bulk collect into pout_result_t; -- bulk collect because I assume you have recordset, not one record
dbms_output.put_line(pout_result_t(1).dummy);
END ;
/
--- Result
X
PL/SQL procedure successfully completed.

Assign ref variable value oracle

hHey,
I want to set the value of the assignment value in the method of the node_ty. However I get the error that navigation through Ref variables is not allowed or the typ I want to assign is not correct. So I don't really know how to do that. Could you help me with that?
CREATE OR REPLACE TYPE property_ty AS OBJECT(
name VARCHAR2(100)
);
/
CREATE OR REPLACE TYPE assignment_ty AS OBJECT(
value VARCHAR2(100),
property REF property_ty
);
/
CREATE OR REPLACE TYPE property_tty AS TABLE OF property_ty;
/
CREATE OR REPLACE TYPE node_ty AS OBJECT(
x NUMBER,
y NUMBER,
assignment REF assignment_ty,
property property_tty,
MEMBER PROCEDURE set_assignment (name VARCHAR2, value VARCHAR2)
);
/
CREATE OR REPLACE TYPE BODY node_ty AS
MEMBER PROCEDURE set_assignment (name VARCHAR2, value VARCHAR2) AS
prop_not_added EXCEPTION;
prop_exists BOOLEAN := FALSE;
assig_test assignment_ty;
prop property_ty;
BEGIN
FOR i IN 1..self.property.COUNT
LOOP
IF property(i).name = name THEN
prop.name :=name;
assig_test.value :=value;
assig_test.property := prop;
assignment := assig_test;
prop_exists := TRUE;
END IF;
END LOOP;
IF prop_exists = FALSE THEN
RAISE prop_not_added;
END IF;
EXCEPTION
WHEN prop_not_added THEN
DBMS_OUTPUT.PUT_LINE('Property cannot be set');
END;
END;
/
You have to create the necessary setup and then query the data from the setup.I am giving only the setup which is different from yours.The remaining you can keep it as same as your setup
create table t00 of property_ty;
insert into t00 values('san');
create table t0 of assignment_ty;
insert into t0 select 'xxx',REF(p) from t00 p;
CREATE OR REPLACE TYPE node_ty AS OBJECT(
x NUMBER,
y NUMBER,
assignment REF assignment_ty,
property property_tty,
MEMBER PROCEDURE set_assignment (p_name VARCHAR2, p_value VARCHAR2)
);
create or replace TYPE BODY node_ty AS
MEMBER PROCEDURE set_assignment (p_name VARCHAR2, p_value VARCHAR2) AS
prop_not_added EXCEPTION;
prop_exists BOOLEAN := FALSE;
assig_test REF assignment_ty;
prop1 property_ty;
prop REF property_ty;
BEGIN
FOR i IN 1..self.property.COUNT
LOOP
IF property(i).name = p_name THEN
SELECT REF(a) INTO assignment FROM t0 a,t00 b where a.value=p_value and b.name=p_name
and ref(b)=property;
prop_exists := TRUE;
END IF;
END LOOP;
IF prop_exists = FALSE THEN
RAISE prop_not_added;
END IF;
EXCEPTION
WHEN prop_not_added THEN
DBMS_OUTPUT.PUT_LINE('Property cannot be set');
END;
END;

return a varray from a function oracle

I want to return a varray from oracle function but I don't know how to do it.
Here is so far what I have tried.
set serveroutput on;
declare
type array_t is varray(2) of number;
CREATE OR REPLACE FUNCTION func() return array_t
begin
array array_t :=array_t(0,0);
array(1):=3;
array(2):=20;
return array;
end;
hier is the right syntax for your function
create type array_t is varray(2) of number;
/
CREATE OR REPLACE FUNCTION func return array_t
IS
v_array array_t;
begin
v_array :=array_t(0,0);
v_array(1):=3;
v_array(2):=20;
return v_array;
end;
/
you can call the function for example in an anonymous plsql block
declare
v_func_result array_t;
begin
v_func_result := func();
dbms_output.put_line(v_func_result(1));
dbms_output.put_line(v_func_result(2));
end;
/
You do not need to declare a procedure in the SQL scope; you can declare it as a nested sub-program in an anonymous PL/SQL block:
SET SERVEROUTPUT ON;
DECLARE
TYPE array_t IS VARRAY(2) OF NUMBER;
data array_t;
FUNCTION func RETURN array_t IS BEGIN RETURN array_t( 3, 20 ); END func;
BEGIN
data := func();
DBMS_OUTPUT.PUT_LINE( '(' || data(1) || ', ' || data(2) || ')' );
END;
/