Why does this error appear me on sql developer - sql

I create the table "Funcionario"
but then the tables "Viagem" and "Encomenda"
show me this error. I didn't understand why, can somebody help me? i can share all the script if you want to see all.
The error that appears is :
"ORA-02270: no matching unique or primary key for this column-list.
A REFERENCES clause in a CREATE/ALTER TABLE statement gives a
column-list for which there is no matching unique or primary key
constraint in the referenced table.
[EDIT] SCRIPT
-- Criar Tabela Zona Geografica
CREATE TABLE ZonaGeografica(
id_zona_geo INTEGER CONSTRAINT pk_ZonaGeografica_id_zona_geo PRIMARY KEY,
latitude INTEGER NOT NULL,
longitude INTEGER NOT NULL
);
-- Criar Tabela Armazem
CREATE TABLE Armazem(
cod_armazem INTEGER CONSTRAINT pk_Armazem_cod_armazem PRIMARY KEY,
id_zona_geo INTEGER NOT NULL,
nome VARCHAR(40) NOT NULL,
morada VARCHAR(50) NOT NULL,
CONSTRAINT fk_ZonaGeografica_id_zona_geo FOREIGN KEY (id_zona_geo) REFERENCES ZonaGeografica(id_zona_geo)
);
-- Criar Tabela TipoVeiculo
CREATE TABLE TipoVeiculo(
tipo_veiculo VARCHAR(20) CONSTRAINT pk_TipoVeiculo_tipo_veiculo PRIMARY KEY,
capacidade_volume INTEGER NOT NULL,
capacidade_peso INTEGER NOT NULL
);
-- Criar Tabela Veiculo
CREATE TABLE Veiculo(
cod_veiculo INTEGER NOT NULL,
tipo_veiculo VARCHAR(20) NOT NULL,
matricula VARCHAR(8) NOT NULL,
marca VARCHAR(20) NOT NULL,
modelo VARCHAR(5) NOT NULL,
nr_apolice INTEGER NOT NULL,
nr_quilometros INTEGER NOT NULL,
CONSTRAINT pk_Veiculo_cod_veiculo_tipo_veiculo PRIMARY KEY(cod_veiculo, tipo_veiculo),
CONSTRAINT fk_Veiculo_tipo_veiculo FOREIGN KEY (tipo_veiculo) REFERENCES TipoVeiculo(tipo_veiculo),
CONSTRAINT ck_Veiculo_matricula CHECK(REGEXP_LIKE(matricula ,'[0-9]{2}-[A-Z]{2}-[0-9]{2}|[0-9]{2}-[0-9]{2}-[A-Z]{2}|[A-Z]{2}-[0-9]{2}-[0-9]{2}'))
);
-- Criar Tabela Funcionario
CREATE TABLE Funcionario(
id_func INTEGER CONSTRAINT pk_Funcionario_id_func PRIMARY KEY,
id_tipo INTEGER NOT NULL,
cod_armazem INTEGER NOT NULL,
cod_supervisor INTEGER NOT NULL,
cc INTEGER NOT NULL CONSTRAINT ck_Funcionario_cc CHECK(REGEXP_LIKE(cc ,'[0-9]{8}-[0-9]{1}-[A-Z]{2}[0-9]{1}')),
nome_func VARCHAR(40) NOT NULL,
morada_func VARCHAR(40) NOT NULL,
nif_func INTEGER NOT NULL UNIQUE CONSTRAINT ck_Funcionario_nif_func CHECK(REGEXP_LIKE(nif_func ,'[0-9]{7}')),
salario_mensal NUMERIC(*,2) NOT NULL,
CONSTRAINT fk_Funcionario_id_tipo FOREIGN KEY (id_tipo) REFERENCES Categoria(id_tipo),
CONSTRAINT fk_Funcionario_cod_armazem FOREIGN KEY (cod_armazem) REFERENCES Armazem(cod_armazem),
CONSTRAINT fk_Funcionario_cod_supervisor FOREIGN KEY (cod_supervisor) REFERENCES Funcionario(id_func)
);
-- Criar Tabela Categoria
CREATE TABLE Categoria(
id_tipo INTEGER CONSTRAINT pk_Categoria_id_tipo PRIMARY KEY,
tipo VARCHAR(20) NOT NULL
);
-- Criar Tabela Viagem
CREATE TABLE Viagem(
nr_viagem INTEGER CONSTRAINT pk_Viagem_nr_viagem PRIMARY KEY,
id_tipo INTEGER NOT NULL,
id_func INTEGER NOT NULL,
cod_veiculo INTEGER NOT NULL,
tipo_veiculo VARCHAR(20) NOT NULL,
data_partida DATE NOT NULL,
CONSTRAINT fk_Viagem_id_tipo FOREIGN KEY (id_tipo) REFERENCES Categoria(id_tipo),
CONSTRAINT fk_Viagem_id_func FOREIGN KEY (id_func) REFERENCES Funcionario(id_func),
CONSTRAINT fk_Viagem_cod_veiculo FOREIGN KEY (cod_veiculo) REFERENCES Veiculo(cod_veiculo),
CONSTRAINT fk_Viagem_tipo_veiculo FOREIGN KEY (tipo_veiculo) REFERENCES TipoVeiculo(tipo_veiculo)
);
-- Criar Tabela Encomenda
CREATE TABLE Encomenda(
id_encomenda INTEGER CONSTRAINT pk_Encomenda_id_encomenda PRIMARY KEY,
cod_armazem INTEGER NOT NULL,
cod_veiculo INTEGER NOT NULL,
nr_viagem INTEGER NOT NULL,
CONSTRAINT fk_Encomenda_nr_viagem FOREIGN KEY (nr_viagem) REFERENCES Viagem(nr_viagem),
id_func INTEGER NOT NULL,
CONSTRAINT fk_Encomenda_cod_armazem FOREIGN KEY (cod_armazem) REFERENCES Armazem(cod_armazem),
CONSTRAINT fk_Encomenda_cod_veiculo FOREIGN KEY (cod_veiculo) REFERENCES Veiculo(cod_veiculo),
CONSTRAINT fk_Encomenda_id_func FOREIGN KEY (id_func) REFERENCES Funcionario(id_func)
);

Here's what's wrong
CONSTRAINT fk_Viagem_cod_veiculo FOREIGN KEY (cod_veiculo) REFERENCES Veiculo(cod_veiculo)
For table Viagem you have this FOREIGN KEY which is referring to only a part of the composite PRIMARY KEY in Veiculo (cod_veiculo, tipo_veiculo)
same with this for Encomenda
CONSTRAINT fk_Encomenda_cod_veiculo FOREIGN KEY(cod_veiculo) REFERENCES Veiculo(cod_veiculo)
Fix your design such that a FOREIGN KEY combination matches with a UNIQUE KEY/PRIMARY KEY in the referenced tables.

The error message is fairly clear (or at least better than some); you have a foreign key which tries to reference column(s) that don't form a unique or primary key in the parent table.
In Viagem you have:
CONSTRAINT fk_Viagem_cod_veiculo FOREIGN KEY (cod_veiculo) REFERENCES Veiculo(cod_veiculo),
but the primary key in Veiculo is the combination of two columns:
CONSTRAINT pk_Veiculo_cod_veiculo_tipo_veiculo PRIMARY KEY(cod_veiculo, tipo_veiculo),
You can't reference a single column from that key, as that single column won't be unique on its own, leading to ambiguity. So the obvious (but probably wrong) fix is to change Viagem to reference both columns:
CONSTRAINT fk_Viagem_cod_veiculo FOREIGN KEY (cod_veiculo, tipo_veiculo)
REFERENCES Veiculo(cod_veiculo, tipo_veiculo),
(If you did that then wouldn't really need the fk_Viagem_tipo_veiculo constraint as well, since the tipo_veiculo is part of the FK to Veiculo, and that table already has its own FK to TipoVeiculo.)
But your Encomenda table has the same problem; you have:
CONSTRAINT fk_Encomenda_cod_veiculo FOREIGN KEY (cod_veiculo) REFERENCES Veiculo(cod_veiculo),
there too. But for that table you don't have the id_tipo column, so you can't include that in the FK.
Which points to the more likely solution, via a question - why does Veiculo include tipo_veiculo in its PK at all? It looks like the cod_veiculo should be unique on its own; in which case change that PK to just:
CONSTRAINT pk_Veiculo_cod_veiculo_tipo_veiculo PRIMARY KEY(cod_veiculo),
and leave both Viagem and Encomenda as you already had them, with all their Fk referencing a single column each. (Although you may want to consider whether Viagem actually needs the id_tipo column at all, since yuo can get that from Veiculo via the linked cod_veiculo...)
If you really want to keep that PK as it is then you would have to add a seperate unique key for just cod_veiculo, which would then satisfy fk_Encomenda_cod_veiculo - but that looks wrong.

Related

SQL set FOREIGN KEY to a non unique value throws error in sql developer

I have a N:M situation, but I can't use any of the 2 non unique values as a Foreign Key can anyone help?? Both Platform_Id and Station_Id can not be set as a foreign key in the Platform_Host table.
CREATE TABLE Repair_Platform
(
Platform_Id INT NOT NULL,
Station_Id INT NOT NULL,
Mechanic_Id INT NOT NULL UNIQUE,
Validation_Num INT NOT NULL,
CONSTRAINT Platform_fk1
FOREIGN KEY (Station_Id) REFERENCES Repair_Station (Station_Id),
CONSTRAINT Platform_fk2
FOREIGN KEY (Mechanic_Id) REFERENCES Engineer (Engineer_Id),
CONSTRAINT Platform_pk
PRIMARY KEY (Station_Id, Platform_Id)
);
CREATE TABLE Platform_Host
(
Station_Id INT NOT NULL,
Platform_Id INT NOT NULL,
Vehicle_Id VARCHAR(8) NOT NULL,
DateTime DATE NOT NULL,
CONSTRAINT Host_fk1
FOREIGN KEY (Station_Id) REFERENCES Repair_Platform (Station_Id),
CONSTRAINT Host_fk2
FOREIGN KEY (Vehicle_Id) REFERENCES Vehicle (License_Plate),
CONSTRAINT Host_fk3
FOREIGN KEY (Platform_Id) REFERENCES Repair_Platform (Platform_Id)
);
Error:
ORA-02270: no matching unique or primary key for this column-list
02270. 00000 - "no matching unique or primary key for this column-list"
*Cause: A REFERENCES clause in a CREATE/ALTER TABLE statement gives a column-list for which there is no matching unique or primary key constraint in the referenced table.
< *Action: Find the correct column names using the ALL_CONS_COLUMNS catalog view
You need to reference the whole primary key of Repair_Platform - like this:
CREATE TABLE Platform_Host
(
-- columns
-- constraints
CONSTRAINT Host_fk3
FOREIGN KEY (StationId, Platform_Id)
REFERENCES Repair_Platform (StationId, Platform_Id)
);
You cannot reference only parts of a primary key - it's an all or nothing deal.

create a foreign key on a primary key of another table

CREATE TABLE public.impiegato(
CF varchar NOT NULL,
codice_reparto int4 NOT NULL,
mansione varchar NULL,
CONSTRAINT impiegato_pkey PRIMARY KEY (CF),
CONSTRAINT impiegato_fkey FOREIGN KEY (codice_reparto) REFERENCES reparto(codice),
);
CREATE TABLE public.reparto(
codice int4 NOT NULL,
nome varchar NULL,
cf_responsabile varchar NULL,
nome_responsabile varchar NULL UNIQUE,
CONSTRAINT reparto_pkey PRIMARY KEY (codice),
CONSTRAINT reparto_cf_responsabile_fkey FOREIGN KEY (cf_responsabile) REFERENCES impiegato(CF)
);
When i run the sql code it tells me that the impiegato table doesn't exist. Can I run a foreign key on a primary key of another table?
The referenced table must exists when a foreign key is declared.
Since in your case the two tables reference each other, it's not possible to solve this by simply creating the right one first.
You have to create the first one (any of them) first without the foreign key constraint, create the second on and then add the foreign key constraint to the first one.
Something along the lines of:
CREATE TABLE public.impiegato
(cf varchar
NOT NULL,
codice_reparto int4
NOT NULL,
mansione varchar
NULL,
CONSTRAINT impiegato_pkey
PRIMARY KEY (cf));
CREATE TABLE public.reparto
(codice int4
NOT NULL,
nome varchar
NULL,
cf_responsabile varchar
NULL,
nome_responsabile varchar
NULL
UNIQUE,
CONSTRAINT reparto_pkey
PRIMARY KEY (codice),
CONSTRAINT reparto_cf_responsabile_fkey
FOREIGN KEY (cf_responsabile)
REFERENCES impiegato
(cf));
ALTER TABLE public.impiegato
ADD CONSTRAINT impiegato_fkey
FOREIGN KEY (codice_reparto)
REFERENCES reparto
(codice);
Unfortunately, you didn't tag your DBMS. From some details I guessed it might be Postgres and the code above hence is Postgres code. If you don't use Postgres, you might need to adapt the ALTER TABLE statement, they can differ between DBMS.

SQL: create table with composite referencing primary key, and foreign key

So I have the following ER diagram:
So Subthing is a generalization. Stuff is either made out of Metal or Wood, it can't be just a Subthing. Here's the create code:
CREATE TABLE Thing (
ThingID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE Subthing (
consists_of INTEGER REFERENCES Thing(ThingID),
SubthingID INTEGER NOT NULL,
PRIMARY KEY (SubthingID, consists_of)
);
CREATE TABLE Wood (
Wstuff VARCHAR(40) NOT NULL,
consists_of INTEGER NOT NULL,
SubthingID INTEGER NOT NULL,
FOREIGN KEY (SubthingID, consists_of) REFERENCES Subthing(SubthingID, consists_of),
PRIMARY KEY (SubthingID, consists_of)
);
CREATE TABLE Dust (
DustID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE Metal (
Mstuff VARCHAR(40) NOT NULL,
consists_of INTEGER NOT NULL,
SubthingID INTEGER NOT NULL,
requires INTEGER NOT NULL REFERENCES Dust(DustID),
FOREIGN KEY (SubthingID, consists_of) REFERENCES Subthing(SubthingID, consists_of),
PRIMARY KEY (SubthingID, consists_of)
);
What I want is for Metal to, at the same time, have a primary key which references (SubthingID, consists_of) and a foreign key with requires, referencing DustID. I can't declare it as a foreign key after the fact since (SubthingID, consists_of) is already a foreign key.
How could you solve this, other than making requires into a table?
Never mind, I was too stupid.
CREATE TABLE Metal (
Mstuff VARCHAR(40) NOT NULL,
consists_of INTEGER NOT NULL,
SubthingID INTEGER NOT NULL,
requires INTEGER NOT NULL,
FOREIGN KEY (requires) REFERENCES Dust(DustID),
FOREIGN KEY (SubthingID, consists_of) REFERENCES Subthing(SubthingID, consists_of),
PRIMARY KEY (SubthingID, consists_of)
);
Works just fine.

Oracle: Many to Many: Requires two Foreign Key Constraints?

Im very new to SQL and i tried to create a many to many relationship:
CREATE TABLE HOUSE_USER
(
USER_ID NUMBER(10) NOT NULL,
USER_EMAIL VARCHAR(255) NOT NULL,
USER_PASSWORD VARCHAR(255) NOT NULL,
CONSTRAINT USER_PK PRIMARY KEY(USER_ID),
CONSTRAINT PROFILE_FK FOREIGN KEY(PROFILE_ID) REFERENCES HOUSE_PROFILE(PROFILE_ID)
);
CREATE TABLE HOUSE_USER_GROUPE
(
USER_GROUPE_ID NUMBER(10) NOT NULL,
USER_GROUPE_NAME VARCHAR(255) NOT NULL,
CONSTRAINT USER_GROUPE_PK PRIMARY KEY(USER_GROUPE_ID)
);
CREATE TABLE HOUSE_USER_USER_GROUPE
(
USER_ID NUMBER(10) NOT NULL,
USER_GROUPE_ID NUMBER(10) NOT NULL,
CONSTRAINT USER_USER_GROUPE_PK PRIMARY KEY(USER_ID, USER_GROUPE_ID),
CONSTRAINT USER_FK FOREIGN KEY(USER_ID) REFERENCES HOUSE_USER(USER_ID),
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES HOUSE_USER_GROUPE(USER_GROUPE_ID)
);
I need to ask now if these two constraints:
CONSTRAINT USER_FK FOREIGN KEY(USER_ID) REFERENCES HOUSE_USER(USER_ID),
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES
are neccessary or not. I ask because i have another many to many relationship:
CREATE TABLE HOUSE_USER_GROUPE
(
USER_GROUPE_ID NUMBER(10) NOT NULL,
USER_GROUPE_NAME VARCHAR(255) NOT NULL,
CONSTRAINT USER_GROUPE_PK PRIMARY KEY(USER_GROUPE_ID)
);
CREATE TABLE HOUSE_ACCESSR
(
ACCESSR_ID NUMBER(10) NOT NULL,
ACCESSR_NAME VARCHAR(255) NOT NULL,
CONSTRAINT ACCESSR_PK PRIMARY KEY(ACCESSR_ID)
);
CREATE TABLE HOUSE_USER_GROUPE_ACCESR
(
USER_GROUPE_ID NUMBER(10) NOT NULL,
ACCESSR_ID NUMBER(10) NOT NULL,
CONSTRAINT USER_GROUPE_ACCESSR_PK PRIMARY KEY(USER_GROUPE_ID, ACCESSR_ID),
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES HOUSE_USER_GROUPE(USER_GROUPE_ID),
CONSTRAINT ACCESSR_FK FOREIGN KEY(ACCESSR_ID) REFERENCES HOUSE_ACCESSR(ACCESSR_ID)
);
I cant create the second many to many table because i already used the constraint:
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES HOUSE_USER_GROUPE(USER_GROUPE_ID),
I could just rename it but because of that error:
ORA-02264: name already used by an existing constraint
I just was wondering if these constraints are mandatory.
Yes, you should create the foreign key constrain on both tables.
The foreign key constraints are there to maintain referential integrity; ensuring that you can't insert values that don't exist in the parent table.
If you don't add the constraint to HOUSE_USER_GROUPE_ACCESR then you don't get that protection in that table. And you should want that protection everywhere.
Your only apparent mistake is that the constraint names are identical to each other. I traditionally either include No Name (letting Oracle decide on the name, because I never refer to the constraint by name) or use a format something like fk_<table>_<field>.
You need to do the constraints.. create the second constraints with another name.

Error There are no primary or candidate keys in the referenced table

I'm getting this error when trying to create a table with foreign key:
There are no primary or candidate keys in the referenced table 'TeamToPlayers' that match the referencing column list in the foreign key 'FKey2'.
I don't understand why, there is a primary key in the table TeamToPlayers.
Here are the queries:
create table TeamToPlayers
(TeamName varchar(50) NOT NULL,
PlayerName varchar(50) NOT NULL,
primary key(TeamName,PlayerName),
CONSTRAINT FKey FOREIGN KEY (TeamName) REFERENCES Teams(TeamName)
)
create table Players
(PlayerName varchar(50) NOT NULL,
primary key(PlayerName),
CONSTRAINT FKey2 FOREIGN KEY (PlayerName) REFERENCES TeamToPlayers(PlayerName)
);
Table TeamToPlayers primary key consists of two fields - you must reference both as otherwise it's not a key. I think you may have your key the wrong way round - it should be on TeamToPlayers and referencing Players like so:
create table TeamToPlayers
(
TeamName varchar(50) NOT NULL,
PlayerName varchar(50) NOT NULL,
primary key(TeamName,PlayerName),
CONSTRAINT FKey FOREIGN KEY (TeamName) REFERENCES Teams(TeamName),
CONSTRAINT FKey2 FOREIGN KEY (PlayerName) REFERENCES Players(PlayerName)
)
create table Players
(PlayerName varchar(50) NOT NULL,
primary key(PlayerName),
);