ORACLE inserts with CLOB column (more than 4000 characters) - sql

first of all sorry for my english.
I am trying to insert approximately 15000 rows, the problem is that there is a column of type CLOB that can have more than 4000 characters giving the error ORA-01704, I know how to insert one by one like this: TO_CLOB (string) || TO_CLOB (string) and it works, but I have approximately 1000 cases where it happens and I don't want to do it manually, what way can you think of to insert them?
Thank you.

i think you're trying something like that:
insert into values('your clob data');
in this case you are using sql literal size which length 4000 bytes.
11g and below,the limit is 4000 bytes.
But if you use script like that :
declare
l_clob varchar2(32767);
begin
...
insert into values(l_clob );
...
end
it means you are using pl sql literal string which has 32k.

Related

in Oracle database, how do I create a table of varchar2 type without length

for using it as a returning type in a function, I need to create a type at database level.
I do it by typing the command :
CREATE TYPE empno_tbl
IS TABLE OF VARCHAR2(100);
but this obliges me to choose a length.
I would like to create a string kind table type without a specific length.
is there a way to do this ?
If you really want it without a length then use CLOB.
CREATE TYPE empno_tbl IS TABLE OF CLOB;
(There is a limit but in Oracle 19c the CLOB datatype has a limit of 4GB * DB_BLOCK_SIZE initialization parameter, which gives a total size of 8 TB to 128 TB, and if you are reaching that limit then there is probably something wrong with your approach.)
The maximum size for a VARCHAR2 is 4000 bytes, so if you can cope with that limit then just use:
CREATE TYPE empno_tbl IS TABLE OF VARCHAR2(4000);

Can I use Varchar2(32767) or Varchar2 Table in IN of sql statement

I have stored function which is returning Varchar2 (32767) and I want to use it in select statement under IN But it gives me error when i use it in Select under IN clause.
SELECT * FROM testcustomers1 where no_of_bu1 in(select myMaxLenFunc('test') from dual);
It gives me error
Error :-
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
If the return value is less than 4k it works fine but if it is greater than that it throws the above error.
Please suggest me if I use varchar2 table or Varchar2 are return in stored function how can i use it IN clause in select.
You have the right idea using a collection instead of a string in the IN clause. Then you will not run into this problem. Try something like this:
CREATE OR REPLACE TYPE strings_t IS TABLE OF VARCHAR2 (4000)
/
CREATE OR REPLACE FUNCTION strings
RETURN strings_t
AUTHID DEFINER
IS
BEGIN
RETURN strings_t ('abc', 'def', '123');
END;
/
CREATE TABLE t (s VARCHAR2 (100))
/
BEGIN
INSERT INTO t
VALUES ('abd');
INSERT INTO t
VALUES ('def');
INSERT INTO t
VALUES ('456');
COMMIT;
END;
/
SELECT *
FROM t
WHERE t.s IN (SELECT COLUMN_VALUE FROM TABLE (strings ()))
/
Your function is PL/SQL and can return a varchar2 string of more than 4000. This is illegal for SQL (if the MAX_STRING_SIZE parameter is of value STANDARD)
http://docs.oracle.com/cd/E11882_01/appdev.112/e17126/datatypes.htm
VARCHAR2 Maximum Size in PL/SQL: 32,767 bytes Maximum Size in SQL
4,000 bytes
So you need to find a way around. Since no_of_bu1 is a SQL column and cannot have more than 4000 bytes in content length you are save with this:
SELECT * FROM testcustomers1
where no_of_bu1 in(select substr(myMaxLenFunc('test'),1,4000) from dual);
Although I would truncate the string within the function.
If your DB is of Oracle 12.1 you can find out if your are STANDARD in SQL stringsize (i.e. 4000)
SELECT name, value
FROM v$parameter
WHERE name = 'max_string_size'

Substr with more than 4000 characters gets ORA-06502: PL/SQL: numeric or value error

In the below script if I try to substr for 4000 character it works and displays all text in my particular ID with respective DB field ID and Language, if I increase it even 4001 db pops up the error - ora-06502: pl/sql: numeric or value error.
Create or replace function GET_AER_TEXT5(M_AER_ID IN NUMBER,
F_ID IN VARCHAR2,PREF_LANGUAGE IN VARCHAR2)
IS
AERTEXT VARCHAR2(32000);
LANG_PARAM VARCHAR2(2000);
AER_CLOB CLOB;
BEGIN
FOR c1 IN (
select TEXT from AER_TEXT
where FIELD_ID=F_ID and AER_ID=M_AER_ID and LANGUAGE IN(PREF_LANGUAGE)
)
LOOP
IF c1.text IS NOT NULL THEN
AER_CLOB:=AER_CLOB || c1.text;
END IF;
END LOOP;
AERTEXT:=substr(AER_CLOB,1,4000);
RETURN(AERTEXT);
END;
Importance of increasing this to more than 4000 is to pull complete text data. If the DB column contains more than 4K character it doesn’t work.
I'm calling it with:
select AER_ID,GET_AER_TEXT5(AER_ID,at,field_id,'001')
from AER a,AER_TEXT AT
where AT.field_ID=12345 and a.aer_id=at.aer_id;
Can you please advise how to get rid of this issue.
Prior to Oracle 12c Oracle only allows 4000 bytes in a varchar2 value in an SQL context. You are allowed 32k in PL/SQL, so your function is sort of OK as it stands, even with the substrng getting the first 4001 characters; but only if you call it from PL/SQL. When you try to call it from SQL:
select AER_ID,GET_AER_TEXT5(AER_ID,at,field_id,'001') ...
... you're trying to assign a 4001-character value to the implicit SQL column in the return statement, and that is causing the error you are seeing.
You can either change your SAP call to use a PL/SQL context and a bind variable to get the return value, though you'll still be limited to 32k; or change your function to keep value as a CLOB, which makes the function a bit pointless as you can just get the value from the table. I'm not familiar with SAP so I'm not quite sure how you'd end up coding either approach.

SELECT as much data from CLOB to VARCHAR2 as possible, with multibyte chars in the data

Multi-byte characters had caused me a lot of pain.
Any suggestion for this problem?
I have a CLOB field that might contains some multi-byte characters, and I need to select in SQL and convert this field into a string for downstream process, currently I am using:
SELECT DBMS_LOB.SUBSTR( description, 4000, 1 ) FROM table
But the 4000 in above command is in length of characters, rather than bytes. So I had to change to 3000 to handle any multi-byte characters that might have crept into the data else buffer size error will occur.
The problem is for records that do not contain multibyte character, it might unnecessarily truncated more data than it need to.
(The 4000 is the string limitation, we can/had to live with that.)
Is there a way to do something in equivalent of:
SELECT DBMS_LOB.SUBSTR( description, 4000bytes, 1 ) FROM table
That way I can get as much data out as possible.
Note: I am not allowed to create temp tables/views, not using PL/SQL, only SQL SELECT...
Jeffrey's thinking process is ok, but alchn is also right. Just ran into this same problem and here is my solution. You'll have to be able to create a function though:
Create Or Replace Function clob_substr(p_clob In Clob
,p_offset In Pls_Integer
,p_length In Pls_Integer) Return Varchar2 Is
Begin
Return substrb(dbms_lob.substr(p_clob
,p_length
,p_offset)
,1
,p_length);
End;
/
Here is a demo of it's use:
Select c
,clob_substr(c
,1
,4000)
From (
Select xmlelement("t", rpad('é', 4000, 'é'), rpad('é', 4000, 'é')).extract('//text()').getclobval() c
From dual
);
Maybe truncate the resulting varchar2 with SUBSTR:
SELECT SUBSTRB( DBMS_LOB.SUBSTR( description, 4000, 1 ), 1, 4000) FROM table

How to query a CLOB column in Oracle

I'm trying to run a query that has a few columns that are a CLOB datatype. If i run the query like normal, all of those fields just have (CLOB) as the value.
I tried using DBMS_LOB.substr(column) and i get the error
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
How can i query the CLOB column?
This works
select DBMS_LOB.substr(myColumn, 3000) from myTable
When getting the substring of a CLOB column and using a query tool that has size/buffer restrictions sometimes you would need to set the BUFFER to a larger size. For example while using SQL Plus use the SET BUFFER 10000 to set it to 10000 as the default is 4000.
Running the DBMS_LOB.substr command you can also specify the amount of characters you want to return and the offset from which. So using DBMS_LOB.substr(column, 3000) might restrict it to a small enough amount for the buffer.
See oracle documentation for more info on the substr command
DBMS_LOB.SUBSTR (
lob_loc IN CLOB CHARACTER SET ANY_CS,
amount IN INTEGER := 32767,
offset IN INTEGER := 1)
RETURN VARCHAR2 CHARACTER SET lob_loc%CHARSET;
I did run into another condition with HugeClob in my Oracle database. The dbms_lob.substr only allowed a value of 4000 in the function, ex:
dbms_lob.substr(column,4000,1)
so for my HughClob which was larger, I had to use two calls in select:
select dbms_lob.substr(column,4000,1) part1,
dbms_lob.substr(column,4000,4001) part2 from .....
I was calling from a Java app so I simply concatenated part1 and part2 and sent as a email.
If it's a CLOB why can't we to_char the column and then search normally ?
Create a table
CREATE TABLE MY_TABLE(Id integer PRIMARY KEY, Name varchar2(20), message clob);
Create few records in this table
INSERT INTO MY_TABLE VALUES(1,'Tom','Hi This is Row one');
INSERT INTO MY_TABLE VALUES(2,'Lucy', 'Hi This is Row two');
INSERT INTO MY_TABLE VALUES(3,'Frank', 'Hi This is Row three');
INSERT INTO MY_TABLE VALUES(4,'Jane', 'Hi This is Row four');
INSERT INTO MY_TABLE VALUES(5,'Robert', 'Hi This is Row five');
COMMIT;
Search in the clob column
SELECT * FROM MY_TABLE where to_char(message) like '%e%';
Results
ID NAME MESSAGE
===============================
1 Tom Hi This is Row one
3 Frank Hi This is Row three
5 Robert Hi This is Row five
For big CLOB selects also can be used:
SELECT dbms_lob.substr( column_name, dbms_lob.getlength(column_name), 1) FROM foo
Another option is to create a function and call that function everytime you need to select clob column.
create or replace function clob_to_char_func
(clob_column in CLOB,
for_how_many_bytes in NUMBER,
from_which_byte in NUMBER)
return VARCHAR2
is
begin
Return substrb(dbms_lob.substr(clob_column
,for_how_many_bytes
,from_which_byte)
,1
,for_how_many_bytes);
end;
and call that function as;
SELECT tocharvalue, clob_to_char_func(tocharvalue, 1, 9999)
FROM (SELECT clob_column AS tocharvalue FROM table_name);
To add to the answer.
declare
v_result clob;
begin
---- some operation on v_result
dbms_lob.substr( v_result, 4000 ,length(v_result) - 3999 );
end;
/
In dbms_lob.substr
first parameter is clob which you want to extract .
Second parameter is how much length of clob you want to extract.
Third parameter is from which word you want to extract .
In above example i know my clob size is more than 50000 , so i want last 4000 character .
If you are using SQL*Plus try the following...
set long 8000
select ...