How convert long text to UTF8 in Oracle 11g? - sql

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

Related

ORACLE SQL function to return JSON response

I have table like below. I am trying to pull all BRKPK_CNTNR_ID, SSP_Q with respect to each OVRPK_CNTNR_ID
enter image description here
Below query runs fine and produces desired result.
DECLARE
json_objects JSON_OBJECT_LIST := JSON_OBJECT_LIST() ;
counter NUMBER := 1;
BEGIN
FOR ovrpk_detail IN (SELECT OVRPK_CNTNR_ID ,BRKPK_CNTNR_ID,ITEM_DISTB_Q FROM OVRPK_DET od WHERE od.OVRPK_CNTNR_ID='92000000356873110552') LOOP
begin
json_objects.extend;
json_objects(counter) :=JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id',ovrpk_detail.OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id',ovrpk_detail.BRKPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('item_distributed_quantity',ovrpk_detail.ITEM_DISTB_Q)
));
counter := counter+1;
END;
END LOOP;
dbms_output.put_line( JSON_UTIL.JSON_ARRAY(json_objects));
END;
I am expecting is to create function that takes OVRPK_CNTNR_ID as input and returns JSON_OBJECT_LIST as output.
Here is my query I tried.
CREATE OR REPLACE FUNCTION get_json_objects(ovrk_cntnr_id IN CHAR)
RETURN JSON_OBJECT_LIST IS
json_objects JSON_OBJECT_LIST := JSON_OBJECT_LIST();
BEGIN
DECLARE counter NUMBER := 1;
FOR ovrpk_detail IN (SELECT OVRPK_CNTNR_ID ,BRKPK_CNTNR_ID FROM OVRPK_DET od WHERE od.OVRPK_CNTNR_ID= ovrk_cntnr_id) LOOP
begin
json_objects.extend;
json_objects(counter) :=JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id',ovrpk_detail.OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id',ovrpk_detail.BRKPK_CNTNR_ID)
));
counter := counter+1;
END;
END LOOP;
RETURN json_objects;
END;
DECLARE
json_return_object JSON_OBJECT_LIST;
ovrk_cnt_i char := '92000000356873110552'
BEGIN
json_return_object := get_json_objects(ovrk_cnt_i);
dbms_output.put_line('JSON Object is: ' || json_return_object);
END;
I am missing something, would anyone help me to resolve this issue? Thank you
Note: I am using Oracle 12.c database which does not support JSON however, JSON_UTIL is library written internally to address same
We do not have your packages or functions so this is difficult to test.
Your code has a DECLARE without a corresponding BEGIN or END. If you get rid of all the unnecessary DECLARE/BEGIN/END statements then you can simplify it to:
CREATE OR REPLACE FUNCTION get_json_objects(
ovrk_cntnr_id IN CHAR
)
RETURN JSON_OBJECT_LIST
IS
json_objects JSON_OBJECT_LIST := JSON_OBJECT_LIST();
counter NUMBER := 1;
BEGIN
FOR ovrpk_detail IN (
SELECT OVRPK_CNTNR_ID,
BRKPK_CNTNR_ID
FROM OVRPK_DET
WHERE OVRPK_CNTNR_ID = ovrk_cntnr_id
) LOOP
json_objects.extend;
json_objects(counter) :=JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id',ovrpk_detail.OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id',ovrpk_detail.BRKPK_CNTNR_ID)
)
);
counter := counter+1;
END LOOP;
RETURN json_objects;
END;
/
If your package functions are callable from SQL then you should be able to simplify it further to:
CREATE OR REPLACE FUNCTION get_json_objects(
i_ovrpk_cntnr_id IN OVRPK_DET.OVRPK_CNTNR_ID%TYPE
) RETURN JSON_OBJECT_LIST
IS
json_objects JSON_OBJECT_LIST;
BEGIN
SELECT JSON_UTIL.JSON_OBJECT(
JSON_ATTRIBUTE_LIST(
JSON_UTIL.JSON_ATTRIBUTE('over_pack_container_id', OVRPK_CNTNR_ID),
JSON_UTIL.JSON_ATTRIBUTE('break_pack_container_id', BRKPK_CNTNR_ID)
)
)
BULK COLLECT INTO json_objects
FROM OVRPK_DET
WHERE OVRPK_CNTNR_ID = i_ovrpk_cntnr_id;
RETURN json_objects;
END;
/
DECLARE
json_return_object JSON_OBJECT_LIST;
ovrk_cnt_i OVRPK_DET.OVRPK_CNTNR_ID%TYPE := '92000000356873110552'
BEGIN
json_return_object := get_json_objects(ovrk_cnt_i);
dbms_output.put_line('JSON Object is: ' || json_return_object);
END;
/

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

Bypass the JSON object using PL / SQL, and output all data in key value format in Oracle

I have JSON, I want to bypass it and display all the data that is in it. But the problem is that I can't know what data will be there. I made the code, but it only looks for top-level objects. And the rest are not. I will be grateful for your help.
DECLARE
l_object json_object_t;
l_key_list json_key_list;
v_clob CLOB;
tv apex_json.t_values;
BEGIN
-- JSON_OBJECT can figure out what keys it has...
v_clob := '{"devices":{"id":"d652f632-0835-871b-a140-58701f019000","scale_id":"88348A32BD3D149FE055000000000001"},"data":{"external_id":"40023"},"data_weight":{"weight":"20322","prevWeight":"1000","prevTransaction":"1607680754361","transaction":"1607680754361","on":"false","transactionDataCount":"1","stable":"false","duration":"12","transactionMaxWeight":"2000","perimetr":"true","driverInCar":"false"}}';
apex_json.parse(tv,v_clob);
l_object := json_object_t.parse (v_clob);
l_key_list := l_object.get_keys;
FOR counter IN 1 .. l_key_list.COUNT
LOOP
DBMS_OUTPUT.put_line (
l_key_list (counter)
|| ' : '
|| apex_json.get_varchar2(p_path => l_key_list (counter), p_values => tv));
END LOOP;
END;
If you take into account only the top level objects, then this code works
DECLARE
l_object json_object_t;
l_key_list json_key_list;
v_clob CLOB;
tv apex_json.t_values;
BEGIN
-- JSON_OBJECT can figure out what keys it has...
v_clob := '{"devices":"3423","data":"okwwwe"}';
apex_json.parse(tv,v_clob);
l_object := json_object_t.parse (v_clob);
l_key_list := l_object.get_keys;
FOR counter IN 1 .. l_key_list.COUNT
LOOP
DBMS_OUTPUT.put_line (
l_key_list (counter)
|| ' : '
|| apex_json.get_varchar2(p_path => l_key_list (counter), p_values => tv));
END LOOP;
END;
RESULT :
devices : 3423
data : okwwwe
And how to deduce the data from the first example, I can not understand. These data must correspond to the hierarchy.
If you have access to the native JSON types (JSON_ELEMENT_T, JSON_ARRAY_T, etc.) you should always use them over using the APEX_JSON package ans they will have much better performance. A package similar to the one below can be used to output the full hierarchy of a JSON object or array. Feel free to tweak the package to change the format of the output.
Package Specification
CREATE OR REPLACE PACKAGE output_json
AS
c_padding_char CONSTANT VARCHAR2 (1) := '-';
c_padding_amount CONSTANT PLS_INTEGER := 1;
PROCEDURE output_scalar (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL);
PROCEDURE output_object (p_object json_object_t, p_padding PLS_INTEGER);
PROCEDURE output_array (p_array json_array_t, p_padding PLS_INTEGER);
PROCEDURE output_element (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL);
END;
/
Package Body
CREATE OR REPLACE PACKAGE BODY output_json
AS
PROCEDURE output_scalar (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL)
IS
BEGIN
DBMS_OUTPUT.put_line (
LPAD (c_padding_char, p_padding, c_padding_char)
|| CASE WHEN p_json_key IS NOT NULL THEN p_json_key || ' : ' END
|| CASE
WHEN p_element.is_boolean
THEN
CASE WHEN p_element.to_boolean THEN 'TRUE' ELSE 'FALSE' END || ' (boolean)'
WHEN p_element.is_date
THEN
TO_CHAR (p_element.TO_DATE, 'YYYY-MM-DD') || ' (date)'
WHEN p_element.is_number
THEN
p_element.TO_NUMBER || ' (number)'
WHEN p_element.is_string
THEN
p_element.TO_STRING || ' (string)'
END);
END;
PROCEDURE output_object (p_object json_object_t, p_padding PLS_INTEGER)
IS
l_keys json_key_list;
l_element json_element_t;
BEGIN
l_keys := p_object.get_keys;
FOR i IN 1 .. l_keys.COUNT
LOOP
l_element := p_object.get (l_keys (i));
output_element (l_element, p_padding, l_keys (i));
END LOOP;
END;
PROCEDURE output_array (p_array json_array_t, p_padding PLS_INTEGER)
IS
BEGIN
FOR i IN 0 .. p_array.get_size - 1
LOOP
output_element (p_array.get (i), p_padding);
END LOOP;
END;
PROCEDURE output_element (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL)
IS
BEGIN
DBMS_OUTPUT.put_line (
CASE
WHEN p_json_key IS NOT NULL AND NOT p_element.is_scalar THEN p_json_key || ' : '
END);
IF p_element.is_scalar
THEN
output_scalar (p_element, p_padding, p_json_key);
ELSIF p_element.is_object
THEN
output_object (TREAT (p_element AS json_object_t), p_padding + c_padding_amount);
ELSIF p_element.is_array
THEN
output_array (TREAT (p_element AS json_array_t), p_padding + c_padding_amount);
END IF;
END;
END;
/
Example Call
DECLARE
l_clob CLOB;
BEGIN
l_clob :=
'{"arr":[1,2,3],"devices":{"id":"d652f632-0835-871b-a140-58701f019000","scale_id":"88348A32BD3D149FE055000000000001"},"data":{"external_id":"40023"},"data_weight":{"weight":"20322","prevWeight":"1000","prevTransaction":"1607680754361","transaction":"1607680754361","on":"false","transactionDataCount":"1","stable":"false","duration":"12","transactionMaxWeight":"2000","perimetr":"true","driverInCar":"false"}}';
output_json.output_element (json_element_t.parse (l_clob), 0);
END;
/
Example Output
arr :
--1 (number)
--2 (number)
--3 (number)
devices :
--id : "d652f632-0835-871b-a140-58701f019000" (string)
--scale_id : "88348A32BD3D149FE055000000000001" (string)
data :
--external_id : "40023" (string)
data_weight :
--weight : "20322" (string)
--prevWeight : "1000" (string)
--prevTransaction : "1607680754361" (string)
--transaction : "1607680754361" (string)
--on : "false" (string)
--transactionDataCount : "1" (string)
--stable : "false" (string)
--duration : "12" (string)
--transactionMaxWeight : "2000" (string)
--perimetr : "true" (string)
--driverInCar : "false" (string)
I also made my own version, but it is limited to 2 levels of objects, and does not take into account arrays.
DECLARE
l_object json_object_t;
l_key_obj json_key_list;
v_clob CLOB;
tv apex_json.t_values;
obj_in_obj JSON_OBJECT_T;
l_key_list json_key_list;
BEGIN
v_clob := '{
"devices":{
"id":"d652f632-0835-871b-a140-58701f019000",
"scale_id":"88348A32BD3D149FE055000000000001"
},
"data":{
"external_id":"40023"
},
"data_weight":{
"weight":"20322",
"prevWeight":"1000",
"prevTransaction":"1607680754361",
"transaction":"1607680754361",
"on":"false",
"transactionDataCount":"1",
"stable":"false",
"duration":"12",
"transactionMaxWeight":"2000",
"perimetr":"true",
"driverInCar":"false"
}
}';
apex_json.parse(tv,v_clob);
l_object := json_object_t.parse (v_clob);
l_key_list := l_object.get_keys;
FOR counter IN 1 .. l_key_list.COUNT
LOOP
obj_in_obj := l_object.get_object(l_key_list (counter));
l_key_obj := obj_in_obj.get_keys;
FOR counter_all_obj IN 1 .. l_key_obj.COUNT
LOOP
DBMS_OUTPUT.put_line (
l_key_list (counter)||'.'||l_key_obj (counter_all_obj)
|| ' : '
|| apex_json.get_varchar2(p_path => l_key_list (counter)||'.'|| l_key_obj (counter_all_obj), p_values => tv));
END LOOP;
END LOOP;
END;

Error ORA-06530 from function that returns an object type

I have the following function GET_UN_COLLECTED_4LD which returns the type ld_data_type:
CREATE OR REPLACE TYPE ld_data_type AS OBJECT(collected NUMBER, uncollected NUMBER);
/
CREATE OR REPLACE FUNCTION GET_UN_COLLECTED_4LD (VAPPOINTOFCAID NUMBER,
VPREVLIQUIDATE NUMBER,
VCURRLIQUIDATE NUMBER,
VNEXTLIQUIDATE NUMBER,
YEPT NUMBER)
RETURN LD_DATA_TYPE
AS
OUT_VAR LD_DATA_TYPE;
VNETV23 NUMBER;
VNETV24 NUMBER;
VCURR23 NUMBER;
VCURR24 NUMBER;
VCOLLECTED NUMBER;
VUNCOLLECTED NUMBER;
BEGIN
SELECT SUM (NETX) - SUM (NETP)
INTO VNETV23
FROM VIEW_CUSTOMER_TRN4INVS4LD
WHERE APPOINTOFCAID = VAPPOINTOFCAID AND VAT = ABS (1.23);
SELECT SUM (NETX) - SUM (NETP)
INTO VNETV24
FROM VIEW_CUSTOMER_TRN4INVS4LD
WHERE APPOINTOFCAID = VAPPOINTOFCAID AND VAT = ABS (1.24);
VCOLLECTED := 0;
VUNCOLLECTED := 0;
CASE
WHEN YEPT = 0
THEN
VCURR24 := VCURRLIQUIDATE - VNETV24;
CASE
WHEN VCURR24 > 0
THEN
VCOLLECTED := VNETV24 * 1.24;
VCURR23 := VCURRLIQUIDATE - VNETV23;
CASE
WHEN VCURR23 > 0
THEN
VCOLLECTED := -999;
ELSE
VCOLLECTED :=
VCOLLECTED + ( (VCURRLIQUIDATE - VCURR24) * 1.23);
END CASE;
ELSE
VCOLLECTED := -1999;
END CASE;
ELSE
OUT_VAR.COLLECTED := -888;
OUT_VAR.UNCOLLECTED := -889;
END CASE;
SELECT VCOLLECTED, VUNCOLLECTED
INTO OUT_VAR.COLLECTED, OUT_VAR.UNCOLLECTED
FROM DUAL;
/*
OPEN buffer_cur;
FETCH buffer_cur INTO out_var.val1, out_var.val2;
CLOSE buffer_cur; */
RETURN OUT_VAR;
END GET_UN_COLLECTED_4LD;
When I call the function like
select GET_UN_COLLECTED_4LD(171231, 42240, 31680, 0, 0) from dual;`
I get an error:
Execution (50: 8): ORA-06530: Reference to uninitialized composite
ORA-06512: at "C##SOLSA.GET_UN_COLLECTED_4LD", line 56
I'm use Oracle 12c Standard edition.
How should I be calling the function GET_UN_COLLECTED_4LD and Where is the problem that causes the error?
As the error says, you haven't initialised your object variable:
...
RETURN LD_DATA_TYPE
AS
OUT_VAR LD_DATA_TYPE := new LD_DATA_TYPE(null, null);
...
Your logic is slightly confused though; at the end of your case you do:
ELSE
OUT_VAR.COLLECTED := -888;
OUT_VAR.UNCOLLECTED := -889;
but then overwrite the value immediately afterwards with:
SELECT VCOLLECTED, VUNCOLLECTED
INTO OUT_VAR.COLLECTED, OUT_VAR.UNCOLLECTED
FROM DUAL;
Possibly you meant to set VCOLLECTED and VUNCOLLECTED in that ELSE. If you did that then you wouldn't need to initialise OUT_VAR, as the first remaining reference would create it; which you could do as:
OUT_VAR := LD_DATA_TYPE (VCOLLECTED, VUNCOLLECTED);
instead of selecting from dual; or you could not have the local variable at all and just do:
...
ELSE
VCOLLECTED := -888;
VUNCOLLECTED := -889;
END CASE;
RETURN LD_DATA_TYPE (VCOLLECTED, VUNCOLLECTED);
END GET_UN_COLLECTED_4LD;
First you need to initialize your object type OUT_VAR before you can set its properties like this:
OUT_VAR:= LD_DATA_TYPE(0,0);
See the details here.

Check if a file exists?

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' ) )
...