SQL truncate clob field - sql

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;
/

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'

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

warning : function created with compilation error

Table EMP has ENAME as attribute.The following function gives error:
SET SERVEROUTPUT ON
SET ECHO ON
CREATE OR REPLACE FUNCTION count_emp(e_name varchar(20))
RETURN integer IS
total integer;
BEGIN
SELECT count(*) into total
FROM DEPARTMENTS
where ENAME = e_name;
RETURN total;
END;
/
warning:function created with compilation error.
You can run show errors; to see what compilation errors are.
The parameter's datatype should be specified without length. Also, use varchar2 instead of varchar.
From Oracle site:
The VARCHAR datatype is synonymous with the VARCHAR2 datatype. To avoid possible changes in behavior, always use the VARCHAR2 datatype to store variable-length character strings.
Try this:
CREATE OR REPLACE FUNCTION count_emp(e_name varchar2) -- here
RETURN integer IS
total integer;
BEGIN
SELECT count(*) into total
FROM DEPARTMENTS
where ENAME = e_name;
RETURN total;
END;
/
If you care about table EMP, you should use it in the function.
I would write this as:
CREATE OR REPLACE FUNCTION count_emp (
in_e_name varchar2
)
RETURN integer IS
v_total integer;
BEGIN
SELECT COUNT(*) into v_total
FROM EMP e
WHERE e.ENAME = in_e_name;
RETURN v_total;
END;
Notes:
Oracle will compile functions and stored procedures even when the objects don't (yet) exist. This is considered a "feature".
Use naming conventions to distinguish parameters and variables from columns. This is using in_ for the input parameters and v_ for the local variables.
Qualify all column name references. This further reduces the possibility of collision between a variable and column name.
You don't need a length for varchar2() inputs (which is preferable to varchar(), although perhaps one day, Oracle will cave to the standard).

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