Non Persistable Types

The ability to create user-defined types in Oracle is very powerful and is supported for many years (since Oracle 8).
It allows us to extend the built-in data types and adjust them to our specific needs, and to use them in our data model and in our code.
In the data model they can be used to define the type of specific columns or the type of tables (“object tables”).
In the code they can be used in SQL statements and in PL/SQL.

I’m not a big fan of using user-defined types in the data model.
I am, however, a huge fan of using them in the code.

Here are a few examples for posts in which user-defined types are used in the code:

So whenever I create a user-defined type my intention is that it will be used only in the code.
If the type is created in a PL/SQL scope, then my intention is enforced by definition.
But what if the type is created in the schema level? Can I enforce my intention? As of version 18c I can.

Persistability

A new feature in Oracle 18c allows to define a user-defined type as either persistable (which is the default) or not persistable.
A persistable type can be used in the code and in the data model, just like any type before 18c.
Let’s create color_t and color_tt as persistable types:

SQL> create type color_t as object (
  2    r number(3),
  3    g number(3),
  4    b number(3),
  5    member function hex_code return varchar2
  6  )
  7  /

Type created.

SQL>
SQL> create type body color_t as
  2    member function hex_code return varchar2
  3    is
  4    begin
  5      return '#' || to_char(self.r, 'fm0x') ||
  6                    to_char(self.g, 'fm0x') ||
  7                    to_char(self.b, 'fm0x');
  8    end hex_code;
  9  end color_t;
 10  /

Type body created.

SQL> create type color_tt as
  2    table of color_t
  3  /

Type created.

We can use persistable types in the data model.
As the type of an object table:

SQL> create table colors of color_t;

Table created.

As the type of a column:

SQL> create table people (
  2    first_name varchar2(20),
  3    last_name  varchar2(30),
  4    eye_color  color_t
  5  );

Table created.

And we can use persistable types in the code.
In PL/SQL:

SQL> declare
  2    v_yellow color_t := color_t(255,255,0);
  3    v_navy   color_t := color_t(0,0,128);
  4  begin
  5    dbms_output.put_line('Yellow: ' || v_yellow.hex_code);
  6    dbms_output.put_line('Navy:   ' || v_navy.hex_code);
  7  end;
  8  /
Yellow: #ffff00
Navy:   #000080

PL/SQL procedure successfully completed.

In SQL:

SQL> select *
  2  from color_tt(
  3         color_t(0,0,0),
  4         color_t(255,255,255));

         R          G          B
---------- ---------- ----------
         0          0          0
       255        255        255
SQL> drop table people;

Table dropped.

SQL> drop table colors;

Table dropped.

SQL> drop type color_tt;

Type dropped.

SQL> drop type color_t;

Type dropped.

A non persistable type can be used only in the code.
If we try to use it as the type of an object table or a column, we get the ORA-22384 exception.
Let’s create color_t and color_tt as non-persistable types:

SQL> create type color_t as object (
  2    r number(3),
  3    g number(3),
  4    b number(3),
  5    member function hex_code return varchar2
  6  )
  7  not persistable
  8  /

Type created.

SQL>
SQL> create type body color_t as
  2    member function hex_code return varchar2
  3    is
  4    begin
  5      return '#' || to_char(self.r, 'fm0x') ||
  6                    to_char(self.g, 'fm0x') ||
  7                    to_char(self.b, 'fm0x');
  8    end hex_code;
  9  end color_t;
 10  /

Type body created.

SQL> create type color_tt as
  2    table of (color_t)
  3  not persistable
  4  /

Type created.

We cannot use non-persistable types in the data model:

SQL> create table colors of color_t;
create table colors of color_t
*
ERROR at line 1:
ORA-22384: cannot create a column or table of a non-persistable type

SQL> create table people (
  2    first_name varchar2(20),
  3    last_name  varchar2(30),
  4    eye_color  color_t
  5  );
create table people (
*
ERROR at line 1:
ORA-22384: cannot create a column or table of a non-persistable type

We can use non-persistable types in the code, in PL/SQL and in SQL:

SQL> declare
  2    v_yellow color_t := color_t(255,255,0);
  3    v_navy   color_t := color_t(0,0,128);
  4  begin
  5    dbms_output.put_line('Yellow: ' || v_yellow.hex_code);
  6    dbms_output.put_line('Navy:   ' || v_navy.hex_code);
  7  end;
  8  /
Yellow: #ffff00
Navy:   #000080

PL/SQL procedure successfully completed.

SQL>
SQL> select *
  2  from color_tt(
  3         color_t(0,0,0),
  4         color_t(255,255,255));

         R          G          B
---------- ---------- ----------
         0          0          0
       255        255        255
SQL> drop type color_tt;

Type dropped.

SQL> drop type color_t;

Type dropped.

Type Dependency

As you may expect, a persistable type cannot depend on non-persistable types.

SQL> create type color_t as object (
  2    r number(3),
  3    g number(3),
  4    b number(3)
  5  )
  6  not persistable
  7  /

Type created.

SQL> create type color_tt as table of color_t
  2  /

Warning: Type created with compilation errors.

SQL> show err
Errors for TYPE COLOR_TT:

LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0      ORA-22383: a persistable type cannot have non-persistable
         attributes

A non-persistable type can depend on both persistable and non-persistable types.

SQL> create or replace type color_tt as
  2    table of (color_t)
  3  not persistable
  4  /

Type created.

Note: the parenthesis are required when creating a collection type with the persistability clause

SQL> drop type color_tt;

Type dropped.

SQL> drop type color_t;

Type dropped.

Type Inheritance

A subtype inherits the persistability attribute of its supertype, and cannot override it.

SQL> create type color_t as object (
  2    r number(3),
  3    g number(3),
  4    b number(3)
  5  )
  6  not final
  7  not persistable
  8  /

Type created.

SQL> create type rgba_color_t
  2    under color_t
  3    (alpha number(3))
  4  persistable
  5  /

Warning: Type created with compilation errors.

SQL> show err
Errors for TYPE RGBA_COLOR_T:

LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0      PLS-00772: PERSISTABLE or NOT PERSISTABLE not permitted with
         UNDER clause

SQL> create type rgba_color_t
  2    under color_t
  3    (alpha number(3))
  4  /

Type created.

SQL> select type_name,persistable
  2  from user_types;

TYPE_NAME            PERSISTABLE
-------------------- --------------------
COLOR_T              NO
RGBA_COLOR_T         NO

In the next post I’ll write about an enhancement that was added to non-persistent types in Oracle 21c.

2 thoughts on “Non Persistable Types”

  1. Hi Oran,
    I bumped into your article while trying to solve some issues with plsql OOP.
    It seems that you just solved it and I think that it explains why Oracle bothered to add the feature in the first place.
    Here is the case:
    I implemented two levels of hierarchy OOP in plsql when the base type and few under it.
    It worked fine as long as one sub-type was initiated and used.
    If more than one subtype was initiated and methods invoked it caused a lock.
    I couldn’t find any documentation on the issue but I suspected that it has something to do with recompiling the base type behind the scenes and trying to protect consistency of the data model.
    Anyhow once I made the base type not persistable the locks disappeared.
    I think this is why the feature was introduced in the first place.

Leave a Reply

Your email address will not be published. Required fields are marked *