How to query a CLOB column in Oracle - sql

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

Related

ORACLE inserts with CLOB column (more than 4000 characters)

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.

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'

Can't save comma separated number string in varchar2()

I've got a list of items I want to add in a single click, for this purpose I created a table with a column with a type varchar2(4000), in this column I want to list id's that refer to the other table so I can paste the value of this column as a parameter. ex. select t.* from table_name t where t.point_id in (varchar2 string of comma seprated point_ids).
The problem I've got is that when I put more than 1 id in the varchar2 field I get ORA-06502: PL/SQL: numeric or value error: character to number conversion error
How can I avoid this error? My field is varchar2, not number and I don't want it to be converted. I need the value I'm parsing to be saved. ex. (11, 12)
Picture of my Table:
EDIT: Note - My select is working okay, the problem I'm having is with saving the information.
My Insert :
procedure lab_water_pointsgroup (v_group_id lab_water_pointsgroups.group_name%type,
v_group_name lab_water_pointsgroups.group_code%type,
v_group_code lab_water_pointsgroups.lab_points_ids%type,
v_lab_points_ids lab_water_pointsgroups.group_id%type) as
begin
update lab_water_pointsgroups
set group_name = v_group_name,
group_code = v_group_code,
lab_points_ids = v_lab_points_ids
where group_id = v_group_id;
if ( SQL%RowCount = 0 ) then
insert into lab_water_pointsgroups
(group_id, group_name, group_code, lab_points_ids)
values
(v_group_id, v_group_name, v_group_code, v_lab_points_ids);
end if;
end;
Not sure how exactly I can help you here as you gave no example. Have a look at the below demo, maybe the contruct with xmltable solves your problem. HTH KR
create table testtab (id number);
insert into testtab values (1);
select * from testtab where id in ('1'); -- works
select * from testtab where id in (1); -- works
select * from testtab where id in (1,2); -- works
select * from testtab where id in ('1,2'); -- ORA-01722: invalid number
select * from testtab where id in (select to_number(xt.column_value) from xmltable('1,2') xt); -- works
Here is how you defined parameters for your procedure:
v_group_id lab_water_pointsgroups.group_name%type,
v_group_name lab_water_pointsgroups.group_code%type,
v_group_code lab_water_pointsgroups.lab_points_ids%type,
v_lab_points_ids lab_water_pointsgroups.group_id%type
I suspect that you made mistake with types, because id has name type, name has code type etc. So it should be:
v_group_id lab_water_pointsgroups.group_id%type,
v_group_name lab_water_pointsgroups.group_name%type,
v_group_code lab_water_pointsgroups.group_code%type,
v_lab_points_ids lab_water_pointsgroups.lab_points_ids%type
And I suggest to use merge instead of this update / insert, but it's not what you asked for :)
Your error is in that you don't make difference between variable containing comma separated numbers and actual enumeration in the 'in' operator. After your code analize and preparation to execution your statement will be like .. id in ('1,2,3') instead of ..id in (1,2,3), did you notice differnce ? So you need to transform comma separated values into array or in this case into collection. Your code should be like this:
select t.*
from table_name t
where t.point_id in
(select regexp_substr(YOUR_VARCHAR2_COLUMN_VALUE, '[^,]+', 1, level)
from dual
connect by regexp_substr(YOUR_VARCHAR2_COLUMN_VALUE, '[^,]+', 1, level) is not null)

Why isn't Oracle converting characters to numbers?

Oracle throws ORA-01722: invalid number in my SQL query and it is unclear why.
I have a table called "LIGHTS" and I want to get the lights with a WATTAGE <= 3. WATTAGE is stored as a VARCHAR2(40) for some reason, but each character does seem to be an integer or float. When I convert WATTAGE to a number using the query:
SELECT TO_NUMBER(WATTAGE) FROM LIGHTS
There's no problem. I get a result like this:
TO_NUMBER(WATTAGE)
1
7
-1
0
15
17.5
However, when I add a WHERE condition to filter the numbers for those less than 3, I get the ORA-01722: invalid number error:
SELECT WATTAGE FROM LIGHTS
WHERE TO_NUMBER(WATTAGE) <= 3
What could be going wrong?
ORA-01722: invalid number comes from the TO_NUMBER(), not from the conditional. I.e., try this and you'll get the same error:
SELECT TO_NUMBER('test') FROM dual;
This would indicate that at least one of your values is not numeric.
Alas Oracle doesn't have a simple way to check whether a string is in fact representing a number. (One of the many reasons to use the correct data type in the first place!)
However, you can write your own. Here is just a brief demo of this concept. I create a table with a column of VARCHAR2 data type, and populate it with a few strings, one of which is not a number.
create table tbl (nbr varchar2(100));
insert into tbl
select '103' from dual union all
select '-1.3' from dual union all
select 'abc' from dual
;
Then I create a small function with a nested block that should error out if TO_NUMBER fails. The error handler will "do something" specific to errors and then return control to the main function. Then I can use this in a WHERE clause. Here are the function and then how it can be used to find the offending values:
create or replace function not_a_number(str varchar2)
return varchar2
as
x number;
r varchar2(100);
begin
begin
x := to_number(str);
exception
when others then
r := str;
end;
return r;
end;
/
select nbr
from tbl
where not_a_number(nbr) is not null;
NBR
-------
abc

SQL truncate clob field

In Oracle I have a query similar to:
CREATE TABLE my_table
(
my_field CLOB,
my_field2 VARCHAR2(50 CHAR),
my_field3 VARCHAR2(5 CHAR),
)
and I would like to run this query:
select count(*)
from my_table
where my_field = substr('...',4000,1)
When I run the query, I get an error:
00000 - "string literal too long"
*Cause: The string literal is longer than 4000 characters.
*Action: Use a string literal of at most 4000 characters.
Longer values may only be entered using bind variables.
Please advice!
As the error message says, Oracle is rolling over because you are trying to use a string literal with more than 4000 bytes in it. One alternative is to use bind variables (as suggested):
VARIABLE my_field CLOB;
EXEC :my_field := 'some really long text here longer than 4000 bytes';
SELECT COUNT(*)
FROM my_table
WHERE my_field = :my_field;
You are using substr with 4000 character it may be possible that your character set is a multibyte character set due to which memory is more than 4k bytes.
One more approach I can suggest is to use plsql varchar2 variable. It has a limit of 32767.
Declare
my_field varchar2(32767) := <Long text>;
v_count number;
begin
SELECT COUNT(*) into v_count FROM my_table
WHERE my_field = my_field;
end;
/