One have to use Pl/sql
G.Singh, April 11, 2002 - 1:12 pm UTC
As mentioned by Tom A little codeing of pl/sql will slove everything. Just make a Procedure to do such kind of thing. Pass it the apporprate value so that it can transfer From DB1 to DB2 Usinglinks . This way Java won't come in between.
Insert CLOB in a table in remote database
Duraiswamy Padmanaban, April 11, 2002 - 3:00 pm UTC
This is quite helpful hint to update the CLOB. We had to do record by record because the remote table has primary key generated by a sequence.
Though I would love to use the following sql, in this case I cannot use
insert into remote_table select * from localtable
as I have not heard that Oracle has any way to generate unique id on the fly.
If there is anyway that can be solved then it would be great.
Anyway, thanks Tom it was really a useful hint to do an update after insert of rest of field. I will try it out.
April 11, 2002 - 7:14 pm UTC
*triggers*
*calling PLSQL from SQL*
*insert into table select my_seq.nextval, ..... *
there are many ways...
kevin, June 22, 2006 - 9:34 am UTC
kevin, June 22, 2006 - 9:36 am UTC
Hi Tom,
I tried to run procedure in local database, and procedure in local database had an insert sql statement, to insert data to table "A" in remote database which has table structure: (id NUMBER, test_clob CLOB). After exec the procedure in local database, it give me an error like:
ORA-22992: cannot use LOB locators selected from remote tables
My procedure in local database is look like:
Create or Replace procedure run_clob(p_id in number, p_file_name in varchar2)
AS
l_clob clob;
l_bfile bfile;
begin
insert into clob_table@dlog_link (id, test_clob ) values
(p_id, empty_clob() )
returning the_clob into l_clob;
l_bfile := BFILENAME ('TEMP_DIR', p_file_name);
DBMS_LOB.FILEOPEN(l_bfile);
DBMS_LOB.LOADFROMFILE(l_clob, l_bfile,
DBMS_LOB.getlength(l_bfile));
DBMS_LOB.FILECLOSE(l_bfile);
end;
/
Thank you
June 22, 2006 - 2:33 pm UTC
it is what it says - you have a lob locator that points to a REMOTE LOB.
You cannot do that to the lob locator over the dblink.
what you could do is load the clob locally, insert into over the dblink (table to table) - perhaps using a global temporary table.
kevin, June 22, 2006 - 2:41 pm UTC
Can you give me some sample code, how to do that please.
Thanks
Kevin, June 22, 2006 - 4:02 pm UTC
Tom,
First I've created procedure and run on local (database A).
Create or replace procedure test_clob (p_id in number)
AS
l_clob clob;
l_bfile bfile;
begin
insert into clob_table (id, the_clob) values
(p_id, empty_clob()) returning the the_clob into l_clob;
l_bfile := BFILENAME ('TEMP_DIR', 'logfile.txt');
DBMS_LOB.FILEOPEN(l_bfile);
DBMS_LOB.LOADFROMFILE(l_clob, l_bfile,
DBMS_LOB.getlength(l_bfile));
DBMS_LOB.FILECLOSE(l_bfile);
end;
/
Procedure created
SQL> exec test_clob(1);
PL/SQL procedure successfully completed
SQL> select * from clob_table;
ID THE_CLOB
1 testing clob column
After that, i've create a global temporary table in remote database (database B).
SQL> create global temporary table foo (id number, text clob);
Table created
SQL> insert into foo select *
SQL> from clob_table@db_link;
0 row created.
When i ran "insert into foo select * from clob_table@db_link", one row support to insert into foo table instead of 0 row. Do you know why?
Thanks
June 22, 2006 - 4:23 pm UTC
I meant to use the global temporary table the "other way around"
you
a) load into a global temporary table
b) insert into table@remote select * from gtt;
kevin, June 22, 2006 - 4:59 pm UTC
After i've followed your instruction like:
SQL> insert into foo@db_link from select * from gtt;
2 rows created.
And then i went to remote database
SQL> select * from foo;
no rows selected.
but in local database, i did
SQL> select count(*) from foo@db_link;
2 rows created.
Can you tell me why no rows return when i do "select * from foo;" in remote database.
Thanks
June 23, 2006 - 9:48 am UTC
did you commit?
Commit is the word
Michel Cadot, June 23, 2006 - 12:54 am UTC
You have to commit your insert before you can see the data in the remote database.
kevin, June 23, 2006 - 9:31 am UTC
I've follow your suggestion, but still can not see the data in remote database.
SQL> insert into foo@db_link select * from gtt;
1 row created.
SQL> commit;
Commit complete.
SQL> select count(*) from foo@db_link;
COUNT(*)
--------
0
but when i ignore the commit statement and the count value is 1:
SQL> insert into foo@db_link select * from gtt;
1 row created.
SQL> select count(*) from foo@db_link;
COUNT(*)
-------
1
But either way, still can not see the data in remote database. What is wrong with this?
Thanks Tom
June 23, 2006 - 10:24 am UTC
if you do not use a gtt, what happens.
Kevin, June 23, 2006 - 10:37 am UTC
you meant, just pick another table instead of gtt.
That happen occur on window. But when i try to test on unix box with same procedure verything is fine. I don't know why.
June 23, 2006 - 1:14 pm UTC
sounds like you might be logging into the wrong databases during your testing then.
To Kevin
Michel Cadot, June 23, 2006 - 10:42 am UTC
What is your Oracle version (4 figures, please)?
And your Windows version (with SP number)?
Michel
kevin, June 23, 2006 - 3:31 pm UTC
My oracle is 9.2.0.1.0 and window is XP Home Edition SP 2
Tom,
Your answer is very excellent and very helpful on my project.
I have another question relate to previous post.
Create or replace procedure test_clob (p_id in number)
AS
l_clob clob;
l_bfile bfile;
begin
insert into clob_table (id, the_clob) values
(p_id, empty_clob()) returning the the_clob into l_clob;
l_bfile := BFILENAME ('TEMP_DIR', 'logfile.txt');
DBMS_LOB.FILEOPEN(l_bfile);
DBMS_LOB.LOADFROMFILE(l_clob, l_bfile,
DBMS_LOB.getlength(l_bfile));
DBMS_LOB.FILECLOSE(l_bfile);
end;
/
I ran the procedure and data were inserted into the "clob_table" table and display by the following sql statement:
SQL> select id, dbms_lob.getlength(the_clob) from clob_table;
ID DBMS_LOB.GETLENGTH(THE_CLOB)
---------- ----------------------------
3 2260
4 2260
5 8333
6 44497
After that, I've created a report in HTMLDB to display the information in the "clob_table" and i've an error like:
report error:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
and I know the error popup because the length of the "id(6) column is greater than 32767 bytes. I've search around in this forum and otn website, but can not came up with any idea how to do it. Can you show me how to handle that situation please?
Thanks
June 24, 2006 - 11:16 am UTC
try out the htmldb forum on otn.oracle.com - best place to get great answers for htmldb....
kevin, June 25, 2006 - 9:04 am UTC
Tom,
but how can i write a code to break a file and append the file, which located in server if the file greater than 32767.
thank you
June 25, 2006 - 11:39 am UTC
I don't know what you mean. No context here. what "file"?
kevin, June 26, 2006 - 1:56 pm UTC
Assume, i've create a table similar like:
CREATE table clob_table (id number, file_name varchar2(40),
output clob);
I'm also have two files name "logfile.txt and logfile2.txt" that are located in TEMP_DIR directory. "logfile.txt" has size = 10234 bytes, and "logfile2.txt" has size = 44479 bytes.
I want to insert "logfile.txt and logfile2.txt" into clob_table by the following procedure below:
Create or replace procedure test_clob (p_id in number,
p_file_name in varchar2, p_output in varchar2)
AS
l_clob clob;
l_bfile bfile;
begin
insert into clob_table (id, file_name, output) values
(p_id, p_file_name, empty_clob()) returning the output into l_clob;
l_bfile := BFILENAME ('TEMP_DIR', 'p_output');
DBMS_LOB.FILEOPEN(l_bfile);
DBMS_LOB.LOADFROMFILE(l_clob, l_bfile,
DBMS_LOB.getlength(l_bfile));
DBMS_LOB.FILECLOSE(l_bfile);
end;
/
and first, i execute the procedure to insert a "logfile.txt" file into the clob_table by the following command:
SQL> exec test_clob (1,'log_file.txt', 'logfile.txt');
SQL> select id, file_name, dbms_lob.getlength(output)
from clob_table;
ID FILE_NAME DBMS_LOB.GETLENGTH(OUTPUT)
1 log_file.txt 10234
SQL> select * from clob_table;
ID FILE_NAME OUTPUT
1 log_file.txt AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
and then, i execute that procedure again to insert a "logfile2.txt" file into the "clob_table" table:
SQL> exec test_clob (2, 'log_file2.txt', 'logfile2.txt');
SQL> select id, file_name, dbms_lob.getlength(output)
from clob_table;
ID FILE_NAME DBMS_LOB.GETLENGTH(OUTPUT)
1 log_file.txt 10234
2 log_file2.txt 44479
SQL> select * from clob_table;
ORA-06502: PL/SQL: numeric or value error: character string buffer to small;
Can you explain for me why select statement is ok when i try to retrieve the information for first time, but the second time, it poput the error message above.
How can i resolve that problems?
Thank your very much
June 26, 2006 - 2:43 pm UTC
that won't happen - do you have some fine grained access control or something else at play here?
That isn't a cut and paste, the error stack is too small.
Kevin, June 27, 2006 - 8:43 am UTC
Sorry, that was my fault, I meant that query cause in HTMLDB not in sqlplus. Can I ask you one more question?
How can i break a row into multiple piece if that row has a size greater than 32767 bytes.
Thank you so much.
June 27, 2006 - 9:32 am UTC
I don't understand what you mean by a "row has a size greater than 32k" or why you would need to break it up?
need more context.
Kevin, June 27, 2006 - 10:16 am UTC
Sorry, I'm not explain very clear.
Ok, Assume I have a file that located at TEMP_DIR directory, and TEMP_DIR directory contain the file name "log_file.txt" that has a size > 32767 bytes. I've created a procedure to insert "log_file.txt" that located at TEMP_DIR directory into "clob_table" table, like the following code below.
Create or replace procedure test_clob (p_id in number,
p_file_name in varchar2)
AS
l_clob clob;
l_bfile bfile;
begin
-- Need some code here to break the "log_file.txt"
-- before insert into clob_table. Because HTMLDB
-- just limited the size of each row up to 32767 bytes
-- otherwise will popup an error
-- report error:
-- ORA-06502: PL/SQL: numeric or value error:
-- character string buffer too small
insert into clob_table (id, the_clob) values
(p_id, empty_clob())
returning the the_clob into l_clob;
l_bfile := BFILENAME ('TEMP_DIR', 'p_file_name');
DBMS_LOB.FILEOPEN(l_bfile);
DBMS_LOB.LOADFROMFILE(l_clob, l_bfile,
DBMS_LOB.getlength(l_bfile));
DBMS_LOB.FILECLOSE(l_bfile);
end;
/
and I want to make a report to display the information in "clob_table" by using HTMLD. Since HTMLDB built using mod_plsql, the maximum size of a single report row is limited to 32767 bytes. That's why, i need to break the "log_file.txt" into multiple piece before insert into the "clob_table".
Thank you.
June 27, 2006 - 10:28 am UTC
you would not break up the lob, I have pages >32k on asktom here, I would not consider chunking stuff up.
You would create a report on the scalar data, showing the first bit of the text (perhaps as a link).
When you click on the link, you branch to a page that has a region of type PL/SQL. It would be passed the primary key (in order to locate the lob again).
You would select out the lob and do something like:
offset := 1;
lob_len := dbms_lob.getlength(l_lob);
loop
htp.prn( dbms_lob.substr( l_lob, 32000, offset ) );
offset := offset+32000;
exit when offset > lob_len;
end loop;
to print out the entire text.
Kevin, June 27, 2006 - 1:09 pm UTC
Thank you so much Tom. It's work wonderful.
Kevin, June 27, 2006 - 1:36 pm UTC
Tom,
Can I user HTML within pl/sql to make the text file look more organize? If yes, Please give me an example.
Thanks
June 27, 2006 - 2:45 pm UTC
I don't know what "more organize" means - you can use HTML, style sheets - anything you want to layout the text, much like I do on this page.
kevin, June 27, 2006 - 2:57 pm UTC
Can you give me little of sample code using HTML in PL/SQL?
Thank you
June 27, 2006 - 3:04 pm UTC
we already did, htp.prn!
just output any html you want
htp.prn( 'Hello world' );
htp.prn( htf.bold( 'Hello' ) || ' world' );
achieve the same, you just mark up the text, or if you like functions, there are functions that add the markup.
Kevin, June 27, 2006 - 3:22 pm UTC
Thank you so much Tom. My project can not complete without your help.
Thank you
Loading a File Into a Remote Database
Su Baba, February 21, 2007 - 7:47 pm UTC
Is there any way to load a file into a CLOB column in a remote database using PLSQL? The local machine only has Oracle Client (SQL*Plus) installed. I understand that dbms_lob.fileopen will only work when the file is on the database server. What's the workaround?
February 22, 2007 - 8:34 am UTC
perhaps the easiest way is:
a) create a scratch table locally
b) load lob using dbms_lob load from file locally
c) insert into remote select * from local to move it
Su Baba, February 22, 2007 - 11:40 am UTC
However, there is no local database. The local machine only has Oracle client installed. Given the case, is it possible to load the file using only PL/SQL?
February 22, 2007 - 11:56 am UTC
ahh, got it
you'll have to write a program or use sqlldr to load the file.
CLOB from procedure across db links work
Melissa, June 24, 2009 - 10:21 am UTC
OK so i've gathered from this that a CLOB can be copied using a procedure across a database link. I'm trying to bring the CLOB across the database link based on a trigger. I have it set up so that the trigger copies the CLOB from one database to another (via dblink). It seems to only work when the clob is under 4000 characters. Is this possible? My lead dba is saying its not possible to copy clobs over a db link in a trigger.
I was thinking of piecing it over 4000 characters at a time but that is very undesireable.
Heres my code:
SELECT count(*)
INTO intExists
FROM emaar_active.xxx@usar b
WHERE b.proj_no = :NEW.ts_proj_num;
IF intExists > 0 THEN
--UPDATE mash_admin.usr_re
-- SET ts_dd_1391 = empty_clob(),
-- ts_new_acquisition = empty_clob()
-- WHERE ts_id = :NEW.ts_id;
INSERT INTO stgng_area.usr_clob_temp_table
(dd_1391, ts_new_acquisition, ts_proj_num, ts_id)
SELECT b.justf_memo, b.proj_memo, b.proj_no, :NEW.ts_id
FROM emaar_active.xxx@usar b
WHERE b.proj_no = :NEW.ts_proj_num;
SELECT ts_new_acquisition
INTO :NEW.ts_new_acquisition
FROM stgng_area.usr_clob_temp_table
WHERE ts_proj_num = :NEW.ts_proj_num
AND ts_id = :NEW.ts_id;
DELETE FROM stgng_area.usr_clob_temp_table
WHERE ts_proj_num = :NEW.ts_proj_num
AND ts_id = :OLD.ts_id;
This is just a portion of my trigger. Also i'm pulling two clobs over and i've only seen this issue on one of the CLOBS i'm pulling over. The other seems to always come over fine. Is it possible that a column in my new instance could be corrupted?
Thanks in advance!!!!
June 26, 2009 - 9:51 am UTC
... My lead dba is saying its not possible
to copy clobs over a db link in a trigger.
....
correct, because most clobs are not done via a simple insert/update - they are modified piecewise - not via DML.
If you truly truly think (I emphasize 'think' - I think otherwise) that you need to replicate this data - use replication. If you do real time synchronous replication (as you are attempting) it becomes painfully obvious to everyone everywhere that you really meant to have A SINGLE DATABASE.
You cannot accomplish this via a trigger in real time, the data is not there.
Typically a lob is created via
insert into t (...., lob_column) values ( ...., empty_clob() ) returning lob_column into :host_variable;
stream data into :host_variable;
the trigger fires on insert, not on the streaming of data into the clob variable. the data just isn't there in the trigger at all in most cases.