Question

So want to get Id's of documents which are bigger than 60 mb:

SELECT

DOCS.ID

FROM DOCS

where LENGTH(DOCS.DOCUMENT) > (60*1024*1024) 

and I get this error : SQL Error: ORA-00932: inconsistent datatypes: expected NUMBER got LONG BINARY 00932. 00000 - "inconsistent datatypes: expected %s got %s" document is savad as a long raw ... probably should cast somehow to long???

The only solution I came up with was To alter table from long raw to BLOB, then for some divine reason you have to recreate ALL indexes for that table... it's the only way.

Was it helpful?

Solution

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

OTHER TIPS

SELECT DOCS.ID
FROM DOCS
WHERE dbms_lob.getlength(DOCS.DOCUMENT) > (60*1024*1024) 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top