reference a compound key in Oracle - oracle

I want to add a foreign key which reference the column in itself
FOREIGN KEY ACCREDITATION_BODY_ID NOT NULL REFERENCES
ACCREDITATION_BODY_LOOK_UP(ACCREDITATION_BODY_ID),
and the SQL in the table is:
CREATE TABLE "COURSE_ACCREDITED"
("COURSE_ID" VARCHAR2(50) NOT NULL ENABLE,
"ACCREDITATION_BODY_ID" VARCHAR2(50) NOT NULL ENABLE,
"DATE_OBTAINED" VARCHAR2(50),
PRIMARY KEY ("COURSE_ID", "ACCREDITATION_BODY_ID", "DATE_OBTAINED") ENABLE)
When I add this foreign key, it appears ORA-02270: no matching unique or primary key for this column-list
What is the problem?

Does ACCREDITATION_BODY_LOOK_UP have primary key (or unique key)?
select constraint_name, constraint_type
from user_constraints
where table_name = 'ACCREDITATION_BODY_LOOK_UP'
and constraint_type in ('P', 'U');
If yes, what are its columns? You need to reference all those columns in the same order when you add a foreign key to a dependent table.
select column_name, position
from user_cons_columns
where table_name = 'ACCREDITATION_BODY_LOOK_UP'
and constraint_name = '<< constraint from previous query >>';
If no, then you need to create a primary key on that table before you can reference it in a foreign key.
alter table ACCREDITATION_BODY_LOOK_UP
add constraint ACCR_BODY_LKUP_PK primary key (ACCREDITATION_BODY_ID);

This means that the child table has values which are not found in the parent table.
You just need to delete these orphaned values or define the foreign key with "novalidate" which skips checking the integrity between the child and parent tables.
CORRECTION: THIS ADDRESS A DIFFERENT PK/FK ERROR
ORA-02270 is because you're trying to create a foreign key and the key is not referencing a primary key or column with a unique constraint.

Related

I'm trying to create foreign key between two tables but got: ORA-02270

Maybe I'm burnout, but I don't understand this. I have two tables in Oracle: TBL_a and TBL_x. I'm trying to create a foreign key between thos two tables as follows and get error
ORA-02270: no matching unique or primary key.
CREATE TABLE tbl_a (
cod_op integer,
cod_dni char(8),
cod_correl integer,
varchar2(50)
);
CREATE TABLE tbl_x (
cod_op integer,
cod_dni char(8),
blabla varchar2(50)
);
CREATE UNIQUE INDEX TBL_A_PK ON TBL_A (COD_OP);
CREATE UNIQUE INDEX TBL_x_PK ON TBL_x (COD_OP);
ALTER TABLE TBL_a ADD CONSTRAINT TBL_a_R01
FOREIGN KEY (COD_OP) REFERENCES TBL_x (COD_OP);
The problem is that you've created unique INDEXES on your tables, but you didn't create a unique or primary key CONSTRAINT. Oracle requires that the constraints exist in order to establish a foreign key relationship.
If you drop your existing indexes and add the appropriate constraints you can establish your foreign key relationship:
DROP INDEX TBL_A_PK;
DROP INDEX TBL_x_PK;
ALTER TABLE TBL_A
ADD CONSTRAINT UQ_A
UNIQUE(COD_OP)
USING INDEX;
ALTER TABLE TBL_X
ADD CONSTRAINT UQ_X
UNIQUE(COD_OP)
USING INDEX;
dbfiddle here
The table that is referred by the foreign key (here, tbl_x) must have a primary key or a unique constraint.
In your use case, as you are declaring a unique index on cod_op, you could simply make cod_op the primary key of tbl_x instead: that would make the error disappear.
Demo on DB Fiddle
In general, it is a good practice to have a primary key on any table. Extending the principe of turning your unique indexes to primary keys, your DDL statements could be simplified as follows:
CREATE TABLE tbl_x (
cod_op INTEGER PRIMARY KEY,
cod_dni CHAR(8),
blabla VARCHAR2(50)
);
CREATE TABLE tbl_a (
cod_op INTEGER PRIMARY KEY,
cod_dni CHAR(8),
cod_correl INTEGER,
blabla VARCHAR2(50),
CONSTRAINT TBL_a_R01 FOREIGN KEY (COD_OP) REFERENCES TBL_x (COD_OP)
);
Demo on DB Fiddle

Oracle foreign key constraints - check constraint syntax?

I have a child table in oracle that has two foreign key columns, relating to two different parent tables. I want to create a constraint that says the child must have at least one of those parents - e.g.
ALTER TABLE table_name
ADD CONSTRAINT constraint_name
FOREIGN KEY (column1)
REFERENCES parent_table (column1)
OR
FOREIGN KEY (column2)
REFERENCES parent_table_2 (column1)
This won't work with a foreign key constraint because that can only relate to one parent table - is it possible to do this with a check constraint instead?
Foreign key constraints ensure the referential integrity, not mandatory values.
I think you have to have to separate FK contraints and additional check constraint like this:
alter table table_name
add constraint c_check_cols
check(column1 is not null or column2 is not null);
You can do it with constraints:
ALTER TABLE table_name
ADD CONSTRAINT constraint_name_1
FOREIGN KEY (column1)
REFERENCES parent_table (column1);
ALTER TABLE table_name
ADD CONSTRAINT constraint_name_2
FOREIGN KEY (column2)
REFERENCES parent_table_2 (column1);
ALTER TABLE table_name
ADD CONSTRAINT constraint_name_3
check (COALESCE(column1, column2) IS NOT NULL);
Of course for column1 and column2 column you must permit NULL values.

Oracle foreign key allow one extra specific value

I have one simple table:
-- Create table
create table FAVOURITE_RULES
( rule_id NUMBER(9) not null,
user_id NUMBER(9) not null);
-- Create/Recreate primary, unique and foreign key constraints
alter table FAVOURITE_RULES
add constraint FAV_RULES_PK primary key (RULE_ID, USER_ID)
alter table FAVOURITE_RULES
add constraint FAV_RULES_RULE_ID_FK foreign key (RULE_ID)
references RULES (RULE_ID) on delete cascade;
alter table FAVOURITE_RULES
add constraint FAV_RULES_USER_ID foreign key (USER_ID)
references USER_AUTHENTICATION (USER_ID) on delete cascade;
I have a rule (from .Net code) that doesn't exist in the original table RULES. It has the Id=-999.
When I try to insert into the FAVOURITE_RULES I get an error about integrity constraint violation (as expected) (FAV_RULES_RULE_ID_FK) violated - parent key not found.
Can I keep the foreign key (FAV_RULES_RULE_ID_FK ) and allow extra only this value (-999) to be inserted?
May be this can help.
Step 1: drop fk constraint
Step 2: insert your violating row
Step 3: again create fk constraint with ENABLE NOVALIDATE

Do I need to drop a foreign key on one table to delete a row on another using oracle?

I have two tables
Parent table
(account_number varchar(15) not null,
branch_name varchar(50) not null,
balance number not null,
primary key(account_number));
Child table
account_number varchar(15) not null,
foreign key(account_number) references parent table(account_number));
I am trying this:
DELETE FROM parent table
WHERE balances > 1000;
I am deleting accounts by balances on the parent but I get an error message about the child relationship.
My assumption is a DELETE CASCADE has to be added to the foreign key in the child table. All the documentation shows how to alter the table when the constraint is named. I do not have that situation. Is there a way to do it, or do I have to specify the cascade in the delete statement I am writing?
Every constraint in Oracle has a name. If a name isn't specified when the constraint is created, Oracle will autogenerate a name for the constraint. If you don't know what the name of a constraint is, try running a SQL statement that violates the constraint and reading the constraint name from the error message:
SQL> delete from parent where account_number = 1234;
delete from parent where account_number = 1234
*
ERROR at line 1:
ORA-02292: integrity constraint (LUKE.SYS_C007357) violated - child record
found
In this case the name of the constraint is SYS_C007357.
If that doesn't work, you can query the data dictionary view user_constraints:
SQL> select constraint_name from user_constraints where table_name = 'CHILD' and constraint_type = 'R';
CONSTRAINT_NAME
------------------------------
SYS_C007357
As far as I can tell, you can't modify a foreign key constraint to enable ON DELETE CASCADE. Instead you must drop the constraint and recreate it.
I don't believe you can apply the CASCADE option to a DELETE statement either, but you can delete the child rows before deleting from the parent:
DELETE FROM child
WHERE account_number IN (SELECT account_number FROM parent WHERE balance > 1000);
DELETE FROM parent
WHERE balance > 1000;
However, I don't know how many other tables you have with foreign key constraints referencing your parent table, nor in how many places you are deleting from the parent table, so I can't say how much work it would be to use this approach.
yes you can set DELETE CASCADE
see more info here FOREIGN KEYS WITH CASCADE DELETE
CREATE TABLE table_name
(
column1 datatype null/not null,
column2 datatype null/not null,
...
CONSTRAINT fk_column
FOREIGN KEY (column1, column2, ... column_n)
REFERENCES parent_table (column1, column2, ... column_n)
ON DELETE CASCADE
);
for example
CREATE TABLE supplier
( supplier_id numeric(10) not null,
supplier_name varchar2(50) not null,
contact_name varchar2(50),
CONSTRAINT supplier_pk PRIMARY KEY (supplier_id)
);
CREATE TABLE products
( product_id numeric(10) not null,
supplier_id numeric(10) not null,
CONSTRAINT fk_supplier
FOREIGN KEY (supplier_id)
REFERENCES supplier(supplier_id)
ON DELETE CASCADE
);

Oracle Constraint Check

I want to check if film.language_id refers to language.language_id.
I used the code:
SELECT *
FROM all_tab_columns
WHERE column_name = 'film.language';
Result:
no rows selected
Does this mean there are no references/referential constraints?
If you want to find out if a column refers to another column by foreign key constraint you can do the following:
Find out if the column is in a constraint:
select constraint_name from user_cons_columns
where table_name='<Your_table>'
and column_name='<Your_column>';
If it is this will give you the name of that constraint.
Next you can find out if that constraint is a foreign key constraint and where the foreign key points to:
select constraint_type
,r_constraint_name
from user_constraints
where constraint_name='<your constraint name>';
If the constraint is a foreign key constraint it is of type 'R'. This will also give you the name of the primary key constraint the foreign key relates to.
Given the name of the primary key constraint you can find the table and column(s) as follows:
select table_name
,column_name
from user_cons_columns
where constraint_name = 'Your PK constraint'
To make life easier you can join all these queries together. But I leave that to you.

Resources