Showing posts with label long. Show all posts
Showing posts with label long. Show all posts

Friday, November 27, 2015

A Simple Example of an Index Organised Table Without Overflow

For a long time I have had a note on my task list to learn about index organized tables. I never got round to doing it because I thought I would never see one. However, I came across several in a 3rd party application recently. An index organized table is a kind of index and table combined. You can see how they work in the example below, which I tested in an Oracle 11.2 database:
 
First I created a sequence. You don’t need a sequence to create an index organized table. I just used it to ensure that the index always contained unique values:

SQL> create sequence seq1
  2  /
 
Sequence created.

SQL>

I read that an index organized table cannot contain a LONG column. When I tried to do this, Oracle returned an ORA-02160:

SQL> create table iot1
  2  (owner varchar2(30),
  3   object_name varchar2(30),
  4   seq_no number,
  5   column_not_allowed long,
  6   constraint iot1_pk
  7   primary key (owner, object_name, seq_no))
  8  organization index
  9  /
organization index
             *
ERROR at line 8:
ORA-02160: index-organized table can not contain
columns of type LONG
 
SQL>

Without the LONG column, the index organized table was created successfully. This was an index organized table without overflow. I will try to look at overflow in a future post:

SQL> create table iot1
  2  (owner varchar2(30),
  3   object_name varchar2(30),
  4   seq_no number,
  5   constraint iot1_pk
  6   primary key (owner, object_name, seq_no))
  7  organization index
  8  /
 
Table created.
 
SQL>

After creating the index organized table, it had an IOT_TYPE of IOT. The IOT_NAME column was empty as the index organized table did not have overflow:

SQL> select iot_type, nvl(iot_name,'NULL')
  2  from user_tables
  3  where table_name = 'IOT1'
  4  /
 
IOT_TYPE             NVL(IOT_NAME,'NULL')
-------------------- ------------------------------
IOT                  NULL

SQL>

I added data to the index organized table like this:

SQL> begin
  2   for i in 1..15 loop
  3    insert into iot1
  4    select owner, object_name, seq1.nextval
  5    from dba_objects;
  6   end loop;
  7  end;
  8  /
 
PL/SQL procedure successfully completed.
 
SQL> select count(*) from iot1
  2  /
 
  COUNT(*)
----------
    996060

SQL>

The index organized table had an entry in DBA_TABLES:

SQL> select count(*) from dba_tables
  2  where table_name = 'IOT1'
  3  /
 
  COUNT(*)
----------
         1

SQL>

... but it did not appear in DBA_SEGMENTS:

SQL> select count(*) from dba_segments
  2  where segment_name = 'IOT1'
  3  /
 
  COUNT(*)
----------
         0

SQL>

... and its TABLESPACE_NAME entry in DBA_TABLES was empty: 

SQL> select nvl(tablespace_name,'NULL')
  2  from dba_tables
  3  where table_name = 'IOT1'
  4  /
 
NVL(TABLESPACE_NAME,'NULL')
------------------------------
NULL

SQL>

The index associated with the index organized table had an entry in DBA_SEGMENTS so I checked how big it was:

SQL> select bytes from dba_segments
  2  where segment_name = 'IOT1_PK'
  3  /
 
     BYTES
----------
  83886080

SQL>

Then I deleted several rows from the index organized table:

SQL> delete from iot1
  2  where owner = 'SYS'
  3  /
 
460995 rows deleted.

SQL>

... and checked that this deleted some leaf rows from the index:

SQL> analyze index iot1_pk validate structure
  2  /
 
Index analyzed.
 
SQL> select name, lf_rows, del_lf_rows
  2  from index_stats
  3  /
 
NAME          LF_ROWS DEL_LF_ROWS
---------- ---------- -----------
IOT1_PK        848331      313266
 
SQL>

When this happens, you can usually just rebuild the index but when I tried to do this to the index for the index organized table, Oracle returned an ORA-28650:

SQL> alter index iot1_pk rebuild
  2  /
alter index iot1_pk rebuild
*
ERROR at line 1:
ORA-28650: Primary index on an IOT cannot be rebuilt
 
SQL>

So I moved the table instead:

SQL> alter table iot1 move online
  2  /
 
Table altered.

SQL>

... then I analyzed the index again:

SQL> analyze index iot1_pk validate structure
  2  /
 
Index analyzed.

SQL>

... and saw that the deleted leaf rows had disappeared:
 
SQL> select name, lf_rows, del_lf_rows
  2  from index_stats
  3  /
 
NAME          LF_ROWS DEL_LF_ROWS
---------- ---------- -----------
IOT1_PK        535065           0

SQL>

... and the index was much smaller:

SQL> select bytes from dba_segments
  2  where segment_name = 'IOT1_PK'
  3  /
 
     BYTES
----------
  25165824

SQL>

Tuesday, January 28, 2014

ORA-01754

The first example below was tested on Oracle 11.2. If you try to have more than one long column in a table, you get an ORA-01754:

SQL> create table tab1 (col1 long, col2 long)
  2  /
create table tab1 (col1 long, col2 long)
                              *
ERROR at line 1:
ORA-01754: a table may contain only one column of type LONG
 
SQL> 

That was fairly obvious. Now here is another example, which I wrote at the start of 2012. I do not know which Oracle version I did it on. First I created a table with one column:

SQL> create table andrews_table
  2  (col1 varchar2(10))
  3  /

Table created.

SQL>

Then I added a long column to the table and described it to show the column I had just added:

SQL> alter table andrews_table
  2  add (col2 long)
  3  /

Table altered.

SQL> desc andrews_table
Name                      Null?    Type
-------------------------- -------- ------------------
COL1                                VARCHAR2(10)
COL2                                LONG

SQL>

Next I set the long column to unused. This does not restore the disk space used by the column:

SQL> alter table andrews_table
  2  set unused column col2
  3  /

Table altered.

SQL>

I described the table again to show that the long column had gone:

SQL> desc andrews_table
Name                      Null?    Type
-------------------------- -------- ------------------
COL1                                VARCHAR2(10)

SQL>

Then I tried to add another long column. This failed as you can only have 1 long column per table. How would you diagnose this problem if it happened to you in real life?

SQL> alter table andrews_table
  2  add (col3 long)
  3  /
add (col3 long)
    *
ERROR at line 2:
ORA-01754: a table may contain only one column of type
LONG

SQL>

You can get a clue by looking in user_unused_col_tabs, which confirms that the table has 1 unused column:

SQL> select count(*) from user_unused_col_tabs
  2  where table_name = 'ANDREWS_TABLE'
  3  /

  COUNT(*)
----------
         1

SQL>

Drop the unused column from the table. This frees up the disk space which the column occupied:

SQL> alter table andrews_table
  2  drop unused columns
  3  /

Table altered.

SQL>

The table no longer has an entry in user_unused_col_tabs:

SQL> select count(*) from user_unused_col_tabs
  2  where table_name = 'ANDREWS_TABLE'
  3  /

no rows selected

SQL>

And you can add another long column if you wish:

SQL> alter table andrews_table
  2  add (col3 long)
  3  /

Table altered.

SQL>

Friday, July 13, 2012

ORA-00932

This was tested on Oracle 9 and Oracle 11.2. If you are searching for a piece of text, which you believe is in one of your views, you might try to do it like this:

SQL> select owner, view_name
  2  from dba_views
  3  where upper(text) like '%BLAH%'
  4  /
where upper(text) like '%BLAH%'
            *
ERROR at line 3:
ORA-00932: inconsistent datatypes: expected NUMBER got
LONG

SQL>

It fails because TEXT is a LONG column:

SQL> desc dba_views
Name                       Null?    Type
-------------------------- -------- ------------------
OWNER                      NOT NULL VARCHAR2(30)
VIEW_NAME                  NOT NULL VARCHAR2(30)
TEXT_LENGTH                         NUMBER
TEXT                                LONG
TYPE_TEXT_LENGTH                    NUMBER
TYPE_TEXT                           VARCHAR2(4000)
OID_TEXT_LENGTH                     NUMBER
OID_TEXT                            VARCHAR2(4000)
VIEW_TYPE_OWNER                     VARCHAR2(30)
VIEW_TYPE                           VARCHAR2(30)
SUPERVIEW_NAME                      VARCHAR2(30)

SQL>

One workaround is to SELECT the OWNERVIEW_NAME and TEXT of all your views and SPOOL them to a file. Then you can search the spool file produced with vi or Notepad.

Wednesday, March 14, 2012

Set Long

As their name suggests, long columns can be long. Oracle lets you choose how much of a long column you see when you select it. You can do this with the set long SQL*Plus command. To illustrate this, first create a table with a 26 character long column: 

SQL> create table andrews_table
  2  (long1 long)
  3  /
 
Table created.
 
SQL> insert into andrews_table values
  2  ('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
  3  /
 
1 row created.

SQL>

To see the current value of long, use the show long command:
 
SQL> show long
long 80
SQL>

The value is 80. This means that you will see a maximum of 80 characters if you select a long column. Therefore, if you select the long column in the table above, you will see all of it: 
 
SQL> select * from andrews_table
  2  /
 
LONG1
-------------------------------------------------------
ABCDEFGHIJKLMNOPQRSTUVWXYZ

SQL>

If you set long to 10, you will see the first ten characters of a long column:
 
SQL> set long 10
SQL> select * from andrews_table
  2  /
 
LONG1
----------
ABCDEFGHIJ

SQL>

If you set long to 20, you will see the first 20 characters of a long column:
 
SQL> set long 20
SQL> select * from andrews_table
  2  /
 
LONG1
--------------------
ABCDEFGHIJKLMNOPQRST

SQL>

... and so on:
 
SQL> set long 30
SQL> select * from andrews_table
  2  /
 
LONG1
------------------------------
ABCDEFGHIJKLMNOPQRSTUVWXYZ
 
SQL>

Thursday, December 29, 2011

Long to LOB Conversion

I went on an Oracle 11g release 2 seminar recently. They said that LONG data types are still supported but that Oracle recommends converting them to LOB (i.e. CLOB or NCLOB). I’m not totally convinced by this as they are still using LONG columns themselves e.g. in table SYS.VIEW$, which is one of the underlying tables for the DBA_VIEWS view:
 
SQL*Plus: Release 10.2.0.4.0 - Production on Thu Dec 29 14:27:22 2011
 
Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.
 
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
 
SQL> desc sys.view$
Name                       Null?    Type
-------------------------- -------- ------------------
OBJ#                       NOT NULL NUMBER
AUDIT$                     NOT NULL VARCHAR2(38)
COLS                       NOT NULL NUMBER
INTCOLS                    NOT NULL NUMBER
PROPERTY                   NOT NULL NUMBER
FLAGS                      NOT NULL NUMBER
TEXTLENGTH                          NUMBER
TEXT                                LONG
 
SQL>
 
Converting a LONG to a CLOB is easy:
 
SQL> create table andrews_table
  2  (name varchar2(10),
  3   address long)
  4  /
 
Table created.
 
SQL> insert into andrews_table values
  2  ('Noddy', '10 High St, Anytown')
  3  /
 
1 row created.
 
SQL> alter table andrews_table modify (address clob)
  2  /
 
Table altered.
 
SQL> desc andrews_table
Name                       Null?    Type
-------------------------- -------- ------------------
NAME                                VARCHAR2(10)
ADDRESS                             CLOB
 
SQL> select * from andrews_table
  2  /
 
NAME       ADDRESS
---------- --------------------
Noddy      10 High St, Anytown
 
SQL>
 
But you need to be certain that you want to do this as there is no going back:
 
SQL> alter table andrews_table modify (address long)
  2  /
alter table andrews_table modify (address long)
                                  *
ERROR at line 1:
ORA-22859: invalid modification of columns
 
SQL>

Long Datatypes

I was looking at LONG datatypes in an Oracle 9 database recently. There are a couple of restrictions with them. You cannot do a create table as select or CTAS on a table or view which contains a LONG column:
  
SQL> desc dba_views
Name                       Null?    Type
-------------------------- -------- ------------------
OWNER                      NOT NULL VARCHAR2(30)
VIEW_NAME                  NOT NULL VARCHAR2(30)
TEXT_LENGTH                         NUMBER
TEXT                                LONG
TYPE_TEXT_LENGTH                    NUMBER
TYPE_TEXT                           VARCHAR2(4000)
OID_TEXT_LENGTH                     NUMBER
OID_TEXT                            VARCHAR2(4000)
VIEW_TYPE_OWNER                     VARCHAR2(30)
VIEW_TYPE                           VARCHAR2(30)
SUPERVIEW_NAME                      VARCHAR2(30)

SQL> create table andrews_views
  2  as select * from dba_views
  3  /
as select * from dba_views
          *
ERROR at line 2:
ORA-00997: illegal use of LONG datatype

SQL>


And you cannot have more than 1 LONG column in a table:

SQL> create table andrews_table
  2  (long1 long)
  3  /


Table created.

SQL> alter table andrews_table add
  2  (long2 long)
  3  /
(long2 long)
*
ERROR at line 2:
ORA-01754: a table may contain only one column of type LONG

SQL>