Home » SQL & PL/SQL » SQL & PL/SQL » Selecting from a LOB column
Selecting from a LOB column [message #18239] Tue, 15 February 2005 10:16 Go to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Can anybody PLEASE tell me how to select from an Oracle 9.2 LOB column in a VB app using ADO? I'm desperate!

Thanks in advance.
Re: Selecting from a LOB column [message #18240 is a reply to message #18239] Tue, 15 February 2005 10:43 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
Mike, do you get the error you mentioned earlier on every row, or maybe just on rows where the length of the CLOB exceeds 32K?
Re: Selecting from a LOB column [message #18242 is a reply to message #18240] Tue, 15 February 2005 13:06 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Todd,

I get the error on all rows, no matter the size. This is the select statement that produces the error:

cmmLog.CommandText = "SELECT dbms_lob.subst(task_memo) FROM taskmemo WHERE proj_id = ? " & "AND task_id = ? AND memo_type_id = ?"

I tried the query another way, without using a command object, and I get different results:

rsMemo.Open "SELECT dbms_lob.substr(task_memo) FROM taskmemo WHERE proj_id = " & projid & " AND task_id = " & taskid & " AND memo_type_id = " & MemoID, conn, adOpenStatic, adLockOptimistic

With this query, there are no errors returned but there are also no results returned. In other words, it is saying it didn't find a row to match what was being asked for, when there is.

I tried the query using dbms_lob.read(task_memo) instead of dbms_lob.substr(task_memo), and I get an error: "ORA-00904: DBMS_LOB.READ: invalid identifier", meaning the column could not be found. The column DOES exist.

What I am trying to do is select the data in this field, and append to it if there is existing data. If there is no existing data, a row is inserted.

This is very basic SQL stuff, it seems ridiculous that it's so complicated with LOBs.

I've tried using the Microsoft ODBC for Oracle driver and the Oracle ODBC driver, v9.2. I get pretty much the same results with each one.

ANY help is most appreciated.

Thanks,

Mike
Re: Selecting from a LOB column [message #18244 is a reply to message #18240] Tue, 15 February 2005 13:51 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Todd,

I take that back about "any size." If, using the ADO command object select statement I change the statement to read "dbms_lob.substr(task_memo, 2000, 1)" then I get an error saying the item cannot be found, in other words, it can't find the column. If I go above 2000 the "raw variable length too long" error gets returned.

Thanks,

Mike
Re: Selecting from a LOB column [message #18245 is a reply to message #18244] Tue, 15 February 2005 14:56 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
Mike, sorry, but I am not an ADO guy. I have no idea why putting in the 2000 would cause that "item cannot be found" error.

Can any of you using ADO help out here?
Re: Selecting from a LOB column [message #18290 is a reply to message #18244] Wed, 16 February 2005 12:25 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
In order to determine whether the problem is on the Oracle side or the ADO side, can you test the following code from SQL*Plus and see what you get?

SELECT dbms_lob.substr (task_memo)
FROM taskmemo
WHERE proj_id = &projid
AND task_id = &taskid
AND memo_type_id = &MemoID
/
Re: Selecting from a LOB column [message #18291 is a reply to message #18290] Wed, 16 February 2005 12:34 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Barbara,

Thanks very much for taking the time. I ran the query in SQL*Plus, and the output is below:

Connected to:
Oracle9i Release 9.2.0.1.0 - Production
JServer Release 9.2.0.1.0 - Production

SQL> select dbms_lob.substr(task_memo)
2 from taskmemo
3 where proj_id = 482
4 and task_id = 33596
5 and memo_type_id = 30;

DBMS_LOB.SUBSTR(TASK_MEMO)
--------------------------------------------------------------------------------
3C48544D4C3E3C484541443E3C2F484541443E3C424F4459206267436F6C6F723D23666666666666
3E0D0A3C503E544553543C2F503E3C2F424F44593E3C2F48544D4C3E00

The value in that column is simply 'TEST', but what I get returned looks like Hex. Also, if I run the query in my VB app without the "dbms_lob.substr", I do not get an error, but the record returned is just a line of question marks.

Thanks again,

Mike
Re: Selecting from a LOB column [message #18294 is a reply to message #18291] Wed, 16 February 2005 14:14 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
What is the datatype of the task_memo column? Is it clob or blob? If it is clob, it should return a varchar2 datatype of 'TEST'. If it is blob then it should return a raw datatype.
Re: Selecting from a LOB column [message #18295 is a reply to message #18294] Wed, 16 February 2005 14:19 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Barbara,

The data type is BLOB. Is that why in SQL*Plus the return value looks like HEX and in my VB app the return value is a string of question marks?

If it is RAW, would you know how I would convert that to where it reads "TEST"?

Thanks again,

Mike
Re: Selecting from a LOB column [message #18296 is a reply to message #18295] Wed, 16 February 2005 14:49 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
That would explain the results that you are getting. Can you use a clob column instead? If not, can you show how the value 'TEST' is inserted?
Re: Selecting from a LOB column [message #18297 is a reply to message #18295] Wed, 16 February 2005 14:56 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Try this and see what you get:

SELECT utl_raw.cast_to_varchar2 (dbms_lob.substr (task_memo))
FROM taskmemo
WHERE proj_id = 482
AND task_id = 33596
AND memo_type_id = 30;
Re: Selecting from a LOB column [message #18298 is a reply to message #18296] Wed, 16 February 2005 15:01 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Barbara,

Unfortunately, no I can't change the data type on the column. My VB app is an "add-on" to another application that determines the DB schema. I have no control over the schema so I have to work with what is there.

In the other application, data is entered into those fields via the user interface. I don't have access to their code.

In my application, when I need to insert a row, it works just fine with this (as long as the data isn't too long):

Set cmmLog = New ADODB.Command
cmmLog.ActiveConnection = conn
cmmLog.CommandType = adCmdText
cmmLog.CommandTimeout = 600
cmmLog.Prepared = True
If rdbs = "SQL" Then
cmmLog.CommandText = "INSERT INTO privuser.taskmemo (memo_id, task_id, memo_type_id, proj_id, task_memo) "VALUES (?, ?, ?, ?, ?)"
Else
cmmLog.CommandText = "INSERT INTO taskmemo (memo_id, task_id, memo_type_id, proj_id, task_memo) VALUES (?, ?, ?, ?, ?)"
End If
Set prmLog2 = cmmLog.CreateParameter("keynum", adInteger, adParamInput, 10, keynum)
cmmLog.Parameters.Append prmLog2
Set prmLog3 = cmmLog.CreateParameter("taskid", adInteger, adParamInput, 10, taskid)
cmmLog.Parameters.Append prmLog3
Set prmLog4 = cmmLog.CreateParameter("memoid", adInteger, adParamInput, 10, MemoID)
cmmLog.Parameters.Append prmLog4
Set prmLog5 = cmmLog.CreateParameter("projid", adInteger, adParamInput, 10, projid)
cmmLog.Parameters.Append prmLog5
Set prmLog6 = cmmLog.CreateParameter("memo", adVarChar, adParamInput, 8192, dtlallH)
cmmLog.Parameters.Append prmLog6
cmmLog.Execute
Set cmmLog = Nothing

This works fine, with the variable "dtlallH" containing the data to be inserted.

I put the "TEST" in there through the other application interface.

The only reason I'm doing a select is to see if a record is returned. If one is, then I append moretext to the record, then update to the database. If no record is returned, I insert to the database. If there is a way to do an update without having to so a select, that would be fine.

Thanks again,

Mike
Re: Selecting from a LOB column [message #18299 is a reply to message #18297] Wed, 16 February 2005 15:23 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Barbara,

With that I get an error returned:

"Item cannot be found in the collection corresponding to the requested name or ordinal"

AAAARRRRGGGGHHHH!!!!

There has to be a way to get this done!

Thanks again,

Mike
Re: Selecting from a LOB column [message #18301 is a reply to message #18298] Wed, 16 February 2005 16:48 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Please see if you can use anything from the following demonstration or if it gives you some ideas.

-- version:
scott@ORA92> SELECT banner FROM v$version
  2  /

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
PL/SQL Release 9.2.0.1.0 - Production
CORE	9.2.0.1.0	Production
TNS for 32-bit Windows: Version 9.2.0.1.0 - Production
NLSRTL Version 9.2.0.1.0 - Production


-- table for testing:
scott@ORA92> CREATE TABLE taskmemo
  2    (task_memo    BLOB,
  3  	proj_id      NUMBER,
  4  	task_id      NUMBER,
  5  	memo_type_id NUMBER)
  6  /

Table created.


-- procedure to check if data exists and insert or update data:
scott@ORA92> CREATE OR REPLACE PROCEDURE insert_or_update_task_memo
  2    (p_task_memo_raw IN RAW,
  3  	p_proj_id	IN taskmemo.proj_id%TYPE,
  4  	p_task_id	IN taskmemo.task_id%TYPE,
  5  	p_memo_type_id	IN taskmemo.memo_type_id%TYPE)
  6  IS
  7    v_task_memo_blob    BLOB;
  8  BEGIN
  9    SELECT task_memo
 10    INTO   v_task_memo_blob
 11    FROM   taskmemo
 12    WHERE  proj_id = p_proj_id
 13    AND    task_id = p_task_id
 14    AND    memo_type_id = p_memo_type_id;
 15    --
 16    DBMS_LOB.WRITEAPPEND
 17  	 (v_task_memo_blob, UTL_RAW.LENGTH (p_task_memo_raw), p_task_memo_raw);
 18  EXCEPTION
 19    WHEN NO_DATA_FOUND THEN
 20  	 INSERT INTO taskmemo (task_memo, proj_id, task_id, memo_type_id)
 21  	 VALUES (EMPTY_BLOB(), p_proj_id, p_task_id, p_memo_type_id)
 22  	 RETURNING task_memo INTO v_task_memo_blob;
 23  	 DBMS_LOB.WRITEAPPEND
 24  	   (v_task_memo_blob, UTL_RAW.LENGTH (p_task_memo_raw), p_task_memo_raw);
 25  END;
 26  /

Procedure created.

scott@ORA92> SHOW ERRORS
No errors.


-- procedure to read data:
scott@ORA92> CREATE OR REPLACE PROCEDURE read_task_memo
  2    (p_proj_id      IN taskmemo.proj_id%TYPE,
  3  	p_task_id      IN taskmemo.task_id%TYPE,
  4  	p_memo_type_id IN taskmemo.memo_type_id%TYPE)
  5  IS
  6    v_task_memo_blob   BLOB;
  7  BEGIN
  8    SELECT task_memo
  9    INTO   v_task_memo_blob
 10    FROM   taskmemo
 11    WHERE  proj_id = p_proj_id
 12    AND    task_id = p_task_id
 13    AND    memo_type_id = p_memo_type_id;
 14    --
 15    DBMS_OUTPUT.PUT_LINE
 16  	 (UTL_RAW.CAST_TO_VARCHAR2 (DBMS_LOB.SUBSTR (v_task_memo_blob, 200, 1)));
 17  END;
 18  /

Procedure created.

scott@ORA92> SHOW ERRORS
No errors.


-- execution of insert:
scott@ORA92> EXEC insert_or_update_task_memo (UTL_RAW.CAST_TO_RAW ('TESTING INSERT'), 482, 33596, 30)

PL/SQL procedure successfully completed.


-- execution of read after insert:
scott@ORA92> SET SERVEROUTPUT ON
scott@ORA92> EXEC read_task_memo (482, 33596, 30)
TESTING INSERT

PL/SQL procedure successfully completed.


-- execution of update:
scott@ORA92> EXEC insert_or_update_task_memo (UTL_RAW.CAST_TO_RAW (' AND TESTING UPDATE'), 482, 33596, 30)

PL/SQL procedure successfully completed.


-- execution of read after update:
scott@ORA92> SET SERVEROUTPUT ON
scott@ORA92> EXEC read_task_memo (482, 33596, 30)
TESTING INSERT AND TESTING UPDATE

PL/SQL procedure successfully completed.
Re: Selecting from a LOB column [message #18328 is a reply to message #18301] Thu, 17 February 2005 08:55 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Barbara,

WOW! How nice of you to go to that extent! I tried your suggestions and here's the results:

First I tried the "insert_or_update" procedure with the existing TASKMEMO table and I received this error:

ERROR at line 1:
ORA-22920: row containing the LOB value is not locked
ORA-06512: at "SYS.DBMS_LOB", line 782
ORA-06512: at "INSERT_OR_UPDATE_TASK_MEMO", line 14
ORA-06512: at line 1

Then I created a test table, TASKMEMO1, and modified the procedure for that table. Then I ran the procedure and it worked great. I ran the "read" procedure and it ran great. Then I ran the "update" procedure again, but this time I got the same error as listed above.

Is this some sort of database setting, or does the procedure need to be modified somehow? This database is an enterprise database so it is getting hit concurrently.

Thanks again for all of your time and trouble,

Mike
Re: Selecting from a LOB column [message #18329 is a reply to message #18328] Thu, 17 February 2005 10:15 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Try adding FOR UPDATE and COMMITs as indicated below.

CREATE OR REPLACE PROCEDURE insert_or_update_task_memo
  (p_task_memo_raw IN RAW,
   p_proj_id       IN taskmemo.proj_id%TYPE,
   p_task_id       IN taskmemo.task_id%TYPE,
   p_memo_type_id  IN taskmemo.memo_type_id%TYPE)
IS
  v_task_memo_blob    BLOB;
BEGIN
  SELECT task_memo 
  INTO   v_task_memo_blob
  FROM   taskmemo
  WHERE  proj_id = p_proj_id
  AND    task_id = p_task_id
  AND    memo_type_id = p_memo_type_id
  <b>FOR    UPDATE</b>;
  --  
  DBMS_LOB.WRITEAPPEND
    (v_task_memo_blob, UTL_RAW.LENGTH (p_task_memo_raw), p_task_memo_raw);
  <b>COMMIT;</b>
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    INSERT INTO taskmemo (task_memo, proj_id, task_id, memo_type_id)
    VALUES (EMPTY_BLOB(), p_proj_id, p_task_id, p_memo_type_id)
    RETURNING task_memo INTO v_task_memo_blob;
    DBMS_LOB.WRITEAPPEND 
      (v_task_memo_blob, UTL_RAW.LENGTH (p_task_memo_raw), p_task_memo_raw);
  <b>COMMIT;</b>
END;
/
Re: Selecting from a LOB column [message #18331 is a reply to message #18329] Thu, 17 February 2005 13:57 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Barbara,

THAT DID THE TRICK! I can just call the procedures from my app and I should be up and running.

Thank you VERY MUCH for taking the time to help out a stranger. You have a been a God-send!

Take care,

Mike
Re: Selecting from a LOB column [message #108806 is a reply to message #18331] Fri, 18 February 2005 07:52 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Mike,

I was thinking about the two procedures that I provided and a couple of things started to bother me.

It would be more convenient if the conversion from varchar2 to raw were done inside the procedure to insert or update, instead of when passing the parameter, so I changed that.

The procedure to read would only display the first 200 characters. So, I changed it to display up to 1000000 characters.

Please see the demonstration of the revised code below. I truncated the lengthy output at the bottom to save space. I hope these work better for you.

Regards,
Barbara

-- procedure to check if data exists and insert or
update data:
scott@ORA92> CREATE OR REPLACE PROCEDURE insert_or_update_task_memo
  2    (p_task_memo	IN VARCHAR2,
  3  	p_proj_id	IN taskmemo.proj_id%TYPE,
  4  	p_task_id	IN taskmemo.task_id%TYPE,
  5  	p_memo_type_id	IN taskmemo.memo_type_id%TYPE)
  6  IS
  7    v_task_memo_raw	   RAW(32767) := UTL_RAW.CAST_TO_RAW (p_task_memo);
  8    v_task_memo_blob    BLOB;
  9  BEGIN
 10    SELECT task_memo
 11    INTO   v_task_memo_blob
 12    FROM   taskmemo
 13    WHERE  proj_id = p_proj_id
 14    AND    task_id = p_task_id
 15    AND    memo_type_id = p_memo_type_id
 16    FOR    UPDATE;
 17    --
 18    DBMS_LOB.WRITEAPPEND
 19  	 (v_task_memo_blob, UTL_RAW.LENGTH (v_task_memo_raw), v_task_memo_raw);
 20    COMMIT;
 21  EXCEPTION
 22    WHEN NO_DATA_FOUND THEN
 23  	 INSERT INTO taskmemo (task_memo, proj_id, task_id, memo_type_id)
 24  	 VALUES (EMPTY_BLOB(), p_proj_id, p_task_id, p_memo_type_id)
 25  	 RETURNING task_memo INTO v_task_memo_blob;
 26  	 DBMS_LOB.WRITEAPPEND
 27  	   (v_task_memo_blob, UTL_RAW.LENGTH (v_task_memo_raw), v_task_memo_raw);
 28    COMMIT;
 29  END;
 30  /

Procedure created.

scott@ORA92> SHOW ERRORS
No errors.


-- procedure to read data:
scott@ORA92> CREATE OR REPLACE PROCEDURE read_task_memo
  2    (p_proj_id      IN taskmemo.proj_id%TYPE,
  3  	p_task_id      IN taskmemo.task_id%TYPE,
  4  	p_memo_type_id IN taskmemo.memo_type_id%TYPE)
  5  IS
  6    v_task_memo_blob   BLOB;
  7  BEGIN
  8    SELECT task_memo
  9    INTO   v_task_memo_blob
 10    FROM   taskmemo
 11    WHERE  proj_id = p_proj_id
 12    AND    task_id = p_task_id
 13    AND    memo_type_id = p_memo_type_id;
 14    --
 15    DBMS_OUTPUT.ENABLE (1000000);
 16    DBMS_OUTPUT.PUT_LINE ('length of task memo: ' || DBMS_LOB.GETLENGTH (v_task_memo_blob));
 17    FOR i IN 0 .. FLOOR (DBMS_LOB.GETLENGTH (v_task_memo_blob) / 250) LOOP
 18  	 DBMS_OUTPUT.PUT_LINE
 19  	   (UTL_RAW.CAST_TO_VARCHAR2 (DBMS_LOB.SUBSTR (v_task_memo_blob, 250, i * 250 + 1)));
 20    END LOOP;
 21  END;
 22  /

Procedure created.

scott@ORA92> SHOW ERRORS
No errors.


-- execution of insert:
scott@ORA92> EXEC insert_or_update_task_memo ('TESTING INSERT', 482, 33596, 30)

PL/SQL procedure successfully completed.


-- execution of read:
scott@ORA92> SET SERVEROUTPUT ON
scott@ORA92> EXEC read_task_memo (482, 33596, 30)
length of task memo: 14
TESTING INSERT

PL/SQL procedure successfully completed.


-- execution of multiple updates to create lengthy task_memo:
scott@ORA92> BEGIN
  2    FOR i IN 1 .. 2000 LOOP
  3  	 insert_or_update_task_memo (' AND TESTING UPDATE ' || i, 482, 33596, 30);
  4    END LOOP;
  5  END;
  6  /

PL/SQL procedure successfully completed.


-- execution of read of lengthy task memo (output truncated to save space):
scott@ORA92> SET SERVEROUTPUT ON
scott@ORA92> EXEC read_task_memo (482, 33596, 30)
length of task memo: 46907
TESTING INSERT AND TESTING UPDATE 1 AND TESTING UPDATE 2 AND TESTING UPDATE 3 AND TESTING UPDATE 4
AND TESTING UPDATE 5 AND TESTING UPDATE 6 AND TESTING UPDATE 7 AND TESTING UPDATE 8 AND TESTING
UPDATE 9 AND TESTING UPDATE 10 AND TESTING UPDATE 11 
... truncated to save space
UPDATE 1996 AND TESTING UPDATE 1997 AND TESTING
UPDATE 1998 AND TESTING UPDATE 1999 AND TESTING UPDATE 2000

PL/SQL procedure successfully completed.
Re: Selecting from a LOB column [message #109081 is a reply to message #108806] Mon, 21 February 2005 16:58 Go to previous messageGo to next message
Mike Sewell
Messages: 16
Registered: April 2002
Junior Member
Barbara,

Thanks again for all of your help.

Take care,

Mike
Re: Selecting from a LOB column [message #109153 is a reply to message #18239] Tue, 22 February 2005 10:27 Go to previous messageGo to next message
Steve Corey
Messages: 336
Registered: February 2005
Location: RI
Senior Member
Barbara -

I am trying something similar to what Mike is doing. I have a procedure to insert binary files into a BLOB column in my table. This is accompanied, at this point, with only a doc_id field as the primary key. My insert procedure is as follows:

CREATE OR REPLACE PROCEDURE SC_LOAD_BLOB(p_id IN NUMBER, p_filename IN VARCHAR2) AS
  l_blob  blob;
  l_bfile bfile;
 begin
  insert into SC_LOB_DATA values (p_id, empty_blob())
  returning attBLOB into l_blob;
  l_bfile := bfilename('RIDOT_ATTACHMENTS_DIR', p_filename);
  dbms_lob.FILEOPEN(l_bfile);
  dbms_lob.loadfromfile(l_blob, l_bfile, dbms_lob.GETLENGTH(l_bfile));
  dbms_lob.FILECLOSE(l_bfile);
 end;
/


My question is, can I use the approach you used (utilizing the UTL casts) to read out binary files instead of varchar characters? I guess the real question is, can I accomplish what Mike was looking to do with binary files and without ADO? I will be using this read/write/append functionality in a custom form to be deployed in the IAS 11.5.8

My banner specs are as follows:

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production
PL/SQL Release 9.2.0.3.0 - Production
CORE    9.2.0.3.0       Production
TNS for 32-bit Windows: Version 9.2.0.3.0 - Production
NLSRTL Version 9.2.0.3.0 - Production


Thanks for your time!

Steve
Re: Selecting from a LOB column [message #109202 is a reply to message #109153] Tue, 22 February 2005 19:55 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Steve,

I don't know if it will work or not. Unfortunately, there seems to be a bug involving dbms_lob.filopen in 9.2.0.1.0 on Windows, which I am using, so I am unable to run your procedure, in order to insert data, in order to do further testing. Why don't you try it and let us know. Hopefully, I will be getting 10g in a few days and then maybe I can try it.

Here is what happens when I try to run something like your procedure. C:\oracle\clip.gif exists on the server and the dbms_lob.fileexists acknowledges that it exists. I have also tested with various other files and permissions exist such that I can access such files in that directory using the directory object with external tables and utl_file and I am able to use the other subprograms of dbms_lob, just not dbms_lob.fileopen. According to what I have read, there seems to be some problem with the Windows paths in the directory object that is used in the parameter for dbms_lob.file_open and I have not found a workaround other than upgrading. I gather that the problem was fixed in 9.2.0.3.

Barbara

scott@ORA92> CREATE TABLE sc_lob_data
  2    (doc_id	      NUMBER,
  3  	attBLOB       BLOB,
  4  	CONSTRAINT    sc_lob_data_doc_id_pk
  5  		      PRIMARY KEY (doc_id))
  6  /

Table created.

scott@ORA92> CREATE OR REPLACE DIRECTORY MY_DIR AS 'c:\oracle'
  2  /

Directory created.

scott@ORA92> CREATE OR REPLACE PROCEDURE sc_load_BLOB
  2    (p_id	   IN NUMBER,
  3  	p_filename IN VARCHAR2)
  4  AS
  5    l_BLOB	      BLOB;
  6    l_bfile	      BFILE;
  7  BEGIN
  8    INSERT INTO sc_lob_data VALUES (p_id, EMPTY_BLOB())
  9    RETURNING attBLOB into l_BLOB;
 10    l_bfile := BFILENAME ('MY_DIR', p_filename);
 11    DBMS_OUTPUT.PUT_LINE (DBMS_LOB.FILEEXISTS (l_bfile));
 12    DBMS_LOB.FILEOPEN (l_bfile);
 13    DBMS_LOB.LOADFROMFILE (l_BLOB, l_bfile, DBMS_LOB.GETLENGTH (l_bfile));
 14    DBMS_LOB.FILECLOSE (l_bfile);
 15  END sc_load_BLOB;
 16  /

Procedure created.

scott@ORA92> SHOW ERRORS
No errors.
scott@ORA92> EXECUTE sc_load_BLOB (1, 'clip.gif')
1
BEGIN sc_load_BLOB (1, 'clip.gif'); END;

*
ERROR at line 1:
ORA-22288: file or LOB operation FILEOPEN failed
ORA-06512: at "SYS.DBMS_LOB", line 504
ORA-06512: at "SCOTT.SC_LOAD_BLOB", line 12
ORA-06512: at line 1


Here is what I would have tested if I could have:

CREATE OR REPLACE PROCEDURE read_attBLOB
  (p_id       IN NUMBER)
IS
  l_BLOB         BLOB;
BEGIN
  SELECT attBLOB 
  INTO   l_BLOB
  FROM   sc_lob_data
  WHERE  doc_id = p_id;
  --  
  DBMS_OUTPUT.ENABLE (1000000);
  DBMS_OUTPUT.PUT_LINE ('length of attBLOB: ' || DBMS_LOB.GETLENGTH (l_BLOB));
  FOR i IN 0 .. FLOOR (DBMS_LOB.GETLENGTH (l_BLOB) / 250) LOOP
    DBMS_OUTPUT.PUT_LINE 
      (UTL_RAW.CAST_TO_VARCHAR2 (DBMS_LOB.SUBSTR (l_BLOB, 250, i * 250 + 1)));
  END LOOP;
END;
/
SHOW ERRORS
SET SERVEROUTPUT ON
EXECUTE read_attBLOB (1)

Re: Selecting from a LOB column [message #109279 is a reply to message #109202] Wed, 23 February 2005 08:49 Go to previous messageGo to next message
Steve Corey
Messages: 336
Registered: February 2005
Location: RI
Senior Member
Barbara -

The read_attBLOB procedure you provided ran without any errors/problems. However, in SQL+ it has a difficult time displaying the binary characters (I am testing with a 19.0KB MS Word document 9.0) Some of the text comes through, but most of it is garbage.

If I wanted to re-create the file using this procedure, can I expect problems due to the binary nature (eg, missing characters, hex characters, etc.) of the file? I realize I may be asking for too much here so if that is the case, let me know.

Basically the aim is to have the end user be able to download and then edit, save, and then re-upload the files to a custom table. As I mentioned in my last post, I will be attempting to do this via a custom form in Forms Builder and utilized in the IAS environment.

In any event, thank you for the timely answer!

Regards,
Steve
Re: Selecting from a LOB column [message #109305 is a reply to message #109279] Wed, 23 February 2005 12:30 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Without being able to test, I would only be guessing. My inclination would be to open MS Word from your form or save the MS Word document as an ASCII text file. This question might be more appropriate for the Forms forum under the Developer and Programmer section:

Developer and Programmer: Forms
Re: Selecting from a LOB column [message #109315 is a reply to message #18239] Wed, 23 February 2005 14:36 Go to previous message
Steve Corey
Messages: 336
Registered: February 2005
Location: RI
Senior Member
Barbara -

OK, thank you for the insight. I actually talked to another developer and he provided me with a iAS side package that utilizes PL/SQL to download binary files from BLOB columns. I have provided it for future reference:

In the following code, if you change the table name and the column
names, it should work. WPG_DOCLOAD is a package that is bundled with
iAS. Since Apps uses iAS, you should have this package in the SYS schema.
---------------------------------------------------------------
procedure download_document(pid in number) is
lloblocator event_document.document_file%type;
cursor lcur is
select document_file
  from event_document
 where id = pid;
begin
  open lcur;
  fetch lcur into lloblocator;
  close lcur;
  --
  wpg_docload.download_file(lloblocator); -- if its blob it can be 
directly downloaded
  --
end;

---------------------------

From forms call this using

web.show_document(http://......com/..../..../<owner>.<pkgname>.download_document?pid=32144,
'_BLANK');

Steve
Previous Topic: to see d specific data according to desire
Next Topic: anonymous block
Goto Forum:
  


Current Time: Sun Aug 31 23:16:24 CDT 2025