Skip to Main Content
  • Questions
  • Is it possible to create a view over a table with a LONG column?

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Gary .

Asked: December 12, 2004 - 8:22 pm UTC

Last updated: December 13, 2004 - 1:56 pm UTC

Version: 9.2.0.4

Viewed 1000+ times

You Asked

Hi Tom

Welcome back from OOW.

I have read several threads on your site about this but didn't seem to find the answer I was looking for and even after RTFD I understood what the conditions are for converting a LONG to a VARCHAR2 but thought there might be a way around the restricting conditions. You always seem to find a way to do the 'impossible' things.

I am using OWB to pull data from an ERP system where I have no control over the layout of the tables but do have some flexibility in creating views.

One of the tables has a LONG column in it (I know it's so 80's but what's a guy to do) and I need to pull 5000 characters of the LONG coumn into my data warehouse using OWB. OWB at this point doesn't like LONG columns (or LOBs for that matter) so I wanted to have a view created over the table in the ERP system that would convert the LONG into a VARCHAR2(5000). I don't want to create another table since that would create an issue with keeping the table current and this table update is outside the normal ERP processing.

The documentation said the TO_LOB function could only be used in an INSERT or CTAS statement and I tend to agree with the documentation after trying various methods to 'trick' the system. I guess I'm not creative enough. I kept getting the old 'Expected 'x' got 'y' error.

Is there a way to create a view over the top of a LONG column that just picks up the first 5000 characters?

Many thanks from one of your groupies.

Gary

Additional information:

Whoops, I knew that there was a 4000 character limit in SQL. I must have been reading about the PL/SQL VARCHAR2 variable that holds 32K.

I can use two (2) 2500 character columns.

I tried creating the view with something like this:

create or replace view data_with_varachar2
as
select
col1,
col2.
col3,
dbms_lob.substr(to_lob(long_col), 2500, 1);

but this was giving me the error:

dbms_lob.substr(to_lob(long_col), 2500, 1)
*
ORA-00932: inconsistent datatypes: expected - got LONG


I also tried several other methods including just using the SQL function SUBSTR on the LONG column, but to no avail.

Many thanks for the help.

Gary


More additional information....

1- I expect to be merging about 1,000 rows daily into a DW table that currently has about 1.2 million rows. The table on the DW side could also be truncated and inserted into as opposed to using the merge.

2- The longest row had 30K of data and the average was only about 350 characters, but I only need the first 5000 characters based on the extract specification from the user.

The LONG column stores text entered or potentially attached to a Purchase Order by the user. The sizes are small since most of the time the text is entered manually by the Purchasing person. There is potentially a row in this table for every PO line although the vast majority do not have text associated with them.

Thanks very much for the help. Sorry to keep you occupied for such a LONG time. :-)>

Gary

and Tom said...

Ok, 1,000 rows is smallish, we can call plsql from sql. In the following, rowid could be replaced with a primary key of course. We'll cache the long so as to do the recursive sql to fetch it out once per row instead of once per call. Since you have 30k max, we can use static sql (else we'd have to use dbms_sql to read this piecewise)

Here is the approach:

ops$tkyte@ORA9IR2> create or replace package get_long_pkg
2 as
3 function piece( p_rowid in rowid, p_from in number, p_for in number ) return varchar2;
4 end;
5 /

Package created.

ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create or replace package body get_long_pkg
2 as
3 g_rowid rowid;
4 g_long long;
5
6 function piece( p_rowid in rowid, p_from in number, p_for in number ) return varchar2
7 is
8 begin
9 if (g_rowid is null or g_rowid <> p_rowid)
10 then
11 select theText into g_long
12 from foo
13 where rowid = p_rowid;
14 g_rowid := p_rowid;
15 end if;
16
17 return substr( g_long, p_from, p_for );
18 end;
19
20 end;
21 /

Package body created.

ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> select textLength,
2 get_long_pkg.piece( rowid, 1, 20 ) p1,
3 get_long_pkg.piece( rowid, 21, 20 ) p2
4 from foo
5 where rownum <= 5;

TEXTLENGTH P1 P2
---------- -------------------- --------------------
546 select ue.name, u.na me, o.name, c.name,
2624 select ou.name, oc.n ame,
decode(c

1211 select u.name, c.nam e, o.name,
de

2730 select uc.name, oc.n ame, c.name, ut.name
243 select o.name, c.sch ema, c.package
from



table foo was created by this process:

</code> http://asktom.oracle.com/Misc/MoveLongs.html <code>



Rating

  (1 rating)

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

Comments

Doh! How simple, a homemade SUBSTR function for LONG's

Gary Wicke, December 13, 2004 - 1:56 pm UTC

Fantastic!

Sometimes those trees just get in the way of the simple and lovely forest view. The function can now be used in the view creation statement.

Thanks again. Have a safe and enjoyable holiday.

Gary

More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here