How to define a foreign key - sql

my two parents table are person and artwork. I created their table as follows:
create table person (
person_id number(20) primary key,
name varchar2(20),
address varchar(50),
contact_number number (10)
);
and other
create table artwork (
artwork_id number primary key,
barcode char (20),
title varchar2(20),
description varchar2(50));
When I try to make the child table vote it is giving this error.
create table vote
(
vote_id number(7) NOT NULL,
artwork_id number(20),
person_id number(20),
PRIMARY KEY (vote_id),
FOREIGN KEY (artwork_id) REFERENCES artwork(artwork_id),
FOREIGN KEY ( person_id) REFERENCES Person(person_id)
);
SP2-0734: unknown command beginning "FOREIGN KE..." - rest of line ignored.

You forgot to mention constraint before foreign key:
create table vote
(
vote_id number(7) NOT NULL,
artwork_id number(20),
person_id number(20),
PRIMARY KEY (vote_id),
CONSTRAINT fk_artwork_id FOREIGN KEY (artwork_id) REFERENCES artwork(artwork_id),
CONSTRAINT fk_person_id FOREIGN KEY ( person_id) REFERENCES Person(person_id)
);
Syntax
The syntax for creating a foreign key using a CREATE TABLE statement
is:
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)
);
Demo
http://sqlfiddle.com/#!4/3d141
Explanation
By default SQLPlus doesn't like blank lines. However we can easily configure our SQLPlus environment to ignore them:
SQL> set sqlblanklines on
We can also put the setting in our glogin.sql file (assuming we're allowed to edit it, which isn't always the case).

remove that blank line before the definition of your constraints when creating the vote table:
create table vote
(
vote_id number(7) NOT NULL,
artwork_id number(20),
person_id number(20),
PRIMARY KEY (vote_id),
FOREIGN KEY (artwork_id) REFERENCES artwork(artwork_id),
FOREIGN KEY ( person_id) REFERENCES Person(person_id)
);
Any blank rows will stop SQL*Plus from accepting input lines.
If you want it to avoid this run:
set sqlblanklines on
before any other instruction.

Related

Oracle: Constraints of keys

I have an entity within Oracle's SQL:
and I'm wondering, what does "UF" represent? I've written the SQL code but I do not know how to represent the "UF" attribute as a constraint.
CREATE TABLE entry (
entryno NUMBER(4) NOT NULL,
carndate DATE NOT NULL,
entrystarttime DATE NOT NULL,
entryfinishtime DATE NOT NULL,
entryplace NUMBER(4) NOT NULL,
charname VARCHAR2(30) NOT NULL,
compno NUMBER(4) NOT NULL,
eventypecode CHAR(3) NOT NULL,
teamname VARCHAR2(30) NOT NULL
);
ALTER TABLE entry ADD CONSTRAINT entry_pk PRIMARY KEY ( entryno,
carndate );
ALTER TABLE entry
ADD CONSTRAINT entry_charity_fk FOREIGN KEY ( charname )
REFERENCES charity ( charname );
ALTER TABLE entry
ADD CONSTRAINT entry_carnival_fk FOREIGN KEY ( carndate )
REFERENCES carnival ( carndate );
ALTER TABLE entry #
ADD CONSTRAINT entry_competitor_fk FOREIGN KEY ( compno )
REFERENCES competitor ( compno );
ALTER TABLE entry #
ADD CONSTRAINT entry_event_fk FOREIGN KEY ( carndate, eventypecode )
REFERENCES evenet ( carndate, eventypecode );
ALTER TABLE entry
ADD CONSTRAINT entry_team_fk FOREIGN KEY ( teamname, carndate )
REFERENCES team ( teamname,carndate );
ALTER TABLE entry
ADD CONSTRAINT ... ("UF")
The UF is actually two flags.
As you've recognised the F means the column is a foreign key. The U stands for Unique. Those columns form part of the compound unique key:
ALTER TABLE entry ADD CONSTRAINT entry_carnival_un UNIQUE
( carndate, compno, eventypecode );
carndate is also part of the compound primary key so really it should be flagged PFU but I guess the modelling tool didn't allow for three flags.

foreign keys: number of columns not equal to referenced columns

I'm getting an error from oracle that says "number of referencing columns must match referenced columns."
I want my column recorded_on in the table measurement to reference recorded_on in the table called sample
The column Recorded on in the Sample table must be part of a composite key together with Scientist_Num
The error is coming from
FOREIGN KEY (Recorded_On) REFERENCES Sample(Scientist, Recorded_On, Site_ID)
CREATE TABLE Sample (
Scientist_Num varchar2(5) not null,
Recorded_On date not null,
Site_ID varchar2(4) not null,
Comments clob,
Primary key (Scientist_Num, Recorded_On),
FOREIGN KEY (Scientist_Num) REFERENCES Scientist(Scientist_Num),
FOREIGN KEY (Site_ID) REFERENCES Site(Site_ID)
);
CREATE TABLE Measurement (
Site_ID varchar2(4) not null,
Recorded_On date not null,
Name varchar2(10) not null,
Value varchar2(10),
Outlier_Indicator varchar2(10),
Primary key (Site_ID, Recorded_On, Name),
FOREIGN KEY (Site_ID) REFERENCES Sample(Site_ID),
FOREIGN KEY (Recorded_On) REFERENCES Sample(Scientist, Recorded_On, Site_ID)
);
The Scientist_Num and Recorded_On columns must be in a composite key together.
The answer to my problem and an explanation of what went wrong would be greatly appreciated.
You can create virtual column in sample table:
Recorded_virtual varchar2(5) [GENERATED ALWAYS] AS
(Scientist||Recorded_On||Site_ID) [VIRTUAL]
And create reference to this column:
CONSTRAINT fk_column
FOREIGN KEY (Recorded_On)
REFERENCES Sample(Recorded_virtual )
Foreign key references need to match the primary keys in number and type. So I think you intend:
CREATE TABLE Measurement (
Site_ID varchar2(4) not null,
Scientist_Num varchar2(5) not null,
----^ added for foreign key reference
Recorded_On date not null,
Name varchar2(10) not null,
Value varchar2(10),
Outlier_Indicator varchar2(10),
Primary key (Site_ID, Recorded_On, Name),
FOREIGN KEY (Site_ID) REFERENCES Site(Site_ID),
-------------------------------------^ Presumably you intend the site table
FOREIGN KEY (Scientist_Num, Recorded_On) REFERENCES
Sample(Scientist_Num, Recorded_On)
-----------------^ two columns, both need to already be defined
);
I suspect there are other issues with your data model, but this should fix the syntax error. If you want further help, then ask another question.

Cannot create table. SQL Error 02270

This is the table I am trying to create. However, I get the error
SQL Error: ORA-02270: no matching unique or primary key for this column-list
SQL:
create table Meets_In
(
cid char(20),
rno integer,
time char(20),
CONSTRAINT PRIM_KEY PRIMARY KEY(time),
constraint meets_fk1 foreign key(cid) references COURSES(CID),
constraint meets_fk2 foreign key(rno) references ROOMS(RNO)
);
These are the parent tables:
create table Courses
(
cid char(20),
cname char(20),
credits integer,
constraint CoursesKey Primary Key (cid, cname)
);
CREATE TABLE ROOMS
(
rno INTEGER,
address CHAR(20),
capacity INTEGER,
CONSTRAINT room_key PRIMARY KEY(rno)
);
I don't understand why I am getting this error.
Cause
The ORA-2270, as the error message suggests, happens when there is no matching unique or primary key for this column-list. This could be because
the parent lacks a constraint altogether
the parent table's constraint is a compound key and we haven't referenced all the columns in the foreign key statement.
Now in your COURSES table, CID is not a primary key. It is a combination of cid,cname. So for every cid, there can be multiple rows.
Now when you reference cid as foreign key for meets_in, it will not work as it violates the second point as I mentioned above.
Workaround
Add column cname in your meets_in table as well. Then use it like below.
create table Meets_In
(
cid char(20) not null,
cname char(20),
rno integer not null,
time1 char(20) not null,
CONSTRAINT PRIM_KEY PRIMARY KEY(time1),
constraint meets_fk1 foreign key(cid,cname) references COURSES (cid,cname), /*Added cid,cname */
constraint meets_fk2 foreign key(rno) references ROOMS (RNO)
);
Meets_In is acting as an associative table. Therefore its primary key should include the foreign keys into the tables it is associating.
Try a primary key consisting of: cid, cname, rno and time.
As others have noted, your primary key for courses is (cid, cname), so you also need to include both of these in your foreign key constraint meets_fk1. Or, if possible, ensure that cid only is the primary key on courses.
(I think time may be a reserved word, so perhaps consider renaming it.)

Foreign Key Creation issue in Oracle

When I try to create these two tables I get:
"SQL Error: ORA-00904: "COLLECTIBLENUM": invalid identifier"
I'm sure it's a noob error but I'm just not seeing it. Can someone please point out what I'm doing wrong? Thanks in advance.
CREATE TABLE Collectibles(
CollectibleNum Number(10) NOT NULL,
CONSTRAINT collectibles_pk PRIMARY KEY(CollectibleNum));
Create table DiecastItems(
DiecastName VARCHAR2(45) NOT NULL,
DiecastCopy NUMBER(2) NOT NULL,
DiecastScale VARCHAR2(25),
ColorScheme VARCHAR2(25),
DiecastYear NUMBER(4),
CONSTRAINT diecastItem_pk PRIMARY KEY(DiecastName, DiecastCopy),
CONSTRAINT diecastItem_Collectible_fk FOREIGN KEY(CollectibleNum) REFERENCES Collectibles(CollectibleNum));
When you add FK, you are linking a column as a child from the table you are creating, to its parent from the parent table. Hence, you need to provide the child column name, as well as the parent column name.
The general syntax is
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)
);
Notice that the columns between FOREIGN KEY brackets, are from the table you are creating, while the columns betweeN REFERENCES PARENT_TABLE are from the parent table.
You do not have a column called CollectibleNum in yourDiecastItems. Hence, the following works fine by adding such a column:
CREATE TABLE collectibles
(
collectiblenum NUMBER(10) NOT NULL,
CONSTRAINT collectibles_pk PRIMARY KEY(collectiblenum)
);
CREATE TABLE diecastitems
(
diecastname VARCHAR2(45) NOT NULL,
diecastcopy NUMBER(2) NOT NULL,
diecastscale VARCHAR2(25),
colorscheme VARCHAR2(25),
diecastyear NUMBER(4),
collectiblenum NUMBER(10), --added column
CONSTRAINT diecastitem_pk PRIMARY KEY(diecastname, diecastcopy),
CONSTRAINT diecastitem_collectible_fk FOREIGN KEY(collectiblenum)
REFERENCES collectibles(collectiblenum)
);
FIDDLE

How to model m:n with 1 optional default value?

Below are two schema which I believe achieve the same result, i.e. m:n relationship with the option for a default/preferred value. Is there any reason to use one over the other?
Schema #1
CREATE TABLE people (
id serial,
primary key (id)
);
CREATE TABLE names (
id serial,
first_name text not null,
last_name text not null,
primary key (id)
);
CREATE TABLE person_has_name (
person_id integer not null references people (id),
name_id integer not null references names (id),
is_default boolean not null default false,
primary key (person_id, name_id)
);
Schema #2
CREATE TABLE people (
id serial,
default_name_id integer references names (id),
primary key (id)
);
-- this table has not changed
CREATE TABLE names (
id serial,
first_name text not null,
last_name text not null,
primary key (id)
);
CREATE TABLE person_has_name (
person_id integer not null references people (id),
name_id integer not null references names (id),
primary key (person_id, name_id)
);
Let's analyze:
Second schema prevent to you to set more than one name as default, but don't prevent to you to set as default name some not related name.
Opposite happens with first schema.
I propose to you (to your zombie user) a third schema that solves math problems:
CREATE TABLE people (
id serial,
default_name_id integer ,
primary key (id),
constraint default_person_name_fk --<--HERE
foreign key (id, default_name_id)
references person_has_name (person_id, name_id)
);
-- this table has not changed
CREATE TABLE names (
id serial,
first_name text not null,
last_name text not null,
primary key (id)
);
CREATE TABLE person_has_name (
person_id integer not null references people (id),
name_id integer not null references names (id),
primary key (person_id, name_id)
);
Regards and sorry about delay, I'm lag ;)
With the second schema you can't add people without first knowing their name. As long as this is ok (i.e. you know that whenever a person is added, they have to reveal their name), then I'd say that either of these schemas are fine, and that schema #2 might even be more optimized in the scenario where you need to query only for the default name.
I would use none of the two.
Solution 1 does not prevent you from having 2 default names for a person.
Solution 2 does not prevent a person having a default name that is not his. You could change the Foreign Key from default_name_id references names(id) to (person_id, default_name_id) references person_has_name(person_id, name_id) but then you'd have circular references and that's another problem, hard to solve.
You could use this, similar to your 2nd solution:
CREATE TABLE people (
id serial,
--- no default_name_id as foreign key here
primary key (id)
);
CREATE TABLE names (
id serial,
first_name text not null,
last_name text not null,
primary key (id)
);
CREATE TABLE person_has_name (
person_id integer not null references people (id),
name_id integer not null references names (id),
primary key (person_id, name_id)
);
With this extra table, for those persons that have a default name:
CREATE TABLE person_default_name (
person_id integer not null,
name_id integer not null,
primary key (person_id),
foreign key (person_id, name_id)
references person_has_name (person_id, name_id)
);