Indeed this is a problem, but you can use PL/SQL as a workaround:
create or replace function get_doc_length(iDocId in number) return number is
aLong long;
begin
select d.document into aLong from docs d where d.id = iDocId;
return length(aLong);
end;
/
This function (which cannot use a LONG
as parameter, unfortunately, so must be specific to table DOCS
) can then be used like this:
SELECT DOCS.ID
FROM DOCS
where get_doc_length(DOCS.ID) > (60*1024*1024)
EDIT : ok, this does not work for big LONG
s. You have to dig even more into SQL's arcanes to make this work:
create or replace function get_doc_length(iDocId in number) return number is
myQuery varchar2(200);
myCursor binary_integer;
myRes pls_integer;
myDoc clob;
long_val long;
long_len integer;
buf_len integer;
cur_pos number;
begin
myQuery := 'select d.document from docs d where d.id = ' || iDocId;
-- Create cursor, parse and bind.
myCursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(myCursor, myQuery, DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN_LONG(myCursor, 01);
myRes := DBMS_SQL.EXECUTE(myCursor);
-- Fetch row (only one normally)
if DBMS_SQL.FETCH_ROWS(myCursor) > 0 then
-- Create CLOB.
DBMS_LOB.CREATETEMPORARY(myDoc, false, DBMS_LOB.CALL);
-- Piecewise fetching of the LONG column, appending to the CLOB.
buf_len := 32760;
cur_pos := 0;
loop
DBMS_SQL.COLUMN_VALUE_LONG(myCursor, 01, buf_len, cur_pos, long_val, long_len);
exit when long_len = 0;
DBMS_LOB.APPEND(myDoc, long_val);
cur_pos := cur_pos + long_len;
end loop;
end if;
DBMS_SQL.CLOSE_CURSOR(myCursor);
return length(myDoc);
end;
/
The DBMS_SQL
package allows to convert a LONG
into a CLOB
by looping on it and appending pieces of the LONG
gradually.
If you want the binary length of the CLOB
instead of its char length (this may differ), you can use dbms_lob.getlength
instead of length
as this other SO post shows.