Skip to Main Content

Breadcrumb

May 4th

Question and Answer

Connor McDonald

Thanks for the question, Firas.

Asked: October 22, 2003 - 7:01 pm UTC

Last updated: April 19, 2018 - 1:06 am UTC

Version: 8.1.7

Viewed 10K+ times! This question is

You Asked

Hi Tom,

We are using an Oracle 8.1.7 database. Is there a way in PL/SQL or Java Stored Procedure to convert a Long Raw into a BLOB?

Thanks,
Firas Khasawneh

and Tom said...

ops$tkyte@ORA817DEV> create table gtt ( id int, x blob );

Table created.

ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> create table t ( id int primary key, x long raw );

Table created.

ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> insert into t values( 1, rpad( 'a', 2000, 'a' ) );

1 row created.

ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> declare
2 l_id number := 1;
3 l_blob blob;
4 begin
5 execute immediate '
6 insert into gtt
7 select :x, to_lob(x)
8 from t
9 where id = :x' using l_id, l_id;
10
11 select x into l_blob from gtt where id = l_id;
12 end;
13 /

PL/SQL procedure successfully completed.


if you just want to convert single row for a session. use

create table new_table as select ...., to_lob(long_raw) from old_table

to permanently convert all rows.

===========================

Addenda - in recent releases, a straight modification is possible as well

SQL> create table t ( x long raw );

Table created.

SQL> insert into t values ( utl_raw.cast_to_raw('qweqweqweqwe'));

1 row created.

SQL> alter table t modify x blob;

Table altered.

SQL> desc t
 Name                                                                    Null?    Type
 ----------------------------------------------------------------------- -------- ------
 X                                                                                BLOB

SQL> select x from t;

X
----------------------------------------------------------------------------------------
717765717765717765717765



Rating

  (13 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Excellent, Thanks

Firas, October 23, 2003 - 3:30 pm UTC

Hi Tom,

Thanks a lot for your prompt response. Is it possible to update a Long Raw column with a BLOB value? I read some where that that is possible by converting the binary bytes into hex but I am not sure if that is possible or how to do it. Any suggestions is highly appreciated.

Tom Kyte
October 23, 2003 - 7:21 pm UTC

nope, no can do there. You would have to use the API's to update the long raw (if the long raw/blob is over 32k, if 32k and less then yes, plsql can do it)

A reader, April 19, 2005 - 9:50 am UTC

Hi Tom,

I have tables x and y as

create table x
(
id number,
str varchar2(255),
lrimage long_raw
);

create table y
(
id number,
str varchar2(255),
blimage blob
);

Table x has about 11 million rows and I am trying to move data from table x to table y.

I tried the following:

create or replace procedure procblob
as
tstr varchar2(255);
timage blob;

begin
..........
select str, to_lob(lrimage) into tstr, timage
from x where id = 1;
insert into y values (1, tstr, timage);

.....
end;
/

When I try to compile this procedure I am getting the error
PL/SQL: ORA-00932: inconsistent datatypes: expected - got BINARY

I also tried

create or replace procedure procblob
as
tstr varchar2(255);
timage long raw;

begin
..........
select str, lrimage into tstr, timage
from x where id = 1;
insert into y values (1, tstr, to_lob(timage));

.....
end;
/

Again I am getting the same error. Please let me know what to do.

Thanks.



Tom Kyte
April 19, 2005 - 9:59 am UTC

use INSERT INTO select ....


do not fetch out, put into plsql only to send back.




insert into y select str, to_lob(lrimage) from x where ...;

no plsql, just sql.



A reader, April 19, 2005 - 10:12 am UTC

Thank you Tom it works great.



Does it work in 9.2.0.6 too?

Roland Rottlaender, May 02, 2006 - 7:23 am UTC

Hi Tom,

is there a difference for 9.2.0.6.?

I have a table

blobdata(
ownerid number(10),
longid number(10),
segmentid number(10),
segment LONG RAW
)

But a Query

Select longid, to_lob(segment) from blobdata where longid = 12345

returns

ORA-00932: inconsistent datatypes: expected - got BINARY



Then I create table
blobdata_temp(
ownerid NUMBER(10),
longid NUMBER(10),
segmentid NUMBER(10),
segment BLOB
)

and tried

INSERT INTO blobdata_temp SELECT ownerid, longid, segmentid, to_lob(segment) from blobdata where ...

All I got is

ORA-00997: illegal use of LONG datatype

I really has no idea what's going wrong...

Would be great if you could help me...

Thanks,

Roland

Tom Kyte
May 02, 2006 - 7:42 am UTC

to_lob only works on insert as select.


give me a cut and pasted example. something like this from my 9206 database:

ops$tkyte@ORA9IR2> create table blobdata(
  2  ownerid         number(10),
  3  longid         number(10),
  4  segmentid     number(10),
  5  segment         LONG RAW
  6  );

Table created.

ops$tkyte@ORA9IR2> insert into blobdata values ( 1, 2, 3, rpad( '00', 4000, '0' ) );

1 row created.

ops$tkyte@ORA9IR2> declare
  2          l_raw long raw;
  3  begin
  4          l_raw := rpad( '00', 32766, '0' );
  5          insert into blobdata values ( 1, 2, 3, l_raw );
  6  end;
  7  /

PL/SQL procedure successfully completed.

ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create table blobdata_temp(
  2  ownerid         NUMBER(10),
  3  longid        NUMBER(10),
  4  segmentid        NUMBER(10),
  5  segment         BLOB
  6  );

Table created.

ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> INSERT INTO blobdata_temp
  2  SELECT ownerid, longid, segmentid, to_lob(segment)
  3    from blobdata;

2 rows created.

ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> select dbms_lob.getlength( segment) from blobdata_temp;

DBMS_LOB.GETLENGTH(SEGMENT)
---------------------------
                       2000
                      16383

ops$tkyte@ORA9IR2>

 

Visi, September 04, 2008 - 10:59 am UTC

Hi Tom,
I have been visiting your site so many times, but it is only this time I am taking the chance to make a question regarding the convertion of Long Raw to BLOB.
I am in the process of loading some 40(GB)pictures from a MSSQL system to Oracle 10g R2 using OLEDB though heterogeneus system(HS).

This is my target table in oracle:

create table T_PICTURES
(
IMAGE_ID VARCHAR2(10) not null,
FILENAME VARCHAR2(250),
ACTIONNR NUMBER,
PICTURE BLOB,
BYTES VARCHAR2(10),
INFO VARCHAR2(10),
IMAGEDATE DATE
);

alter table T_PICTURES
add constraint XPK_PICTURES primary key (IMAGE_ID));


And this is the description from sqlplus of the remote table in MSSQL.

image_id varchar2(8)
filename varchar2(250) y
actionnr number(10) y
picture long raw y
bytes number(10) y
info number(10) y
imagedate date y

The following is a code I wrote and it is suposed to migrate a record at a time, any time it is being executed and converting the LONG RAW picture field to BLOB using the TO_LOB function.


begin
for c in (select t.appno
from stg_passports t, t_pictures p
where t.appno = p.image_id(+)
and p.image_id is null
and rownum <= 1 )
loop

insert into t_pictures
(image_id, filename, actionnr, picture, bytes, info, imagedate)
SELECT "ImageID" image_id,
"FileName" filename,
"ActionNr" actionnr,
to_lob("Picture") picture,
"Bytes" bytes,
"Info" info,
"ImageDate" imagedate
FROM ITCPortrait@mssql
WHERE "ImageID" = c.appno;
commit;
end loop;
--
end;

When I try to run it, I am getting ORA-00997: illegal use of LONG datatype
ORA-06512: at line 10

Am I doing something wrong here? I am realy confused. I'd really appreciate your intervention on this. I hope I was somehow clear in my explanations.

Thanks and regards,
Visi
Tom Kyte
September 04, 2008 - 1:39 pm UTC

to_lob is not implemented by mysql - it would be the thing that would have to convert the long raw into a lob.


long raws are not going to be dblink friendly at all. Your best bet will be to write an external application that selects from mysql, inserts into Oracle.

Or dump the data out into a flat file and load that.

Visi, September 05, 2008 - 7:10 am UTC

Hi Tom,
Sorry for the confusion. By MSSQL I ment Microsoft SQL Server not MYSQL.

However, I think I was able to overcome the issue by introducing a middle step in the procedure. Instead of using an INSERT...INTO clause with a TO_LOB function, I used a record type Variable as a helper.
This is the final code of the procedure:

create or replace procedure p_load_picture
as
type TPicData is record(
image_id varchar2(8),
filename varchar2(250),
actionnr number(10),
picture long raw,
bytes number(10),
info number(10),
imagedate date);
--
v_data TPicData;
--
begin
for c in (select t.appno
from stg_passports t, t_pictures p
where t.appno = p.image_id(+)
and p.image_id is null
and rownum <= 1)
loop
SELECT "ImageID" image_id,
"FileName" filename,
"ActionNr" actionnr,
"Picture" picture,
"Bytes" bytes,
"Info" info,
"ImageDate" imagedate
into v_data
FROM ITCPortrait@mssql
where "ImageID" = c.appno;
--
insert into t_pictures
(image_id, filename, actionnr, picture, bytes, info, imagedate)
values
(v_data.image_id,
v_data.filename,
v_data.actionnr,
v_data.picture,
v_data.bytes,
v_data.info,
v_data.imagedate);
--
end loop;
--
commit;
--
end;

Amazingly, Oracle is implicitly converting the LONG RAW data type to BLOB data type, so at the end we don't need to call a TO_LOB function at all.

Note: The LOOP might look unnecessary there but probably I am going to increase the number of records loaded in a single run.

Thanks again Tom

Regards,
Visi

Tom Kyte
September 05, 2008 - 9:25 am UTC

do you have any images over 32k, if so, there will be a problem there..

Visi, September 05, 2008 - 11:18 am UTC

Hi Tom,
The avarege size of a picture is about 10KB.The largest foto so far looks to be around 20KB. Probably I was lucky :)

Thanks for letting me know.

Regards,
Visi

Long raw

Anis, March 06, 2009 - 3:52 am UTC

Would you help me, I want to insert doc or pdf file into oracle database from oracle developer 6i.

Thanks
Anis
Tom Kyte
March 06, 2009 - 10:25 am UTC

http://otn.oracle.com/ -> discussion forums -> there are good ones for Developer related questions.

I haven't touched it since 1995.

TO_LOB() doubt

Badri, March 03, 2010 - 9:39 am UTC

Hi Tom,

I have a table t with a LOB column into which i tried the below query,
insert into t select to_lob(text) from user_views;

and this worked.

But when I tried to execute only
select to_lob(text) from user_views;

I got the below error
SQL Error: ORA-00932: inconsistent datatypes: expected - got LONG
00932. 00000 -  "inconsistent datatypes: expected %s got %s"

Could you please help me understand the reason for this behaviour.

Thanks in advance
Badri
Tom Kyte
March 03, 2010 - 10:57 am UTC

to_lob() is documented to only work in an insert/select or create table/select statement.

http://docs.oracle.com/docs/cd/E11882_01/server.112/e10592/functions203.htm#SQLRF06134

The lob needs to "live" somewhere, with just a select - the lob wouldn't exist in a table anywhere. The to_lob function was implemented purely to convert a long to a lob - once (as a migration device). That was the intended functionality.

raw

A reader, March 03, 2010 - 10:10 pm UTC

Can you explain to us the difference between BLOB and RAW datatype and for what kind of data you use RAW data type.
Tom Kyte
March 04, 2010 - 9:46 am UTC

RAW is limited to 2000 bytes.

blob is virtually unlimited (terabytes).

if you have data that is binary in nature (not a string - just binary bytes) that is 2000 bytes or less - use RAW (more efficient, more compact, less overhead)

if you have data that is binary in nature that exceeds 2000 bytes, you will use a blob - which can store massive amounts of data.

Ram, March 29, 2010 - 11:07 pm UTC

INSERT INTO APAC2.PS_VENDOR_CONVER (SELECT DISTINCT 'MASTR', A.VENDOR_ID,
A.CONVER_DT, A.CONVER_SEQ_NUM, A.CNTCT_SEQ_NUM, A.CONVER_TOPIC,
A.OPRID, A.REVIEW_DAYS, A.REVIEW_DATE, A.REVIEW_NEXT_DATE,
A.KEYWORD1, A.KEYWORD2, A.KEYWORD3, TO_LOB (A.DESCRLONG) FROM
APAC2.PS_C_NR_VDCNVR_TMP A)

A.DESCRLONG is a LONG field, so I am using TO_LOB

Hi Tom

I need help here wrt LONG field. In the SELECT I have to use a DISTINCT becos of functionality and I have to use the Long Field as well.
A.DESCRLONG is a LONG field.
But this is showing me an error that it is a wrong data type.
Can you help me in resolving the sql insert please

Thanks
Tom Kyte
April 05, 2010 - 10:23 am UTC

you cannot use distinct, it will simply not work - there is no "solution" using straight SQL. longs cannot be distinct'ed...

Now, if it is some set of fields that should be distincted you could:

select .... existing select list....
  from table
 where rowid in (select max(rowid) from table group by <that list of columns>);

That would work - if the descrlong is not to be in the list of distincted columns.

If it is, you will not be using SQL only to do this.

sam, February 19, 2014 - 12:06 pm UTC

Hi,
I created a one table in that i created one column with LONG RAW datatype and i want to migrate the data to another table but in that column datatype is BLOB.
I want to know is it possible or not.If yes how?

It seems this is outdated

Dinesh Gadhia, April 18, 2018 - 4:18 pm UTC

when i tried to compile, i got below.

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management,
OLAP,
Advanced Analytics and Real Application Testing options


Warning: Java created with compilation errors.

Errors for JAVA SOURCE "BlobArray":

LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 BlobArray:12: oracle.jdbc.driver.OracleResultSet is not public in
oracle.jdbc.driver; cannot be accessed from outside package

0/0 OracleResultSet rs = (OracleResultSet) blobs.getResultSet();
0/0 ^
0/0 BlobArray:12: oracle.jdbc.driver.OracleResultSet is not public in
oracle.jdbc.driver; cannot be accessed from outside package

0/0 2 errors
0/0 ^
0/0 Note: BlobArray uses or overrides a deprecated API.

LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 Note: Recompile with -Xlint:deprecation for details.
0/0 OracleResultSet rs = (OracleResultSet) blobs.getResultSet();

Warning: Java created with compilation errors.

SQL> l 12
12* conn.setAutoCommit(false);
SQL> l
1 create or replace and resolve java source named "BlobArray" as
2 import java.io.*;
3 import java.lang.*;
4 import oracle.sql.*;
5 import oracle.jdbc.driver.*;
6 import java.sql.*;
7
8 public class BlobArray {
9 public static void doWork(oracle.sql.ARRAY blobs) throws Exception {
10 DriverManager.registerDriver(new OracleDriver());
11 Connection conn = DriverManager.getConnection("jdbc:oracle:kprb:@");
12 conn.setAutoCommit(false);
13 OracleResultSet rs = (OracleResultSet) blobs.getResultSet();
14 PrintStream os = new PrintStream(System.out);
15
16 for (int i = 0; rs.next(); i++) {
17 BLOB b = rs.getBLOB(2);
18 int length = (int) b.length();
19 int bufferSize = b.getBufferSize();
20 byte[] buffer = new byte[bufferSize];
21 InputStream is = b.getBinaryStream();
22
23 while ((length = is.read (buffer,0,bufferSize)) != -1) {
24 os.write(buffer, 0, length);
25 }
26
27 os.println();
28 os.println("===========================");
29 }
30
31 os.println();
32 os.println("JAVA PART IS DONE");
33 os.flush();
34 }
35* }
SQL>

Please help
Connor McDonald
April 19, 2018 - 1:06 am UTC

Thanks for letting us know.

In 12c, there is a much much easier way.

SQL> create table t ( x long raw );

Table created.

SQL> insert into t values ( utl_raw.cast_to_raw('qweqweqweqwe'));

1 row created.

SQL> alter table t modify x blob;

Table altered.

SQL> desc t
 Name                                                                    Null?    Type
 ----------------------------------------------------------------------- -------- ------
 X                                                                                BLOB

SQL> select x from t;

X
----------------------------------------------------------------------------------------
717765717765717765717765


More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database