Showing posts with label LONG datatype. Show all posts
Showing posts with label LONG datatype. Show all posts

Friday, August 30, 2024

DBMS_XMLGEN limited workaround for converting LONG columns into CLOBs

If you landed here is because you hit the problem of dealing with LONG columns.

There are some good articles elsewhere about how to tackle this old problem, my contribution in this case consists in advising about some limitations that apparently have been overlooked when using the same technique explained below.

It's a mystery to me why after so many years we can't rid of this annoyance once for good, why not "simply" adding a CLOB column equivalent at least in the case of data dictionary columns?
Come on!

I needed to extract the content of the TEXT column from DBA_VIEWS and DBA_MVIEWS, possibly without having to pass through an INSERT into a table (using function TO_LOB), which is the best workaround in case you deal with static data, for one-off operations.

I stumbled upon an old video of Connor McDonald showing how to extract the content of a LONG column exploiting the XML API DBMS_XMLGEN.GETXMLTYPE. This trick seemed to save the day after some adaptation for my case, and actually I was almost ready to celebrate when I started hitting some errors while doing further tests.

To cut a long story short, eventually I encountered the following problems:

  1. API documentation for version 19c of DBMS_XMLGEN.SETCONVERTSPECIALCHARS is incorrect as it mentions a parameter "conv" but the real parameter name is "replace". This typo is still present in the latest version of the documentation of 23ai.

  2. DBMS_XMLGEN.GETXMLTYPE and DBMS_XMLGEN.GETXML won't perform special characters escaping via DBMS_XMLGEN.SETCONVERTSPECIALCHARS if the column type is LONG.
    I was getting parsing errors when using Connor's EXTRACTVALUE technique because the XML document contained < or > as spare characters in the source (as in WHERE conditions inside the query source).

  3.  DBMS_XMLGEN.GETXMLTYPE and DBMS_XMLGEN.GETXML will truncate the content to the first 32K for LONG columns.

Problem #1 was easily solved, problem #2 was solved extracting the data using REGEXP_SUBSTR instead of EXTRACTVALUE, but this was possible because I was working on a XML document containing a single ROW tag at a time. For multiple rows this solution will not work.

  FUNCTION long2clob
     ( p_qry in clob, -- must return a single row!
       p_col in varchar2)
  RETURN CLOB
  IS
    c        CLOB;
  BEGIN
    c := regexp_substr(
           dbms_xmlgen.getxml(p_qry),
           '(<ROW>.*<' || p_col || '>(.*)</' || p_col || '>.*</ROW>)',
           1,
           1,
           'cn'
           ,2
         );
    return c;

  END long2clob;

Problem #3 remains, unless LONG columns are less than 32K.
Unfortunately we do have some views exceeding 32K of source, but considering the usage of this function I'll probably live with this limitation for the moment.
By the way, SQLDeveloper won't allow you to edit a view larger than 32K, and to me this sounds like an invitation to avoid such situations.

Finally, I also tried to see what happens when you supply a LONG column to function JSON_OBJECT, unfortunately it returns the exception:

ORA-40654: Input to JSON generation function has unsupported data type.

That's all folks!
(quote)

Wednesday, November 21, 2007

ORA-00997: illegal use of LONG datatype

I don't really expect to see a large audience for this kind of error as the LONG datatype has been long deprecated by Oracle and it has been superseded by CLOBs (and BLOBs in case of LONG RAW), however a friend of mine contacted me this morning because while trying to execute a simple query like:
INSERT INTO long_table_b (col_k, long_col)
SELECT 2, long_col
FROM long_table_a
WHERE col_k = 1
he was getting the following error message:
ORA-00997: illegal use of LONG datatype

The reason is quite simple, open up the oracle document where the restrictions that apply to LONG datatypes are described and you will realize that you cannot just perform a simple query like the above when LONGs are involved (see bullet #8).

You can easily recreate the problem in this fashion:

create table test_long_a (col_k number, long_col long)
/
create table test_long_b (col_k number, long_col long)
/
insert into test_long_a values (1, lpad(' ', 4000))
/
insert into test_long_b
select 2, long_col
from test_long_a
where col_k = 1
/
ORA-00997: illegal use of LONG datatype
Now you might want to ask how can you can work around this limitation.
Well, the fact is that LONG datatypes have so many limitations that it is really a problem to work with them. According to Tom Kyte there are a few possibilities that you might want to explore, but basically you'd better to migrate the programs soon from LONG to CLOBs (or BLOBs) because they have been deprecated for almost 10 years now.
In the end CLOBs and BLOBs are much better to deal with, so do not *waste* your time with LONGs any more.

See message translations for ORA-00997 and search additional resources.



ORA-00997: Uso non consentito del tipo dati LONG
ORA-00997: uso no válido del tipo de dato LONG
ORA-00997: el tipus de dades LONG s'utilitza de forma il legal
ORA-00997: utilisation interdite du type de données LONG
ORA-00997: Unzulässige Verwendung des Datentyps LONG
ORA-00997: μη αποδεκτή χρήση του τύπου δεδομένων LONG
ORA-00997: ugyldig brug af LONG-datatype
ORA-00997: otillåten användning av datatypen LONG
ORA-00997: ugyldig bruk av datatypen LONG
ORA-00997: LONG-tietotyyppiä on käytetty väärin
ORA-00997: itt nem megengedett a LONG adattípus használata
ORA-00997: folosire ilegală a tipului de dată LONG
ORA-00997: Ongeldig gebruik van LONG-gegevenstype.
ORA-00997: uso inválido do tipo de dados LONG
ORA-00997: utilização ilegal do tipo de dados LONG
ORA-00997: неверное использование типа данных LONG
ORA-00997: nepřípustně použitý datový typ LONG
ORA-00997: neprípustné použitie dátového typu LONG
ORA-00997: niedozwolone użycie typu danych LONG
ORA-00997: geçersiz LONG veri türü kullanımı
ORA-00997: illegal use of LONG datatype

yes you can!

Two great ways to help us out with a minimal effort. Click on the Google Plus +1 button above or...
We appreciate your support!

latest articles