I have 3 tables, and would like to create a new table which has 3 columns which are foreign keys to the other 3 tables ids.
CREATE TABLE tableABC(
tblA INTEGER REFERENCES tableA,
tblB INTEGER REFERENCES tableB,
tblC INTEGER REFERENCES tableC,
newColumn Integer,
PRIMARY KEY (tblA, tblB, tblC) ----- Is this efficient ?
);
CREATE TABLE tableA(
tableA_id SERIAL PRIMARY KEY
);
CREATE TABLE tableB(
tableB_id SERIAL PRIMARY KEY
);
CREATE TABLE tableC(
tableC_id SERIAL PRIMARY KEY
);
Now for table tableABC I would like the column pair (tblA, tblB, tblC) to be unique. When querying this table, search will be based on those three columns. Which way would be most efficient.
I did some search and could not find a way to have foreign key constraint on 3 columns from 3 different tables.
For example FOREIGN KEY (b, c) REFERENCES other_table (c1, c2) references one table. Is it possible to reference 3 different tables.
Tnx.
Related
I have two tables that have a junction table in between due to fact that there is many to many relationship between. How do I make a foreign key reference from one of the tables to the junction table to obtain a specific ID(the primary key ID of the opposite table), the ID is part of the primary key of the junction table that is made up of two foreign keys of the two tables. I made a foreign key reference straight to the junction table but its throwing an error "The number of columns in the referencing column list for foreign key does not match those of the primary key in the referenced table" when launching the CREATE query for the tables. What should I do to successfully make a foreign key reference to junction table?
The many side of both relationships will be at the junction table eg (written in SQL)
create table t1 (
id int primary key
) ;
create table t2 (
id int primary key
) ;
create table junction (
t1id int references t1( id ) not null
, t2id int references t2( id ) not null
) ;
-- PK: 2 columns
alter table junction
add constraint pkey_j primary key( t1id, t2id ) ;
DBfiddle here.
i have 3 tables, 2 tables have a primary key and 1 table have a foreign key
this is the example
TABLE 1
--------
Id1 INT PRIMARY KEY
Name
TABLE 2
-------
Id2 INT PRIMARY KEY
Name
TABLE 3
-------
Id (Foreign key Table 1 & Table 2)
The problem is when i insert some id in table 3 exist in table 1 and not exist in table 2 she give me error please some help ?
You can define a column to have a foreign key relationship to two different tables:
constraint fk_table3_table1_name foreign key (name) references table1(name)
constraint fk_table3_table23_name foreign key (name) references table2(name)
However, that would require tha tthe name be in both the base tables. So, in practice, tables are never really defined this way.
It sounds like you have a data modeling issue. But you have not provided enough information in the question to provide a better answer. One possibility is two columns and a generated column and check constraint:
create table table3 . . .
name1 varchar(255),
name2 varchar(255),
name as (coalesce(name1, name2)),
check (name1 is null or name2 is null), -- at least one doesn't have a value
constraint fk_table3_table1_name foreign key (name1) references table1(name)
constraint fk_table3_table23_name foreign key (name2) references table2(name)
Note: You also should not be using a string as a foreign key. Number ids (ints) are a better choice.
I have 2 tables both with primary ids:
CREATE TABLE Table1
( Id INT NOT NULL AUTO_INCREMENT,
CONSTRAINT t1_pkey PRIMARY KEY (Id));
CREATE TABLE Table2
( Id INT NOT NULL AUTO_INCREMENT,
CONSTRAINT t2_pkey PRIMARY KEY (Id));
I have a third table which I am trying to setup a foreign key
CREATE TABLE Action
( TableId INT NOT NULL AUTO_INCREMENT,
CONSTRAINT ac_pkey PRIMARY KEY (Id));
I need to add a foreign key that can reference either table1 or table2 depending on which one has value. Is this possible or am I going to have to setup a parent table for tables 1 and 2?
It is not possible for a foreign key to reference one table or the other.
You could combine table1 and table2 with a type column and then have the combination of id, type be the primary key of the combined table and the foreign key in Action.
You could create a new table that is a parent of both table1 and table2 as well as Action
You could create two separate columns in Action, on that references table1 and the other that references table2 and then create a check constraint that ensures that only one of those is populated.
Which approach you prefer will come down to exactly what you're trying to model.
I have 3 tables: A, B, C.
The table A contains the attributes: a (primary key)
The table B contains the attributes: a, c (both of them compose a composite primary key)
The table C contains the attributes: c (primary key)
How should I set a constraint to remove the elements of B on cascade, when I remove an entry in A? (using Oracle DBMS).
I have tried this:
ALTER TABLE A ADD CONSTRAINT constraint FOREIGN KEY (a) REFERENCES B (a) ON DELETE CASCADE
But next error is thrown:
ORA-02270: no matching unique or primary key for this column-list
Thanks
Edited:
I´ve added two foreign keys to the table B:
ALTER TABLE B ADD CONSTRAINT FOREIGN KEY (a) REFERENCES A (a) ON DELETE CASCADE
ALTER TABLE B ADD CONSTRAINT FOREIGN KEY (c) REFERENCES C (c) ON DELETE CASCADE
Then, I will remove elements in table B, and the entries in A and C are also removed.
To meet this requirement:
Then, I will remove elements in table B, and the entries in A and C are also removed.
You need to make the B table a parent table for tables A and C by a adding foreign key constraint, that references B table to A and C tables.
Note that the number of referencing columns have to match the number of referenced columns:
create table A(
tab_id number primary key
);
create table B(
col1 number,
col2 number,
constraint PK_Key primary key(col1, col2)
);
create table C(
tab_id number primary key
);
alter table A add ( col1 number
, col2 number
, constraint fk_AB foreign key(col1, col2)
references B(col1, col2) on delete cascade);
alter table C add ( col1 number
, col2 number
, constraint fk_CB foreign key(col1, col2)
references B(col1, col2) on delete cascade);
This is a bit of a guess, but I am assuming table B is a child of of both A and C (perhaps B is a bridging (or cross-reference) table between A and C, where A and C share a many to many relationship).
Table A \*---1 Table B 1---\* Table C (* = many, 1 = one)
I also notice that the FK you are introducing in an identifying FK (by virtue of B(a) being a part of B's primary key).
That makes Table A the parent in this relationship, and B the child. In my experience, any FKs need to be added to the child side of the relationship (in this case, table B).
I'm no Oracle expert, but does this not make more sense?...
ALTER TABLE B ADD CONSTRAINT constraint FOREIGN KEY (a) REFERENCES A (a) ON DELETE CASCADE
This should remove all B rows referring to the PK of any A rows you choose to remove. BUT, I'm not an Oracle expert, so take only at face value until someone with Oracle smarts can confirm (or bomb) my explanation.
Take the following two tables in Oracle:
Create Table A
( A int, B int, C int,
Constraint pk_ab Primary Key(A, B),
Unique (C)
);
Create Table B
( D int, E int, F int,
Constraint fk_d Foreign Key (D) References A(A),
Constraint fk_e Foreign Key (E) References A(B)
);
Why doesn't this statement work? Or more specifically, why shouldn't it work? The reason I'm trying to create this type of relation is say, in the future, I want to delete B.D, but keep the relation FK_E.
I'm getting the error:
ORA-02270: no matching unique or primary key for this column-list
"Why doesn't this statement work? Or more specifically, why shouldn't
it work? "
You have defined the primary key on A as a compound of two columns (A,B). Any foreign key which references PK_AB must match those columns in number. This is because a foreign key must identify a single row in the referenced table which owns any given row in the child table. The compound primary key means column A.A can contain duplicate values and so can column A.B; only the permutations of (A,B) are unique. Consequently the referencing foreign key needs two columns.
Create Table B
( D int, E int, F int,
Constraint fk_de Foreign Key (D,E) References A(A,B)
);
"Since there are multiple PK's that table B references"
Wrong. B references a single primary key, which happens to comprise more than one column,
" say, in the future, I want to delete B.D, but keep the relation
fk_e. "
That doesn't make sense. Think of it this way: D is not a property of B, it is an attribute B inherits through its dependence on table A.
One way to avoid this situation is to use a surrogate (or synthetic) key. Compound keys are often business keys, hence their columns are meaningful in a business context. One feature of meaningful column values is that they can change, and cascading such changes to foreign keys can be messy.
Implementing a surrogate key would look like this:
Create Table A
( id int not null, A int, B int, C int,
Constraint pk_a Primary Key(ID),
constraint uk_ab Unique (A,B)
);
Create Table B
( a_id int, F int,
Constraint fk_n_a Foreign Key (A_ID) References A(ID)
);
Of course, you could kind of do this using the schema you posted, as you already have a single column constraint on A(C). However, I think it is bad practice to reference unique constraints rather than primary keys, even though it's allowed. I think this partly because unique constraints often enforce a business key, hence meaning, hence the potential for change, but mainly because referencing primary keys just is the industry standard.
Try create two separate indexes for column's A and B before creating table B
CREATE INDEX a_idx ON A (A);
CREATE INDEX b_idx ON A (B);
But probably you need a compound FK on table B
Create Table B
( D int, E int, F int,
Constraint fk_d Foreign Key (D,E) References A(A,B)
);
A foreign key always references a PK of another table. Neither A nor B
alone are PK's.. You have multiple PK's.
Constraint fk_d Foreign Key (D,E) References A(A,B)
Also the database cannot validate a partial null multiple foreign key, so I think the check constraint also needs to be added to the table.
alter table B add constraint check_nullness
check ( ( D is not null and E is not null ) or
( D is null and E is null ) )