Number of referencing columns must match referenced columns - sql

I am relatively new to SQL and I keep getting the following error "The number of columns in the foreign-key referencing list is not equal to the number of columns in the referenced list."
create table client
(name varchar(30),
phone int,
city varchar(20),
state char(2) CHECK(state='MN' OR state='ND' OR state='SD' OR state='WI' or state='IA'),
primary key(name,phone));
create table owns_vehicle
(name varchar(30),
phone int,
vin varchar(10),
primary key(name, phone, vin),
foreign key(name,phone) references client);
create table service_appointment
(mydate date,
vin varchar(10),
mechanic varchar(15),
description varchar(30) NOT NULL,
cost int CHECK (cost>=0),
primary key(mydate,vin),
foreign key(vin) references owns_vehicle);
This is the line that is causing the issue:
foreign key(vin) references owns_vehicle);
Does anyone know why I am getting this error?

You try to reference owns_vehicle, thus you need to reference all of the tables PRIMARY KEY columns, which would be name, phone, vin. But your foreign key has only vin, thus there are two columns (name, phone) missing.

The primary key has three parts. You need to reference all of them. If you are going to use this model, then you need the other two components:
create table service_appointment (
mydate date,
name varchar(30),
phone int,
vin varchar(10),
mechanic varchar(15),
description varchar(30) NOT NULL,
cost int CHECK (cost>=0),
primary key(mydate,vin),
foreign key(name, phone, vin) references owns_vehicle (name, phone, vin)
);
However, I think you data model should change. VINs can change owners. People can change phone numbers. These don't seem like good components of a primary key.

If you assume that a vehicle can only have a single owner at a given time, you can make your current data model work by changing owns_vehicle to have a uniqueness constraint on VIN:
CREATE TABLE OWNS_VEHICLE
(NAME VARCHAR2(30),
PHONE INT,
VIN VARCHAR2(10),
CONSTRAINT PK_OWNS_VEHICLE
PRIMARY KEY(NAME, PHONE, VIN)
USING INDEX,
CONSTRAINT OWNS_VEHICLE_UQ1
UNIQUE(VIN)
USING INDEX,
CONSTRAINT OWNS_VEHICLE_FK1
FOREIGN KEY(NAME,PHONE) REFERENCES CLIENT(NAME, PHONE));

Related

How to create zero or one to many relationship using sql

I have this data model generated by EntityFramework in an existing application but i want to create the same tables with the same relationships in my database.
I succeeded creating the relationship (one to zero or one) between Student and StudentAddress with the following query which is correct:
CREATE TABLE Student(
StudentId INT NOT NULL PRIMARY KEY,
FirstName VARCHAR(30),
LastName VARCHAR(30),
City VARCHAR(30),
State1 VARCHAR(30),
StandardId INT NOT NULL FOREIGN KEY REFERENCES Standard(StandardId));
CREATE TABLE StudentAddress(
StudentId INT,
Adress1 VARCHAR(30),
Adress2 VARCHAR(30),
City VARCHAR(30),
State VARCHAR(30),
CONSTRAINT StudentAdress_PK PRIMARY KEY(StudentId),
CONSTRAINT StudentAdress_Student_FK FOREIGN KEY(StudentId)
REFERENCES Student(StudentId));
My question is considering this data model how to create the relationship (zero or one to many) between Standard and Student tables.
Thank you for your help
You do this the same way that you implemented the one to zero or one relationship.
So far you have a foreign key in StudentAddress to Student. There is nothing enforcing one address per student. (You could do so with a unique index on `StudentAddress.StudentId'.)
So do the same thing. Have a StandardId field in the Student table, and you will have a many Student to zero or one Standard relationship.
You need a third table that stores the relationships:
CREATE TABLE StandardStudenRelation (
ID INT IDENTITY(1,1) PRIMARY KEY
, StandardID INT NOT NULL
, StudentID INT NOT NULL
, CONSTRAINT Student_ID_FK FOREIGN KEY(StudentId)
REFERENCES Standard(StudentId)
, CONSTRAINT Standard_ID_FK FOREIGN KEY(StandardID)
REFERENCES Standard(StandardId)
);

SQL: Foreign key references a composite primary key

I'm new to SQL and there are a lot of things going on that I still don't seem to quite understand. I have the following table
CREATE TABLE Person
(
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
PRIMARY KEY (First_Name, Name, Address)
);
I know want to create another table that has the primary key from the table Person as foreign key and also as primary key:
CREATE TABLE Purchase
(
No_Installments int,
Rate int,
Person varchar(50) NOT NULL PRIMARY KEY,
CONSTRAINT PFK
FOREIGN KEY (Person) REFERENCES Person (First_Name, Name, Address)
);
For some reason this doesn't work and I get an error every time. I've already looked up the other threads here on stackoverflow, but they don't really seem to help me. What am I doing wrong?
If you have a compound PK made up from three columns, then any child table that wants to establish a foreign key relationship must ALSO have all those 3 columns and use all 3 columns to establish the FK relationship.
FK-PK relationship is an all or nothing proposal - you cannot reference only parts of a primary key - either you reference all columns - or you don't reference.
CREATE TABLE Purchase
(
No_Installments int,
Rate int,
Person varchar(50) NOT NULL PRIMARY KEY,
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
CONSTRAINT PFK
FOREIGN KEY (First_Name, Name, Address)
REFERENCES Person (First_Name, Name, Address)
);
Have an integer primary key, using identity, auto_increment, serial or whatever for your database:
CREATE TABLE Person (
PersonId int identity PRIMARY KEY
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
CONSTRAINT unq_person_3 UNIQUE (First_Name, Name, Address)
);
Then use the identity column for the reference:
CREATE TABLE Purchase (
PurchaseId int identity PRIMARY KEY,
No_Installments int,
Rate int,
PersonId int,
CONSTRAINT PFK
FOREIGN KEY (PersonId) REFERENCES Person (PersonId)
);
Notes:
You really don't want to have to deal with a composite primary key. Have you thought about what the joins will look like?
You don't want a primary key where the values are subject to change. What happens when someone changes his/her name? When someone moves?
Person should not be the primary key in Purchases. Are you only allowing someone to make one purchase?
As noted initially, how you generate such a column varies by database; identity happens to be the way that SQL Server does this.
You probably want to assign a unique ID to each person, not relying on their name to be unique or for an address to be required. That ID will be your Primary key and foreign key. Your purchase table should also have its own id for its primary key -- otherwise because primary keys must be unique, each person can only have one purchase.
CREATE TABLE Person (
id serial NOT NULL,
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
PRIMARY KEY (id));
CREATE TABLE Purchase (
id serial NOT NULL,
No_Installments int,
Rate int,
Person int NOT NULL,
FOREIGN KEY (Person) REFERENCES Person (id),
PRIMARY KEY (id));

SQL - is developing queries based on nonexistent data possible?

Is it possible to develop a query from nonexistent data? for example, I have this schema :
-- ZIP code database
BEGIN TRANSACTION;
CREATE TABLE city (
city_id INT,
city_name VARCHAR(80),
city_county VARCHAR(80),
city_state VARCHAR(5),
city_country VARCHAR(5),
city_region VARCHAR(5),
longitude INT,
latitude INT,
timezone varchar(80),
PRIMARY KEY (city_id)
);
CREATE TABLE zipcode (
zipcode CHAR(5),
ziptype VARCHAR(36),
active BOOLEAN,
primary_city_id INT NOT NULL,
notes TEXT,
PRIMARY KEY (zipcode),
FOREIGN KEY (primary_city_id) REFERENCES city(city_id)
);
CREATE TABLE acceptable (
zipcode CHAR(5),
city_id INT,
acceptable BOOLEAN,
PRIMARY KEY (zipcode, city_id),
FOREIGN KEY (zipcode) REFERENCES zipcode(zipcode),
FOREIGN KEY (city_id) REFERENCES city(city_id)
);
CREATE TABLE zip_areacode (
zipcode CHAR(5),
areacode VARCHAR(5),
PRIMARY KEY (zipcode, areacode),
FOREIGN KEY (zipcode) REFERENCES zipcode(zipcode),
FOREIGN KEY (areacode) REFERENCES areacode(prefix)
);
COMMIT;
//from here, would I be able to filter out results by the zip code with the highest population? This isn't possible, right? I don't see any data regarding population
No, you cant. Because you have no information about population. Thus your queries will be on non existent relations. That's not possible.
You can create temporary tables (relations) if you want. And fill it with random data. But I don't think you'll find out something useful.

SQL Constraints Confusion

I'm in a bit of a mix right now, I have a Table called Avatars, which has a foreign key called Family. Now, in the family table, I have two Foreign Keys called Mother and Father - Now this is the confusing bit, in both the Mother and Father Tables, there is a Foreign key called Avatar_ID which is of course the Primary Key to the Avatars table. I'm not sure if that's even allowed in SQL PLUS.
Whenever I try and enter the tables 'Family, Mother or Father', I keep getting the error:ORA-02291: integrity constraint (SG304.FK_FATHER_ID) violated - parent key not found.
Is there any way around this? Or will I have to change my code completely? A sample of the code is below.
CREATE TABLE Avatars (
Avatar_ID VARCHAR(10) NOT NULL,
Avatar_Name VARCHAR(30),
AvA_DOB DATE,
Age VARCHAR(30),
Gender VARCHAR(30),
Strength_Indicated INT,
Hoard INT,
Avatar_Level VARCHAR(30),
Skill VARCHAR(30),
Original_Owner VARCHAR(30),
Family_ID VARCHAR(10) NOT NULL,
Species_ID VARCHAR(10) NOT NULL,
Inventory_ID VARCHAR(30) NOT NULL,
Weapon_ID VARCHAR(10),
Player_ID VARCHAR(10) NOT NULL,
PRIMARY KEY (Avatar_ID));
CREATE TABLE Family (
Family_ID VARCHAR(10) NOT NULL,
Mother_ID VARCHAR(10) NOT NULL,
Father_ID VARCHAR(10) NOT NULL,
primary key(Family_ID)
);
CREATE TABLE Mother (
Mother_ID VARCHAR(10) NOT NULL,
Avatar_ID VARCHAR(10) NOT NULL,
primary key(Mother_ID)
);
CREATE TABLE Father (
Father_ID VARCHAR(10) NOT NULL,
Avatar_ID VARCHAR(10) NOT NULL,
primary key(Father_ID)
);
ALTER TABLE Avatars
ADD CONSTRAINT fk_Family_ID
FOREIGN KEY (Family_ID)
REFERENCES Family(Family_ID);
ALTER TABLE Family
ADD CONSTRAINT fk_Mother_ID
FOREIGN KEY (Mother_ID)
REFERENCES Mother(Mother_ID);
ALTER TABLE Family
ADD CONSTRAINT fk_Father_ID
FOREIGN KEY (Father_ID)
REFERENCES Father(Father_ID);
ALTER TABLE Father
ADD CONSTRAINT fk_Avatar_ID
FOREIGN KEY (Avatar_ID)
REFERENCES Avatars(Avatar_ID);
ALTER TABLE Mother
ADD CONSTRAINT fk_Avatars_ID
FOREIGN KEY (Avatar_ID)
REFERENCES Avatars(Avatar_ID);
INSERT INTO Avatars (Avatar_ID,Avatar_Name,AvA_DOB,Age,Gender,Strength_Indicated,Hoard,Avatar_Level, Skill, Original_Owner, Family_ID,Species_ID,Inventory_ID,Player_ID) VALUES
('Ava01','Verda','20-JAN-2014','1 year 2 months','Female','100','20','Master','Leader',' - ',' - ','DRA1','MasterInventory','Player07');
Thanks in advance for any help given! (:
Foreign key refers to a record in parent table. In your INSERT statement you are inserting value ' - ' into a column parent_id. In this error message oracle informs you that there is no record with value ' - ' in a column family_id of a table family. As I can understand, you are trying to use ' - ' as 'absence of value'. There is special value for that - NULL. So you need to write your statement as:
INSERT INTO Avatars (Avatar_ID, Avatar_Name, AvA_DOB,
Age, Gender, Strength_Indicated, Hoard, Avatar_Level, Skill,
Original_Owner, Family_ID, Species_ID, Inventory_ID, Player_ID)
VALUES ('Ava01', 'Verda', '20-JAN-2014', '1 year 2 months' ,'Female',
'100', '20', 'Master', 'Leader', NULL, NULL, 'DRA1',
'MasterInventory', 'Player07');
Also I can recommend some changes to your schema. First of all, use number data type for primary keys - it allows you to use sequences to generate unique values. Also, I don't know details of the problem, but "family relations" in your tables look a bit complicated. You can describe it in a single table:
create table family_tree (
person_id number primary key,
father_id number,
mother_id number,
sex char(1),
name varchar2(50),
family_name varchar2(50));
add constraint fk_mother_id foreign key (mother_id)
references family_tree (person_id);
add constraint fk_father_id foreign key (father_id)
references family_tree (person_id);

oracle table creation

The following code gives me ERROR at line 3: ORA-00907: missing right parenthesis:
CREATE TABLE ORGANISATION(
ORG_REF VARCHAR(5),
POSTCODE VARCHAR(10) FOREIGN KEY,
TELEPHONE NUMBER FOREIGN KEY,
DESCRIPTION VARCHAR(30),
AGENCY_ID VARCHAR(5));
Line 3 code is very annoying because looking at the line there are no spelling mistakes and everything is in the right place.
That's not how you define a foreign key. A foreign key must know how to find it's partner.
Read here: http://www.techonthenet.com/oracle/foreign_keys/foreign_keys.php
Foreign key definition goes something like this:
CREATE TABLE ORGANISATION(
ORG_REF VARCHAR(5),
POSTCODE VARCHAR(10), --THIS WILL BE FOREIGN KEY
TELEPHONE NUMBER, --2nd FOREIGN KEY
DESCRIPTION VARCHAR(30),
AGENCY_ID VARCHAR(5),
FOREIGN KEY FK_POSTCODE
REFERENCES other_table (post_code),
FOREIGN KEY FK_TELEPHONE
REFERENCES other_table2 (phone)
);
UPDATE:
Additional Recommended Reading: http://mattgemmell.com/2008/12/08/what-have-you-tried/
Where to start?
You should be using varchar2 not varchar. Although they're currently identical the future behaviour of varchar is not guaranteed
Telephone number as a numeric field? A lot of phone numbers start with a 0. You're losing this. If you ever want to display it nicely you have to do some funky string manipulation on exit.
If your IDs are numbers then you should store them as a number.
There is rarely a situation where a table should not have a primary key.
A foreign key is designed to enforce referential integrity in the database. There should therefore be one or two more tables in this schema as a minimum.
A typical situation might be like this, which assumes that the same postcode,phone combination exists in agency.
CREATE TABLE ORGANISATION(
ORG_REF VARCHAR2(5),
POSTCODE VARCHAR2(10) ,
TELEPHONE VARCHAR2(50),
DESCRIPTION VARCHAR(30),
AGENCY_ID VARCHAR(5),
CONSTRAINT PK_ORGANISATION PRIMARY KEY ( org_ref ),
CONSTRAINT FX_ORGANISATION FOREIGN KEY
REFERENCES SOME_OTHER_TABLE(POSTCODE,PHONE)
);
If it were just a single column and not 2 you could reference it inline, something like the following:
create table organisation (
org_ref number(16) not null
, phone varchar2(5) not null constraint fk_organisation
references agency ( phone )
, constraint pk_organisation primary key ( org_ref )
);
However, I doubt very much that this'll work. A foreign key must reference a unique constraint. So, judging by your comments you must have a table agency with a unique constraint or primary key on phone, postcode.
I suspect your data-model is flawed; it sounds as though organisation inherits from agency.
I would remove the phone and postcode from agency and just do a join to get that information, if you're currently looking at the agency table:
select a.*, o.postcode, o.phone
from agency a
join organisation o
on a.agency_id = o.agency_id
where a.id = 12345
Further reading:
Examples
Documentation
CREATE TABLE ORGANISATION(
ORG_REF VARCHAR(5),
POSTCODE VARCHAR(10),
TELEPHONE NUMBER,
DESCRIPTION VARCHAR(30),
AGENCY_ID VARCHAR(5),
constraint pcodefk foreign key(POSTCODE) references postalcodetable(POSTALCODE),
constraint telefk foreign key(TELEPHONE) references telephonenumbers(TELEPHONE));