| Updating CLOB [message #504100] |
Thu, 21 April 2011 09:54  |
 |
amerar
Messages: 18 Registered: April 2011
|
Junior Member |
|
|
Ok, CLOB columns are such a hassle.
I have a variable in my script: v_field1 VARCHAR2(32000);
This is part of a cursor record:
v_mf_table IS TABLE OF mf_detail%ROWTYPE INDEX BY BINARY_INTEGER;
v_mf_record v_mf_table;
I use a FORALL to insert the data into a table:
FORALL x IN v_mf_record.FIRST .. v_mf_record.COUNT
INSERT INTO monthly_mf_snapshot VALUES v_mf_record(x);
BUT! v_field1 is > 4000 characters. Does this trash my changes of using FORALL? Do I need to deal with 4k chunks in an UPDATE instead?
Help Please.
|
|
|
|
| Re: Updating CLOB [message #504104 is a reply to message #504100] |
Thu, 21 April 2011 10:04   |
cookiemonster
Messages: 13975 Registered: September 2008 Location: Rainy Manchester
|
Senior Member |
|
|
|
You make absolutely no mention in your post of how you are using v_field1 in the code. Telling us that would be a necessary starting point.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Re: Updating CLOB [message #504158 is a reply to message #504122] |
Thu, 21 April 2011 13:05   |
 |
amerar
Messages: 18 Registered: April 2011
|
Junior Member |
|
|
Been playing around. This is messed up and confusing. See my table definition above, I have CLOB columns in the table. I can issue a direct insert into that table of a value = 32000K.
However, if in my PL/SQL code I have this: v_mf_record(v_rec).monthly_data := RPAD('A',32000,'A'), where v_mf_record(v_rec).monthly_data is a ROWTYPE based on the table above, I get an error.
So, why will a direct insert statement to the table work, and assigning a variable the same length value, which is based on a CLOB column, not work? I'm a bit lost there.
|
|
|
|
|
|
|
|
|
|
|
|
| Re: Updating CLOB [message #504173 is a reply to message #504168] |
Thu, 21 April 2011 14:06   |
 |
amerar
Messages: 18 Registered: April 2011
|
Junior Member |
|
|
Try this script......
CREATE TABLE data (
key1 VARCHAR2(100),
col1 VARCHAR2(100),);
CREATE TABLE test (
key1 VARCHAR2(100),
col1 VARCHAR2(100),
c1 CLOB);
DECLARE
CURSOR data_crs IS
SELECT key1, col1, NULL data_string
FROM data;
CURSOR mf_monthly (p_key VARCHAR2) IS
SELECT mr.m_fund_id ||'|'|| mr.year ||'|'|| mr.month ||'|'|| mr.total_return ||'|'||
mr.unit_value ||'|'|| mr.nav monthly_data
FROM mutual_fund mf, month_result mr, fund_master fm
WHERE mf.m_fund_id = mr.m_fund_id
AND mf.m_fund_id = fm.fund_id
AND TO_DATE(mr.year, 'YYYY') >= ADD_MONTHS(SYSDATE, -132)
AND mf.ticker = p_key
ORDER BY mr.year, mr.month;
v_data CLOB;
TYPE v_data_table IS TABLE OF data_crs%ROWTYPE INDEX BY BINARY_INTEGER;
v_data_record v_data_table;
BEGIN
OPEN data_crs;
FETCH data_crs BULK COLLECT INTO v_data_record;
CLOSE data_crs;
FOR v_rec IN v_data_record.FIRST .. v_data_record.COUNT LOOP
FOR x_rec IN mf_monthly(v_data_record(v_rec).key1) LOOP
v_data := v_data || x_rec.monthly_data || '+++';
END LOOP;
v_data := NULL;
END LOOP;
/*** Error should happen here if v_data > 32k ***/
v_data_record(v_rec) := v_data;
FORALL x IN v_data_record.FIRST .. v_data_record.COUNT
INSERT INTO test VALUES v_data_record(x);
END;
/
|
|
|
|
|
|
|
|
| Re: Updating CLOB [message #504199 is a reply to message #504178] |
Thu, 21 April 2011 23:32   |
 |
Barbara Boehmer
Messages: 9106 Registered: November 2002 Location: California, USA
|
Senior Member |
|
|
You need to make the data_string in your data_crs an empty_clob() as shown below.
SCOTT@orcl_11gR2> CREATE TABLE data
2 (key1 VARCHAR2 (100),
3 col1 VARCHAR2 (100))
4 /
Table created.
SCOTT@orcl_11gR2> CREATE TABLE test1
2 (key1 VARCHAR2(100),
3 col1 VARCHAR2(100),
4 c1 CLOB)
5 /
Table created.
SCOTT@orcl_11gR2> INSERT INTO data VALUES ('X', 'XXX')
2 /
1 row created.
SCOTT@orcl_11gR2> DECLARE
2 CURSOR data_crs
3 IS
4 SELECT key1, col1,
5 EMPTY_CLOB() AS data_string
6 FROM data;
7
8 CURSOR mf_monthly
9 IS
10 SELECT RPAD ('A', 32000, 'A') AS monthly_data
11 FROM dual;
12
13 v_data CLOB;
14
15 TYPE v_data_table IS TABLE OF data_crs%ROWTYPE INDEX BY BINARY_INTEGER;
16 v_data_record v_data_table;
17 BEGIN
18 OPEN data_crs;
19 FETCH data_crs BULK COLLECT INTO v_data_record;
20 CLOSE data_crs;
21
22 FOR v_rec IN v_data_record.FIRST .. v_data_record.COUNT LOOP
23 FOR x_rec IN mf_monthly LOOP
24 v_data := v_data || x_rec.monthly_data || '+++';
25 END LOOP;
26
27 v_data_record(v_rec).data_string := v_data;
28
29 v_data := NULL;
30 END LOOP;
31
32 FORALL x IN v_data_record.FIRST .. v_data_record.COUNT
33 INSERT INTO test1 VALUES v_data_record(x);
34 END;
35 /
PL/SQL procedure successfully completed.
SCOTT@orcl_11gR2> SELECT * FROM test1
2 /
KEY1
--------------------------------------------------------------------------------
COL1
--------------------------------------------------------------------------------
C1
--------------------------------------------------------------------------------
X
XXX
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
... -- truncated to save space
AAAAAAAAAAAAAAA
+++
1 row selected.
SCOTT@orcl_11gR2>
|
|
|
|
|
|
|
|
|
|
|
|
| Re: Updating CLOB [message #504269 is a reply to message #504267] |
Fri, 22 April 2011 19:31   |
 |
Barbara Boehmer
Messages: 9106 Registered: November 2002 Location: California, USA
|
Senior Member |
|
|
I am assuming that this is a somewhat simplified version of the actual problem and that there is a relation between the two actual cursors. Otherwise, you could just calculate the value of v_data once. I would think that the forall would be fast and that the nested for loops would be the slow part. Have you timed those parts separately? If it weren't for the size of your clobs, you could just use a simple insert into ... select ... from ... I would at least try to eliminate as many intermediary steps as possible, such as eliminating the first cursor and the v_data variable as shown below.
SCOTT@orcl_11gR2> CREATE TABLE data
2 (key1 VARCHAR2 (100),
3 col1 VARCHAR2 (100))
4 /
Table created.
SCOTT@orcl_11gR2> CREATE TABLE test1
2 (key1 VARCHAR2(100),
3 col1 VARCHAR2(100),
4 c1 CLOB)
5 /
Table created.
SCOTT@orcl_11gR2> INSERT INTO data VALUES ('X', 'XXX')
2 /
1 row created.
SCOTT@orcl_11gR2> DECLARE
2 TYPE v_data_table IS TABLE OF test1%ROWTYPE INDEX BY BINARY_INTEGER;
3 v_data_record v_data_table;
4
5 CURSOR mf_monthly
6 IS
7 SELECT RPAD ('A', 32000, 'A') AS monthly_data
8 FROM dual;
9 BEGIN
10 SELECT key1, col1,
11 EMPTY_CLOB() AS c1
12 BULK COLLECT
13 INTO v_data_record
14 FROM data;
15
16 FOR v_rec IN v_data_record.FIRST .. v_data_record.COUNT LOOP
17 FOR x_rec IN mf_monthly LOOP
18 v_data_record(v_rec).c1 :=
19 v_data_record(v_rec).c1 || x_rec.monthly_data || '+++';
20 END LOOP;
21 END LOOP;
22
23 FORALL x IN v_data_record.FIRST .. v_data_record.COUNT
24 INSERT INTO test1 VALUES v_data_record(x);
25 END;
26 /
PL/SQL procedure successfully completed.
SCOTT@orcl_11gR2> SELECT * FROM test1
2 /
KEY1
--------------------------------------------------------------------------------
COL1
--------------------------------------------------------------------------------
C1
--------------------------------------------------------------------------------
X
XXX
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
... -- truncated to save space
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+++
1 row selected.
SCOTT@orcl_11gR2>
|
|
|
|
| Re: Updating CLOB [message #504270 is a reply to message #504269] |
Fri, 22 April 2011 19:40   |
ThomasG
Messages: 3212 Registered: April 2005 Location: Heilbronn, Germany
|
Senior Member |
|
|
What I really feel here is that the CLOBs are not the right way to hold the data. Anything in a CLOB (or LOB for that matter) should not be anything that needs to be touched and updated thousands of times, since that will of course slow everything to a crawl.
Plus, having a CLOB named "MONTHLY_DATA" where records get appended sounds pretty much like having a *.CSV file stored in a CLOB that you then read to get to the data, and append to store more data, sounds pretty much like a complete design failure from the start.
At first glance child tables that hold the records would be the more RDBMS fitting solution. Than using a RDBMS to store "files" and then re-implement all the RDBMS features that would already be there for data in tables yourself.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Re: Updating CLOB [message #504309 is a reply to message #504283] |
Sat, 23 April 2011 05:39   |
ThomasG
Messages: 3212 Registered: April 2005 Location: Heilbronn, Germany
|
Senior Member |
|
|
One option which might be the easiest to implement without changing too much of the other code:
Don't store and then select the CLOBs from the table, crate a function that returns a CLOB and call that function in the select from PHP instead of the CLOB column.
Then put the logic that you now use to store the CLOB in the table in the function that returns the CLOB.
I have use that approach a few times, where I built complete HTML documents inside the database to pass to a front end as CLOBs.
[Updated on: Sat, 23 April 2011 05:39] Report message to a moderator
|
|
|
|
| Re: Updating CLOB [message #504335 is a reply to message #504309] |
Sat, 23 April 2011 14:30  |
 |
amerar
Messages: 18 Registered: April 2011
|
Junior Member |
|
|
So, are you suggesting maybe an inline function to collect the data, and the function itself will get the data? The table would have 5 CLOB columns, so you are suggesting to use individual functions to get the data instead?
|
|
|
|