Domains in Oracle Database 23ai/26ai
This article demonstrates the use of Domains in Oracle database 23ai/26ai.
oracle 23configurationintermediate
by OracleDba
32 views
This article demonstrates the use of Domains in Oracle database 23ai/26ai.
12345678
conn sys/SysPassword1@//localhost:1521/freepdb1 as sysdba
drop user if exists testuser1 cascade;
create user testuser1 identified by testuser1 quota unlimited on users;
grant connect, resource to testuser1;
grant create domain to testuser1;
conn testuser1/testuser1@//localhost:1521/freepdb112345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
drop domain if exists email_dom;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'));
drop domain if exists email_dom;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'))
display lower(email_dom)
order lower(email_dom)
annotations (Description 'Domain for Emails');
drop domain if exists email_dom;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'))
collate binary_ci;
drop domain if exists email_dom;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'))
display lower(email_dom)
order lower(email_dom)
annotations (Description 'Domain for Emails');
-- Domain reference.
drop table if exists t1 purge;
create table t1 (
id number,
email email_dom
);
-- Domain reference with domain keyword.
drop table if exists t1 purge;
create table t1 (
id number,
email domain email_dom
);
-- Data type and domain reference.
drop table if exists t1 purge;
create table t1 (
id number,
email varchar2(100) email_dom
);
-- Data type and domain reference with domain keyword.
drop table if exists t1 purge;
create table t1 (
id number,
email varchar2(100) domain email_dom
);
SQL> desc t1;
Name Null? Type
----------------------------------------- -------- ---------------------------------
ID NUMBER
EMAIL VARCHAR2(100) TESTUSER1.EMAIL_DOM
SQL>
-- Insert correctly.
insert into t1 values (1, '[email protected]');
insert into t1 values (2, '[email protected]');
-- Doesn't pass check constraint.
insert into t1 values (3, 'banana');
*
ERROR at line 1:
ORA-11534: check constraint (TESTUSER1.SYS_C0012510) due to domain constraint TESTUSER1.EMAIL_CHK of
domain TESTUSER1.EMAIL_DOM violated
SQL>1234567891011121314151617181920212223242526272829303132333435363738394041
drop domain if exists address_dom;
create domain address_dom as (
address_line_1 as varchar2(50),
address_line_2 as varchar2(50),
city as varchar2(50),
country_code as varchar2(5),
postcode as varchar2(10)
)
constraint address_chk check (address_line_1 is not null and
city is not null and
country_code is not null and
postcode is not null)
display address_line_1||','||address_line_2||','||city||','||country_code||','||postcode;
drop table if exists addresses purge;
create table addresses (
id number,
address_line_1 varchar2(50),
address_line_2 varchar2(50),
city varchar2(50),
country_code varchar2(5),
postcode varchar2(10),
domain address_dom(address_line_1, address_line_2, city, country_code, postcode)
);
SQL> desc addresses
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
ADDRESS_LINE_1 VARCHAR2(100) TESTUSER1.ADDRESS_DOM
ADDRESS_LINE_2 VARCHAR2(50) TESTUSER1.ADDRESS_DOM
CITY VARCHAR2(50) TESTUSER1.ADDRESS_DOM
COUNTRY_CODE VARCHAR2(5) TESTUSER1.ADDRESS_DOM
POSTCODE VARCHAR2(10) TESTUSER1.ADDRESS_DOM
SQL>
drop table if exists addresses purge;
drop domain if exists address_dom;123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
-- UK address.
create domain address_uk_dom as (
address_line_1 as varchar2(50),
address_line_2 as varchar2(50),
city as varchar2(50),
postcode as varchar2(10)
)
constraint address_uk_chk check (address_line_1 is not null and
city is not null and
postcode is not null and
length(postcode) between 6 and 8);
-- US address.
create domain address_us_dom as (
address_line_1 as varchar2(50),
address_line_2 as varchar2(50),
city as varchar2(50),
postcode as varchar2(10)
)
constraint address_us_chk check (address_line_1 is not null and
city is not null and
postcode is not null and
(length(postcode) = 5 or length(postcode) = 9));
-- Default address.
create domain address_dom as (
address_line_1 as varchar2(50),
address_line_2 as varchar2(50),
city as varchar2(50),
postcode as varchar2(10)
)
constraint address_chk check (address_line_1 is not null and
city is not null and
postcode is not null);
create flexible domain address_flex_dom (address_line_1, address_line_2, city, postcode)
choose domain using (country_code varchar2(5))
from case
when country_code in ('GB','GBR') then address_uk_dom(address_line_1, address_line_2, city, postcode)
when country_code in ('US','USA') then address_us_dom(address_line_1, address_line_2, city, postcode)
else address_dom(address_line_1, address_line_2, city, postcode)
end;
create table addresses (
id number,
address_line_1 varchar2(50),
address_line_2 varchar2(50),
city varchar2(50),
country_code varchar2(5),
postcode varchar2(10),
domain address_flex_dom(address_line_1, address_line_2, city, postcode) using (country_code)
);
insert into addresses (id, address_line_1, address_line_2, city, country_code, postcode)
values (1, '1 my street', null, 'birmingham', 'GB', 'A12 BCD');
1 row created.
SQL>
insert into addresses (id, address_line_1, address_line_2, city, country_code, postcode)
values (2, '2 my street', null, 'boston', 'US', '12345');
1 row created.
SQL>
insert into addresses (id, address_line_1, address_line_2, city, country_code, postcode)
values (3, '3 my street', null, 'dublin', 'IRE', '1234567890');
1 row created.
SQL>
insert into addresses (id, address_line_1, address_line_2, city, country_code, postcode)
values (4, '4 my street', null, 'birmingham', 'GB', '12345');
*
ERROR at line 1:
ORA-11534: check constraint (TESTUSER1.SYS_C0012512) due to domain constraint
TESTUSER1.SYS_DOMAIN_C0063 of domain TESTUSER1.ADDRESS_FLEX_DOM violated
SQL>
insert into addresses (id, address_line_1, address_line_2, city, country_code, postcode)
values (5, '5 my street', null, 'boston', 'US', 'A12 BCD');
*
ERROR at line 1:
ORA-11534: check constraint (TESTUSER1.SYS_C0012513) due to domain constraint
TESTUSER1.SYS_DOMAIN_C0062 of domain TESTUSER1.ADDRESS_FLEX_DOM violated
SQL>
drop table if exists addresses purge;
drop domain if exists address_flex_dom;
drop domain if exists address_dom;
drop domain if exists address_uk_dom;
drop domain if exists address_us_dom;123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
create domain kanban_lanes_domain as
enum (
backlog,
doing,
review,
done
);
select * from kanban_lanes_domain;
ENUM_NA ENUM_VALUE
------- ----------
BACKLOG 1
DOING 2
REVIEW 3
DONE 4
SQL>
drop domain if exists kanban_lanes_domain;
create domain kanban_lanes_domain as
enum (
backlog = 10,
doing = 20,
review = 30,
done = 40
);
select * from kanban_lanes_domain;
ENUM_NA ENUM_VALUE
------- ----------
BACKLOG 10
DOING 20
REVIEW 30
DONE 40
SQL>
drop domain if exists kanban_lanes_domain;
create domain kanban_lanes_domain as
enum (
backlog = 'B',
doing = 'D',
review = 'R',
done = 'D2'
);
select * from kanban_lanes_domain;
ENUM_NA EN
------- --
BACKLOG B
DOING D
REVIEW R
DONE D2
SQL>
drop domain if exists kanban_lanes_domain;
create domain kanban_lanes_domain as
enum (
backlog,
doing,
review,
done
);
create table kanban_board (
id number generated always as identity,
story clob,
lane kanban_lanes_domain
);
insert into kanban_board (story, lane) values ('Do something', kanban_lanes_domain.doing);
column story format A20
select id, story, domain_display(lane) as lane from kanban_board;
ID STORY LANE
---------- -------------------- -------
1 Do something DOING
SQL>
drop domain if exists kanban_lanes_domain force;
create domain kanban_lanes_domain as
enum (
new_lane,
backlog,
doing,
review,
done
);
alter table kanban_board modify lane domain kanban_lanes_domain;
column story format A20
select id, story, domain_display(lane) as lane from kanban_board;
ID STORY LANE
---------- -------------------- --------
1 Do something BACKLOG
SQL>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
select email from t1 order by email;
EMAIL
--------------------------------------------------------------------------------
[email protected]
[email protected]
SQL>
select domain_display(email) from t1 order by email;
DOMAIN_DISPLAY(EMAIL)
--------------------------------------------------------------------------------
[email protected]
[email protected]
SQL>
select email from t1 order by domain_order(email);
EMAIL
--------------------------------------------------------------------------------
[email protected]
[email protected]
SQL>
select domain_name(email) from t1 where rownum = 1;
DOMAIN_NAME(EMAIL)
----------------------------------------
TESTUSER1.EMAIL_DOM
SQL>
select cast('[email protected]' as domain email_dom);
CAST('[email protected]'ASDOMAINEMAIL_DOM)
----------------------------------------------------------------------------------------------------
[email protected]
SQL>
select domain_check(email_dom, '[email protected]');
DOMAIN_CHEC
-----------
TRUE
SQL>
select domain_check(email_dom, 'grape');
DOMAIN_CHEC
-----------
FALSE
SQL>
select domain_check_type(email_dom, '[email protected]');
DOMAIN_CHEC
-----------
TRUE
SQL>
select domain_check_type(email_dom, 'grape');
DOMAIN_CHEC
-----------
TRUE
SQL>12345678910111213141516171819202122232425262728
-- Display
alter domain email_dom
add display lower(email_dom);
alter domain email_dom
modify display upper(email_dom);
alter domain email_dom
drop display;
-- Order
alter domain email_dom
add order lower(email_dom);
alter domain email_dom
modify order upper(email_dom);
alter domain email_dom
drop order;
-- Annotation
alter domain email_dom
annotations (Usage 'Use this for email columns.');
alter domain email_dom
annotations (drop Usage);12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
drop domain email_dom;
*
ERROR at line 1:
ORA-11502: The domain to be dropped has dependent objects.
SQL>
column constraint_name format a20
column search_condition format a50
select constraint_name, constraint_type, search_condition
from user_constraints
where table_name = 'T1';
CONSTRAINT_NAME C SEARCH_CONDITION
-------------------- - --------------------------------------------------
SYS_C0012349 C REGEXP_LIKE ("EMAIL",'^(\S+)\@(\S+)\.(\S+)$')
SQL>
drop domain email_dom force;
Domain dropped.
SQL>
select constraint_name, constraint_type, search_condition
from user_constraints
where table_name = 'T1';
no rows selected
SQL>
desc t1
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
EMAIL VARCHAR2(100)
SQL>
-- Recreate the test domain and table.
drop table t1 purge;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'));
create table t1 (
id number,
email domain email_dom
);
-- Check the constraints.
select constraint_name, constraint_type, search_condition
from user_constraints
where table_name = 'T1';
CONSTRAINT_NAME C SEARCH_CONDITION
-------------------- - --------------------------------------------------
SYS_C0012351 C REGEXP_LIKE ("EMAIL",'^(\S+)\@(\S+)\.(\S+)$')
SQL>
-- Drop the domain with FORCE PRESERVE option.
drop domain email_dom force preserve;
-- Check the constraints.
select constraint_name, constraint_type, search_condition
from user_constraints
where table_name = 'T1';
CONSTRAINT_NAME C SEARCH_CONDITION
-------------------- - --------------------------------------------------
SYS_C0012351 C REGEXP_LIKE ("EMAIL",'^(\S+)\@(\S+)\.(\S+)$')
SQL>12345678910111213141516171819202122232425262728293031323334353637383940414243444546
drop table if exists t1 purge;
drop domain if exists email_dom;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'));
create table t1 (
id number,
email domain email_dom
);
column table_name format a30
column column_name format a30
select table_name, column_name
from user_tab_columns
where domain_name = 'EMAIL_DOM';
TABLE_NAME COLUMN_NAME
------------------------------ ------------------------------
T1 EMAIL
SQL>
drop domain email_dom force preserve;
create domain email_dom as varchar2(200)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'));
alter table t1 modify email domain email_dom;
*
ERROR at line 1:
ORA-11517: the column data type does not match the domain column
SQL>
alter table t1 modify email varchar2(200);
alter table t1 modify email domain email_dom;
desc t1
Name Null? Type
----------------------------------------- -------- ---------------------------------
ID NUMBER
EMAIL VARCHAR2(200) TESTUSER1.EMAIL_DOM
SQL>1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
column object_name format A20
column object_type format A20
select object_name, object_type
from user_objects
order by 1;
OBJECT_NAME OBJECT_TYPE
-------------------- --------------------
EMAIL_DOM DOMAIN
T1 TABLE
SQL>
column column_name format A20
column domain_owner format A20
column domain_name format A20
select column_id,
column_name,
domain_owner,
domain_name
from user_tab_columns
where table_name = 'T1'
order by 1;
COLUMN_ID COLUMN_NAME DOMAIN_OWNER DOMAIN_NAME
---------- -------------------- -------------------- --------------------
1 ID
2 EMAIL TESTUSER1 EMAIL_DOM
SQL>
SQL> desc user_domains
Name Null? Type
----------------------------------------------------- -------- ------------------------------------
OWNER NOT NULL VARCHAR2(128)
NAME NOT NULL VARCHAR2(128)
COLS NOT NULL NUMBER
DISCRIMINANTCOLS NUMBER
FLAGS NUMBER
BUILTIN VARCHAR2(3)
DATA_DISPLAY CLOB
DISPLAY_LENGTH NUMBER
DATA_ORDER CLOB
ORDER_LENGTH NUMBER
SELECTOR CLOB
SELECTOR_LENGTH NUMBER
SQL>
SQL> desc user_domain_cols;
Name Null? Type
----------------------------------------------------- -------- ------------------------------------
OWNER NOT NULL VARCHAR2(128)
DOMAIN_NAME NOT NULL VARCHAR2(128)
COLUMN_NAME NOT NULL VARCHAR2(128)
COLUMN_ID NOT NULL NUMBER
DATA_TYPE_ID NOT NULL NUMBER
DATA_TYPE VARCHAR2(106)
DATA_LENGTH NUMBER
DATA_PRECISION NUMBER
DATA_SCALE NUMBER
NULLABLE VARCHAR2(1)
DATA_DEFAULT CLOB
DEFAULT_LENGTH NUMBER
DEFAULT_ON_NULL VARCHAR2(3)
DEFAULT_ON_NULL_UPD VARCHAR2(3)
CHARACTER_SET_NAME VARCHAR2(44)
CHAR_COL_DECL_LENGTH NUMBER
COLLATION VARCHAR2(100)
EXACT VARCHAR2(3)
CHAR_LENGTH NUMBER
DISCRIMINANT VARCHAR2(3)
SQL>
SQL> desc user_domain_constraints
Name Null? Type
----------------------------------------------------- -------- ------------------------------------
NAME NOT NULL VARCHAR2(128)
DOMAIN_OWNER NOT NULL VARCHAR2(128)
DOMAIN_NAME NOT NULL VARCHAR2(128)
CONSTRAINT_TYPE VARCHAR2(1)
SEARCH_CONDITION CLOB
STATUS VARCHAR2(8)
DEFERRABLE VARCHAR2(14)
DEFERRED VARCHAR2(9)
VALIDATED VARCHAR2(13)
GENERATED VARCHAR2(14)
BAD VARCHAR2(3)
RELY VARCHAR2(4)
INVALID VARCHAR2(7)
ORIGIN_CON_ID NUMBER
SQL>123456789101112131415161718192021222324252627282930313233343536373839
drop table t1 purge;
drop domain email_dom;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'));
create table t1 (
id number,
email domain email_dom
);
declare
l_email domain email_dom;
begin
null;
end;
/
l_email domain email_dom;
*
ERROR at line 2:
ORA-06550: line 2, column 18:
PLS-00103: Encountered the symbol "EMAIL_DOM" when expecting one of the following:
:= . ( @ % ; not null range default character
The symbol ":=" was substituted for "EMAIL_DOM" to continue.
SQL>
declare
l_email t1.email%type;
begin
l_email := '[email protected]';
l_email := 'banana';
end;
/
PL/SQL procedure successfully completed.
SQL>1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
drop table if exists t1 purge;
drop domain if exists email_dom;
create domain email_dom as varchar2(100)
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'));
create table t1 (
col1 varchar2(50),
col2 varchar2(100),
col3 varchar2(200)
);
alter table t1 modify col1 domain email_dom;
*
ERROR at line 1:
ORA-11517: the column data type does not match the domain column
SQL>
alter table t1 modify col2 domain email_dom;
Table altered.
SQL>
alter table t1 modify col3 domain email_dom;
Table altered.
SQL>
drop table if exists t1 purge;
drop domain if exists email_dom;
create domain email_dom as varchar2(100) strict
constraint email_chk check (regexp_like (email_dom, '^(\S+)\@(\S+)\.(\S+)$'));
create table t1 (
col1 varchar2(50),
col2 varchar2(100),
col3 varchar2(200)
);
alter table t1 modify col1 domain email_dom;
*
ERROR at line 1:
ORA-11517: the column data type does not match the domain column
SQL>
alter table t1 modify col2 domain email_dom;
Table altered.
SQL>
alter table t1 modify col3 domain email_dom;
*
ERROR at line 1:
ORA-11517: the column data type does not match the domain column
SQL>Please to add comments
No comments yet. Be the first to comment!