Oracle check constraint for varray type - oracle

I have a custom type defined as this :
CREATE TYPE myType_t AS VARRAY(2) of char(10);
Is it possible to add a check constraint on the char(10) type, so myType_t items respect a certain regex? I tried things like
CREATE TYPE myType_t AS VARRAY(2) of char(10)
( constraint c_myType_format check ( regexp_like(IdontKnowWhatToWriteHere, '[:digit:]{8}'));
which obviously doesn't work... I thought maybe defining another type for the
AS VARRAY(2) of myOtherType_t
but here again I don't know where to put the regex check.
And yes, I also tried adding the constraint to the table that will use my type, but I can't find the correct syntax.

According to Oracle documentation:
Oracle does not support constraints on columns or attributes whose
type is a user-defined object, nested table, VARRAY, REF, or LOB

Related

How to give a field of an object the same type as a column of a table?

I would like to a object with a field that has the same type as column of a table.
create table TA (
TA_1 number
);
CREATE TYPE my_obj2 IS object
(
TA_1 TA.TA_1%type
);
ORA-24344: success with compilation error
Is it possible. If yes, what is wrong in this code?
code
You can't do that.
The CREATE TYPE document states:
This data type must be stored in the database; that is, either a predefined data type or a user-defined standalone collection type.

Syntax for creating foreign key index inline in create table statement

I want to create a table bar with a named foreign key constraint backed by a named index. I would like to do that with an inline definition in the create table DDL statement. When looking at the Oracle 19 SQL Language Reference it looks like Oracle should support doing this inline.
When executing the following statements...
create table foo (
id number not null primary key
);
create table bar (
id number not null primary key,
nick varchar2(16) not null constraint foo_nick_ck unique using index,
foo_id number not null constraint foo_fk references foo using index
);
Oracle will respond with [42000][907] ORA-00907: missing right parenthesis and point at the position just before the using index on the last line. If I remove using index it works (but without index being created of course). I've kept the column nick as an example of where it works to create the backing index inline, but for a unique constraint instead of a foreign key constraint.
I am aware that a workaround is to create the backing index in a separate DDL statement, but I would very much like to have it neat and tidy inline.
I am aware that a workaround is to create the backing index in a separate DDL statement, but I would very much like to have it neat and tidy inline.
Unfortunately the syntax does not exist to create indexes inline.
The USING INDEX clause is syntactic sugar: Oracle creates indexes to enforce Primary Key and Unique constraints regardless of whether we include that clause (*). This is because an index is necessary to Oracle's implementation of unique constraints. But there is no such need for an index to enforce a foreign key, it's just desirable.
(*) Unless there's an existing index on the constrained column(s) which Oracle can use.
As per Oracle documentation:
You can specify the using_index_clause only when enabling unique or
primary key constraints
You cannot specify this clause for a NOT NULL, foreign key, or
check constraint.

Oracle PLSQL Alter/Drop Attributes of Object Type

I am new to Oracle PLSQL and have to Alter an Object Type. I´ve made many mistakes with the data types of the new Columns, so I had to drop them and altered them a second time.
For example, I did this:
ALTER TYPE testObjectType ADD ATTRIBUTE (Prename VARCHAR2(50))
ALTER TYPE testObjectType DROP ATTRIBUTE Prename
ALTER TYPE testObjectType ADD ATTRIBUTE (Prename VARCHAR2(50 CHAR))
Now below the "Create or Replace" - Code of the Object there are many lines of code about adding & dropping Attributes. I´ve to try to simply delete this lines but the changes don't work at all. How can I tidy up my Object-Type? (I'm using Oracle SQL Developer).
You need to reset it so it is no longer treated as an evolved type:
alter type testobjecttype reset;
Then you can rebuild it with:
create or replace type testobjecttype as object
( prename varchar2(50 char) );
(plus any other attributes etc it should have).
btw there isn't much point naming database objects in CamelCase as the database ignores it, and schema browsers will just list it in uppercase (because that's how the dictionary stores names), which can become hard to read without word separators. (And shouldn't it be TestObjectType anyway?) There is a better case for it in naming program variables, although they are case-insensitive as well, so it's probably simplest and cleanest to just code in lowercase.

Table types with dba objects

Why can't we create an object with the below code.
create or replace type typ_obj_dba_test as object (name_col
dba_objects.object_name%type);
It gives me object_name must be declared.
Is it because dba_objects is a view?
"Is it because dba_objects is a view?"
No. You couldn't do it with a table column either. The %TYPE syntax is restricted to PL/SQL and you are creating a SQL TYPE, not PL/SQL.
This restriction is annoying to many developers, particularly those coming from a background in more dynamic programming languages. But the snag is %TYPE syntax is dynamic: if the referenced column changes its data type the referencing object changes.
That's neat when we're declaring variables or parameters in stored procedures. But we can use SQL types to define table columns (*). Cascading a change in one column to who-knows-how-many columns which reference it would be a nightmare. So Oracle doesn't allow us to do it.
I'm afraid you'll need to use an explicit datatype declaration:
create or replace type typ_obj_dba_test as object (
name_col varchar2(30)
);
(*) It's not generally advisable to use Types in table definitions, but Oracle supports ORDBMS data structures.

Can I drop/add attribute without consequences? Oracle Object Type

I have an OBJECT_TYPE with ATTRIBUTE varchar2(200). There many other objects referencing this one. I need to reduce the length of the attribute to varchar2(50). I know I cannot do it directly, so I found this way:
ALTER TYPE CUSTOMER DROP ATTRIBUTE name INVALIDATE;
ALTER TYPE CUSTOMER ADD ATTRIBUTE name varchar2(50) CASCADE;
The question is: is there anything that could be broken after the dropping/creating of the attribute? Is it correct to use the INVALIDATE option instead of CASCADE in the DROP statement? I don't want to loose anything - relations or data.
Is there a reason the following is not used:
ALTER TYPE CUSTOMER MODIFY ATTRIBUTE name VARCHAR2(50);
I have run into compatibility problems when using types and dropping an attribute especially if there are tables and data defined using the types. This is one reason I avoid basing tables and views on the data types. The change in the length would invalidate the table and any rows where the associated data exceeds 50. If the other objects are just types and are not used in views and tables then the alter type above should work fine. And you may need to recompile any types. Keep in mind that the type is becoming more restrictive and how it may affect any associated data.

Resources