create table invoices (
invoice_id integer not null
constraint invoice_pk primary key,
customer_id integer not null,
invoice_datetime timestamp not null,
status varchar2(10) not null,
constraint inv_status_c check (
status in ( 'NEW', 'PAID', 'CANCELLED', 'REFUNDED' )
)
)
Table created.
create table invoice_items (
invoice_id
constraint init_invoice_fk
references invoices
not null,
item_number integer not null,
product_id integer not null,
order_id integer not null,
quantity integer not null,
unit_price number not null,
constraint invoice_items_pk
primary key ( invoice_id, item_number ),
constraint inv_order_product_u
unique ( order_id, product_id ),
constraint init_qty_gt_zero_c
check ( quantity > 0 )
)
Table created.
insert into invoices
values ( 1, 1, timestamp'2023-01-01 00:00:00', 'NEW' )
1 row(s) inserted.
commit
Statement processed.
Add new, unvalidated constraint
alter table invoices
add constraint inv_status_c_new
check (
status in ( 'NEW', 'PAID', 'CANCELLED', 'REFUNDED', 'VOID' )
)
novalidate
Table altered.
select constraint_name, validated, search_condition
from user_constraints
where table_name = 'INVOICES'
and constraint_type = 'C'
CONSTRAINT_NAME | VALIDATED | SEARCH_CONDITION |
---|---|---|
INV_STATUS_C | VALIDATED | status in ( 'NEW', 'PAID', 'CANCELLED', 'REFUNDED' ) |
INV_STATUS_C_NEW | NOT VALIDATED | status in ( 'NEW', 'PAID', 'CANCELLED', 'REFUNDED', 'VOID' ) |
SYS_C00128236024 | VALIDATED | "INVOICE_ID" IS NOT NULL |
SYS_C00128236025 | VALIDATED | "CUSTOMER_ID" IS NOT NULL |
SYS_C00128236026 | VALIDATED | "INVOICE_DATETIME" IS NOT NULL |
SYS_C00128236027 | VALIDATED | "STATUS" IS NOT NULL |
Validate new constraint
alter table invoices
modify constraint inv_status_c_new
validate
Table altered.
select constraint_name, validated, search_condition
from user_constraints
where table_name = 'INVOICES'
and constraint_type = 'C'
CONSTRAINT_NAME | VALIDATED | SEARCH_CONDITION |
---|---|---|
INV_STATUS_C | VALIDATED | status in ( 'NEW', 'PAID', 'CANCELLED', 'REFUNDED' ) |
INV_STATUS_C_NEW | VALIDATED | status in ( 'NEW', 'PAID', 'CANCELLED', 'REFUNDED', 'VOID' ) |
SYS_C00128236024 | VALIDATED | "INVOICE_ID" IS NOT NULL |
SYS_C00128236025 | VALIDATED | "CUSTOMER_ID" IS NOT NULL |
SYS_C00128236026 | VALIDATED | "INVOICE_DATETIME" IS NOT NULL |
SYS_C00128236027 | VALIDATED | "STATUS" IS NOT NULL |
Remove the old constraint
alter table invoices
drop constraint inv_status_c
online
Table altered.
Change constraint name
alter table invoices
rename constraint inv_status_c_new
to inv_status_c
Table altered.
View the NOT NULL constraints
select constraint_name, column_name
from user_constraints
join user_cons_columns
using ( table_name, constraint_name )
where table_name = 'INVOICES'
and search_condition_vc like '%NOT NULL%'
CONSTRAINT_NAME | COLUMN_NAME |
---|---|
SYS_C00128236024 | INVOICE_ID |
SYS_C00128236025 | CUSTOMER_ID |
SYS_C00128236026 | INVOICE_DATETIME |
SYS_C00128236027 | STATUS |
Make a column optional
declare
stmt clob;
constraint_name varchar2(ora_max_name_len);
begin
select constraint_name
into constraint_name
from user_constraints
join user_cons_columns
using ( table_name, constraint_name )
where table_name = 'INVOICES'
and search_condition_vc like '%NOT NULL%'
and column_name = 'STATUS';
stmt := 'alter table invoices
drop constraint ' || constraint_name || '
online';
execute immediate stmt;
end;
Table dropped.
Make a column mandatory
alter table invoices
modify status
constraint inv_status_nn
not null
novalidate
Table altered.
Validate NOT NULL
alter table invoices
modify constraint inv_status_nn
validate
Table altered.
Add columns to a unique constraint
create unique index inv_order_product_inv_ui
on invoice_items ( order_id, product_id, invoice_id )
online
Index created.
Add unique constraint using index
alter table invoice_items
add constraint inv_order_product_inv_u
unique ( order_id, product_id, invoice_id )
using index inv_order_product_inv_ui
novalidate
Table altered.
Validate unique constraint
alter table invoice_items
modify constraint inv_order_product_u
validate
Table altered.
Remove old unique constraint
alter table invoice_items
drop constraint inv_order_product_u
online
Table altered.
Changing primary key
alter table invoices
drop primary key
ORA-02273: this unique/primary key is referenced by some foreign keysMore Details: https://docs.oracle.com/error-help/db/ora-02273
select * from user_constraints
where r_constraint_name = 'INVOICE_PK'
OWNER | CONSTRAINT_NAME | CONSTRAINT_TYPE | TABLE_NAME | SEARCH_CONDITION | SEARCH_CONDITION_VC | R_OWNER | R_CONSTRAINT_NAME | DELETE_RULE | STATUS | DEFERRABLE | DEFERRED | VALIDATED | GENERATED | BAD | RELY | LAST_CHANGE | INDEX_OWNER | INDEX_NAME | INVALID | VIEW_RELATED | ORIGIN_CON_ID |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SQL_XSIYZTLIUNRUVDYIMDLSKNBOC | INIT_INVOICE_FK | R | INVOICE_ITEMS | - | - | SQL_XSIYZTLIUNRUVDYIMDLSKNBOC | INVOICE_PK | NO ACTION | ENABLED | NOT DEFERRABLE | IMMEDIATE | VALIDATED | USER NAME | - | - | 13-JUL-23 | - | - | - | - | 3 |
Force primary key removal
alter table invoices
drop primary key
cascade
keep index
Table altered.
select index_name, uniqueness
from user_indexes
where table_name = 'INVOICES'
INDEX_NAME | UNIQUENESS |
---|---|
INVOICE_PK | UNIQUE |
Add unique constraint using old primary key index
alter table invoices
add unique ( invoice_id )
using index invoice_pk
novalidate
Table altered.
Recreate foreign key
alter table invoice_items
add constraint inv_cust_date_fk
foreign key ( invoice_id )
references invoices ( invoice_id )
on delete cascade
deferrable
Table altered.
Can't have duplicate foreign keys
alter table invoice_items
add constraint inv_cust_date_fk
foreign key ( invoice_id )
references invoices ( invoice_id )
ORA-02275: such a referential constraint already exists in the tableMore Details: https://docs.oracle.com/error-help/db/ora-02275
Duplicate check constraints
alter table invoice_items
add constraint init_qty_gt_zero_c_copy
check ( quantity > 0 )
Table altered.
select constraint_name, search_condition_vc
from user_constraints
where table_name = 'INVOICE_ITEMS'
CONSTRAINT_NAME | SEARCH_CONDITION_VC |
---|---|
INV_ORDER_PRODUCT_INV_U | - |
INV_CUST_DATE_FK | - |
SYS_C00128236030 | "INVOICE_ID" IS NOT NULL |
SYS_C00128236031 | "ITEM_NUMBER" IS NOT NULL |
SYS_C00128236032 | "PRODUCT_ID" IS NOT NULL |
SYS_C00128236033 | "ORDER_ID" IS NOT NULL |
SYS_C00128236034 | "QUANTITY" IS NOT NULL |
SYS_C00128236035 | "UNIT_PRICE" IS NOT NULL |
INIT_QTY_GT_ZERO_C | quantity > 0 |
INVOICE_ITEMS_PK | - |
INIT_QTY_GT_ZERO_C_COPY | quantity > 0 |
Temporary table for redefinition
create table invoice_items_tmp (
invoice_id
constraint init_invoice_fk_tmp
references invoices ( invoice_id )
not null,
item_number integer not null,
product_id integer not null,
order_id integer not null,
quantity integer not null,
unit_price number not null,
constraint invoice_items_pk_tmp
primary key ( invoice_id, item_number ),
constraint inv_order_product_u_tmp
unique ( order_id, product_id ),
constraint init_qty_gt_zero_c_tmp
check ( quantity > 0 )
)
Table created.
select table_name, constraint_name, constraint_type, delete_rule, deferrable
from user_constraints
where table_name like 'INVOICE_ITEMS%'
and constraint_type = 'R'
TABLE_NAME | CONSTRAINT_NAME | CONSTRAINT_TYPE | DELETE_RULE | DEFERRABLE |
---|---|---|---|---|
INVOICE_ITEMS_TMP | INIT_INVOICE_FK_TMP | R | NO ACTION | NOT DEFERRABLE |
INVOICE_ITEMS | INV_CUST_DATE_FK | R | CASCADE | DEFERRABLE |
Redefine the constraints online
declare
l_num_errors pls_integer;
begin
dbms_redefinition.can_redef_table(SYS_CONTEXT('userenv','current_schema'), 'invoice_items');
dbms_redefinition.start_redef_table(SYS_CONTEXT('userenv','current_schema'), 'invoice_items', 'invoice_items_tmp');
/* Comment back in to copy grants & triggers if necessary
dbms_redefinition.copy_table_dependents(
uname => SYS_CONTEXT('userenv','current_schema'),
orig_table => 'INVOICE_ITEMS',
int_table => 'INVOICE_ITEMS_TMP',
copy_indexes => 0,
copy_constraints => false,
ignore_errors => true,
num_errors => l_num_errors);
*/
if l_num_errors > 0 then
dbms_redefinition.abort_redef_table(SYS_CONTEXT('userenv','current_schema'), 'invoice_items', 'invoice_items_tmp');
raise_application_error ( -20001, 'Redef problem' );
else
dbms_redefinition.sync_interim_table(SYS_CONTEXT('userenv','current_schema'), 'invoice_items', 'invoice_items_tmp');
dbms_redefinition.finish_redef_table(SYS_CONTEXT('userenv','current_schema'), 'invoice_items', 'invoice_items_tmp');
end if;
end;
Statement processed.
select table_name, constraint_name, constraint_type, delete_rule, deferrable
from user_constraints
where table_name like 'INVOICE_ITEMS%'
and constraint_type = 'R'
TABLE_NAME | CONSTRAINT_NAME | CONSTRAINT_TYPE | DELETE_RULE | DEFERRABLE |
---|---|---|---|---|
INVOICE_ITEMS | INIT_INVOICE_FK_TMP | R | NO ACTION | NOT DEFERRABLE |
INVOICE_ITEMS_TMP | INV_CUST_DATE_FK | R | CASCADE | DEFERRABLE |