How to set keys to a relationship table in Oracle10g - sql

Please before judging bear in mind that I don't understand that's why I ask the question. I am discouraged by some down voting that has occured in the past.
I have to create a database in Oracle 10g and I am using the template to create a new table.
The database is about an imaginary facebook application.
Amongst others it includes relationship "like" with 3 attributes all of which are supposed to be keys:
like:
username: key
message_author: key
message_code: key
as I said like is a relationship between two entities user and message.
I tried to setup the table like as 3 foreign keys connected to the other tables but oracle will not accept it.
I get the following error message:
Failed Creating FK like_FK2 ORA-02270: no matching unique or primary key for this column-list
ORA-00942: table or view does not exist
ORA-06510: PL/SQL: unhandled user-defined exception
I suppose I am doing something wrong with the keys, but I can't understand what it is
SQL commands:
CREATE table "ΑΡΕΣΕΙ" (
"ΟΝΟΜΑΧΡΗΣΤΗ" VARCHAR2(30) NOT NULL,
"ΣΥΓΦΕΑΣ_ΜΗΝΤΟΣ" VARCHAR2(30) NOT NULL,
"ΚΩΔΜΗΝΥΜΑΤΟΣ" NUMBER NOT NULL
)
/
ALTER TABLE "ΑΡΕΣΕΙ" ADD CONSTRAINT "ΑΡΕΣΕΙ_FK"
FOREIGN KEY ("ΟΝΟΜΑΧΡΗΣΤΗ")
REFERENCES "ΧΡΗΣΤΗΣ" ("ΟΝΟΜΑΧΡΗΣΤΗ")
/
ALTER TABLE "ΑΡΕΣΕΙ" ADD CONSTRAINT "ΑΡΕΣΕΙ_FK2"
FOREIGN KEY ("ΣΥΓΦΕΑΣ_ΜΗΝΤΟΣ")
REFERENCES "ΜΗΝΥΜΑ" ("ΣΥΓΦΕΑΣ_ΜΗΝΤΟΣ")
/
ALTER TABLE "ΑΡΕΣΕΙ" ADD CONSTRAINT "ΑΡΕΣΕΙ_FK3"
FOREIGN KEY ("ΚΩΔΜΗΝΥΜΑΤΟΣ")
REFERENCES "ΜΗΝΥΜΑ" ("ΚΩΔΜΗΝΥΜΑΤΟΣ")
/
alter table "ΑΡΕΣΕΙ" add
constraint ΑΡΕΣΕΙ_UK1
unique ("ΚΩΔΜΗΝΥΜΑΤΟΣ")
/

Before you specify any relationship constraints and other constraints like UNIQUE, make sure that the tables exist before you code and run these statements. I am editing your code a little bit in my answer:
CREATE table "ΑΡΕΣΕΙ" (
"ΟΝΟΜΑΧΡΗΣΤΗ" VARCHAR2(30) NOT NULL,
"ΣΥΓΦΕΑΣ_ΜΗΝΤΟΣ" VARCHAR2(30) NOT NULL,
"ΚΩΔΜΗΝΥΜΑΤΟΣ" NUMBER(10,2) NOT NULL -- PRECISION AND SCALE MUST BE MENTIONED FOR NUMBER DATA TYPE
)
/
CREATE table "ΜΗΝΥΜΑ" (
"ΣΥΓΦΕΑΣ_ΜΗΝΤΟΣ" VARCHAR2(30) -- data types are recommended to be the same
"ΚΩΔΜΗΝΥΜΑΤΟΣ" NUMBER(10,2)
-- Other columns go here
)
/
CREATE TABLE "ΧΡΗΣΤΗΣ" (
"ΟΝΟΜΑΧΡΗΣΤΗ" VARCHAR(30)
-- Other columns go here
)
/
-- After you create all the tables, you can code the alter table statements
-- that would add all your necessary constraints.
ALTER TABLE "ΑΡΕΣΕΙ" ADD CONSTRAINT "ΑΡΕΣΕΙ_FK"
FOREIGN KEY ("ΟΝΟΜΑΧΡΗΣΤΗ")
REFERENCES "ΧΡΗΣΤΗΣ" ("ΟΝΟΜΑΧΡΗΣΤΗ")
/
ALTER TABLE "ΑΡΕΣΕΙ" ADD CONSTRAINT "ΑΡΕΣΕΙ_FK2"
FOREIGN KEY ("ΣΥΓΦΕΑΣ_ΜΗΝΤΟΣ")
REFERENCES "ΜΗΝΥΜΑ" ("ΣΥΓΦΕΑΣ_ΜΗΝΤΟΣ")
/
ALTER TABLE "ΑΡΕΣΕΙ" ADD CONSTRAINT "ΑΡΕΣΕΙ_FK3"
FOREIGN KEY ("ΚΩΔΜΗΝΥΜΑΤΟΣ")
REFERENCES "ΜΗΝΥΜΑ" ("ΚΩΔΜΗΝΥΜΑΤΟΣ")
/
alter table "ΑΡΕΣΕΙ" add
constraint ΑΡΕΣΕΙ_UK1
unique ("ΚΩΔΜΗΝΥΜΑΤΟΣ")
/
Also, keep in mind that there is a constraint called PRIMARY KEY which allows you to put unique and not null constraints on a column at the same time. I recommend you read the documentation provided by Oracle at docs.oracle.com for your reference.
Also, I hope you mention all your table names and column names in ASCII (a-z, A-Z, 0-9) characters. Unicode characters as object identifiers may be supported but are difficult to maintain.

Related

Change primary key from simple to composite with new column

I am trying to change the primary key of one of my tables from a simple to a composite key, where the composite should be composed of the old pk column and a newly created one.
I followed along this answer from a very similar question: https://stackoverflow.com/a/27832197/1948454
It almost works, except that there is no value set in the dependant table for the new column.
Here's the situation:
Suppose I have a table for a catalog, and a table for catalog entries. Before:
-- DDL Catalog
CREATE TABLE public.Catalog (
name_ VARCHAR(255) NOT NULL,
foo_ VARCHAR(255) NULL,
CONSTRAINT Catalog_pkey PRIMARY KEY (name_)
);
-- DDL CatalogEntry
CREATE TABLE public.CatalogEntry (
pricekey_ VARCHAR(255) NOT NULL,
pricekeyroot_ VARCHAR(255) NOT NULL,
catalog_name_ VARCHAR(255) NULL,
bar_ VARCHAR(255) NULL,
CONSTRAINT CatalogEntry_pkey PRIMARY KEY (pricekey_, pricekeyroot_)
);
-- public.CatalogEntry FOREIGN KEYs
ALTER TABLE public.CatalogEntry ADD CONSTRAINT CatalogEntry_catalog_name__fkey FOREIGN KEY (catalog_name_) REFERENCES Catalog(name_) ON DELETE CASCADE;
So CatalogEntry.catalog_name references to Catalog.name_.
Now I need to add another column version_ to the Catalog table, indicating a version of some catalog. This means I will have to create a new composite pk composed of name_ and version_. Here's my script:
-- UPDATE script
-- add the new version column and set all values to default of 1
ALTER TABLE Catalog ADD version_ INTEGER;
UPDATE Catalog SET version_ = 1;
ALTER TABLE Catalog ALTER column version_ SET not null;
-- update primary key and foreign key
BEGIN;
-- first, drop fkey constraint on CatalogEntry
ALTER TABLE CatalogEntry DROP CONSTRAINT CatalogEntry_catalog_name__fkey;
-- then, update Catalog primary key
ALTER TABLE Catalog DROP CONSTRAINT Catalog_pkey,
ADD CONSTRAINT Catalog_uni_name UNIQUE (name_),
ADD PRIMARY KEY (name_, version_);
-- now add new foreign key again to CatalogEntry
ALTER TABLE CatalogEntry ADD catalog_version_ INTEGER;
ALTER TABLE CatalogEntry
ADD CONSTRAINT CatalogEntry_catalog_name__catalog__fkey FOREIGN KEY (catalog_name_, catalog_version_)
references Catalog(name_, version_ ) ON DELETE CASCADE;
COMMIT;
-- finally, remove unique constraint on name since it is not needed anymore
ALTER TABLE Catalog DROP CONSTRAINT Catalog_uni_name;
After performing these steps, the primary and foreign key appear to be set correctly - but the value of CatalogEntry.catalog_version_ is null. The corresponding value of Catalog.version_ is set correctly to 1.
Where is my mistake? Do I also have to set CatalogEntry.catalog_version_ manually to 1? I would have assumed that it would be set automatically.
The value of CatalogEntry.catalog_version_ doesn't magically get set just because you define a foreign key constraint.
What effectively happened is that no row in CatalogEntry references a row in Catalog. The reason is that the default for foreign key constraints is MATCH SIMPLE, see the documentation:
MATCH SIMPLE allows any of the foreign key columns to be null; if any of them are null, the row is not required to have a match in the referenced table.
You should create the foreign key constraint as MATCH FULL so that either all or none of the columns must be NULL. Then you would have received an error creating the foreign key.
Solution: update CatalogEntry and set the column to 1 there as well, then define the foreign key with MATCH FULL.

Create table with foreign key to an other table created below in sql file

My problem is that i have two tables with each table having a foreign key to the other table.
Each time , i execute the SQL file containing the creation of the two tables, it gives me an error that he doesn't find the other table. I'm working with sqlplus to execute the sql file.
Here's an example of SQL file i tried with :
create table A(
Age number(3),
name number(3) constraint A_FK references B(name))
/
create table B(
Age number(3) constraint B_FK references A(Age),
name number(3))
And even if i reverse the order, it gives the same error.
Thanks for help.
This is a problem of cycles in foreign keys. One method is to add all foreign keys after table creation (as I think the other answers propose).
You can also just do that for the first table:
create table A (
Age number(3) primary key,
name number(3)
);
create table B (
name number(3) primary key,
Age number(3),
constraint B_FK foreign key (age) references A(Age)
);
alter table B add constraint A_FK foreign key (name) references B(name);
Here is a db<>fiddle.
Notes:
Foreign keys should reference primary keys, so I added that declaration as well.
I recommend making the primary key the first column in the table.
You can also define the constraint inline for one of the tables (i.e. age number(3) constraint b_fk references a(age)).
The table column(s) that is referred by a foreign key must exist at the time when the constraint is created. Since you have some kind of cyclic reference between the tables, you need to do this in three steps:
first create one table without the foreign key
create the second table (with its foreign key)
finally add the foreign key to the first table with an alter table statement
You also need the referred column to have a unique or primary key constraint set up, otherwise you would get error ORA-02270: no matching unique or primary key for this column-list.
create table A(
age number(3) primary key,
name number(3)
);
create table B(
age number(3) constraint B_FK references A(Age),
name number(3) primary key
);
alter table A add constraint A_FK foreign key (name) references B(name);
Demo on DB Fiddle
Side note: I am quite suspicious about your sample structure, but this could be because your oversimplified it in the question.
It fails because the reference table doesn't exist yet.
Create the tables without the key first. Then drop one and recreated it with the reference. Then drop the 2nd and recreate it with the reference.
Create table first and then ADD the CONSTRAINT
ALTER TABLE A
ADD FOREIGN KEY (name) REFERENCES B(name);
ALTER TABLE B
ADD FOREIGN KEY (age) REFERENCES A(age);

Can't add foreign key constraint to table

CREATE TABLE CUSTOMER
(
CNUM VARCHAR(25) NOT NULL,
CNAME VARCHAR(75) NOT NULL,
CTYPE VARCHAR(20) NOT NULL,
CONSTRAINT CUSTOMER_PK PRIMARY KEY(CNUM),
CONSTRAINT CHECK_CTYPE CHECK(CTYPE IN('INDIVIDUAL', 'INSTITUTION'))
);
CREATE TABLE CREDIT_TERM
(
CREDITSTATUS VARCHAR(20) NOT NULL,
STARTDATE DATE NOT NULL,
ENDDATE DATE NOT NULL,
CONSTRAINT CREDIT_TERM_PK PRIMARY KEY(CREDITSTATUS)
);
insert into CREDIT_TERM values('ONE-MONTH','15-05-2015','15-06-2015');
insert into CREDIT_TERM values('TWO-MONTH','15-05-2015','15-06-2015');
insert into CREDIT_TERM values('THREE-MONTH','15-05-2015','15-06-2015');
ALTER TABLE CUSTOMER
ADD CONSTRAINT CUSTOMER_FK_CREDITSTATUS
FOREIGN KEY(CREDITSTATUS) REFERENCES CREDIT_TERM(CREDITSTATUS);
I am trying to add a foreign key constraint, but I don't understand why I get this error:
ERROR at last line :
ORA-00904: "CREDITSTATUS": invalid identifier
As I noted in the comments, your customer table does not have a creditstatus column. You'd first have to add it:
ALTER TABLE customer ADD creditstatus VARCHAR2(20);
And then make it a foreign key, with the statement you already have.
You're trying to add a foreign key constraint for a foreign key named CREDITSTATUS on the CUSTOMER table. However, the CUSTOMER table doesn't have a foreign key for CREDITSTATUS.
You'll have to create a foreign key in CUSTOMER for CREDITSTATUS, then rerun the last line to add the constraint.
EDIT
Use ALTER TABLE to add the column to CUSTOMER:
ALTER TABLE CUSTOMER ADD CREDITSTATUS VARCHAR(20);
Docs:
http://www.techonthenet.com/oracle/tables/alter_table.php
You can add the column and the foreign key constraint in one statement:
alter table customer add (
creditstatus varchar2(20) constraint customer_fk_creditstatus references credit_term
);
A few notes. First, I enclosed the column definition in parentheses. It may work without them, but the official syntax seems to require them. http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_3001.htm#i2103924
Second, in an in-line constraint (defined at the column level, not at the table level), you may not use the words FOREIGN KEY. The word REFERENCES already identifies the constraint type. Third, if you reference the PRIMARY KEY of the referenced table, you are not required to (but you may if you wish) name the referenced column in the referenced table. If you don't name the column, the PRIMARY KEY of the referenced table will be used by default - which is what you want anyway, in the vast majority of cases.

correcting errors in sql code

I am new to this website, i hope that i ask the question the right way
-- Create a Database table to represent the "FACT" entity.
CREATE TABLE FACT
(
Time_id DATE NOT NULL,
Area_id INTEGER NOT NULL,
Reported_crime_id INTEGER NOT NULL,
Crime_status VARCHAR(8) NOT NULL,
no_of_crime INTEGER NOT NULL,
Max_crime INTEGER NOT NULL,
Avg_crime INTEGER NOT NULL,
Min_crime INTEGER NOT NULL,
date_reported DATE NOT NULL,
-- Specify the PRIMARY KEY constraint for table "FACT".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_fact PRIMARY KEY (Time_id, Area_id, Reported_crime_id,
Crime_status)
);
-- Create a Database table to represent the "Crime_Dim" entity.
CREATE TABLE Crime_Dim
(
REPORTED_CRIME_ID INTEGER NOT NULL,
CRIME_TYPE_Desc VARCHAR(50),
DATE_REPORTED DATE NOT NULL,
Crime_type_id INTEGER NOT NULL,
-- Specify the PRIMARY KEY constraint for table "Crime_Dim".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_crime_dim PRIMARY KEY (REPORTED_CRIME_ID)
);
-- Create a Database table to represent the "Location_Dim" entity.
CREATE TABLE Location_Dim
(
AREA_ID INTEGER NOT NULL,
AREA_Name VARCHAR(30) NOT NULL,
Area_code INTEGER NOT NULL,
Force_id INTEGER NOT NULL,
-- Specify the PRIMARY KEY constraint for table "Location_Dim".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_location_dim PRIMARY KEY (AREA_ID)
);
-- Create a Database table to represent the "Time_Dim" entity.
CREATE TABLE Time_Dim
(
Time_id INTEGER NOT NULL,
day_id INTEGER NOT NULL,
Month_id INTEGER NOT NULL,
Year INTEGER,
-- Specify the PRIMARY KEY constraint for table "Time_Dim".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_time_dim PRIMARY KEY (Time_id)
);
-- Create a Database table to represent the "Reported_crime_dim" entity.
CREATE TABLE Reported_crime_dim
(
Crime_status VARCHAR(20) NOT NULL,
Date_reported DATE NOT NULL,
-- Specify the PRIMARY KEY constraint for table "Reported_crime_dim".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_reported_crime_dim PRIMARY KEY (Crime_status)
);
-- i.e. tables may be referenced before they have been created. This method is therefore safer.
-- Alter table to add new constraints required to implement the "FACT_Time_Dim" relationship
-- This constraint ensures that the foreign key of table "FACT"
-- correctly references the primary key of table "Time_Dim"
ALTER TABLE FACT
ADD CONSTRAINT fk1_fact_to_time_dim FOREIGN KEY(Time_id) REFERENCES Time_Dim(
Time_id) ON DELETE RESTRICT ON UPDATE RESTRICT;
-- Alter table to add new constraints required to implement the "FACT_Location_Dim" relationship
-- This constraint ensures that the foreign key of table "FACT"
-- correctly references the primary key of table "Location_Dim"
ALTER TABLE FACT
ADD CONSTRAINT fk2_fact_to_location_dim FOREIGN KEY(AREA_ID) REFERENCES
Location_Dim(AREA_ID) ON DELETE RESTRICT ON UPDATE RESTRICT;
-- Alter table to add new constraints required to implement the "FACT_Crime_Dim" relationship
-- This constraint ensures that the foreign key of table "FACT"
-- correctly references the primary key of table "Crime_Dim"
ALTER TABLE FACT
ADD CONSTRAINT fk3_fact_to_crime_dim FOREIGN KEY(REPORTED_CRIME_ID) REFERENCES
Crime_Dim(REPORTED_CRIME_ID) ON DELETE RESTRICT ON UPDATE RESTRICT;
-- Alter table to add new constraints required to implement the "FACT_Reported_crime_dim" relationship
-- This constraint ensures that the foreign key of table "FACT"
-- correctly references the primary key of table "Reported_crime_dim"
ALTER TABLE FACT
ADD CONSTRAINT fk4_fact_to_reported_crime_dim FOREIGN KEY(Crime_status)
REFERENCES Reported_crime_dim(Crime_status) ON DELETE RESTRICT ON UPDATE
RESTRICT;
--------------------------------------------------------------
-- End of DDL file auto-generation
--------------------------------------------------------------
​
Could someone help me in correcting the errors in the sql code above? when i run the code as mentioned at the last few codes i need to create constraint to prevent Foreign keys in the Fact table and relate them back to their original table if i have got this right...
could someone correct the code and let me know plz
Following this answer, you have to remove ON DELETE RESTRICT and ON UPDATE RESTRICT.
There's no such option in Oracle.

Is there any way to make the following sql query work?

I am trying to create two tables using the following SQL:
create table student(sid char(20) primary key,name char(20),age int,hours char(10) references courses(cid));
create table courses(cid char(10),cname char(10),grader char(20) references student(sid));
However I get the following error:
1: ERROR: relation "courses" does not exist
3: ERROR: relation "student" does not exist
Is there any way or syntax which can solve this problem?
You would need to create the tables first (without REFERENCES clause). After that create your foreign keys manually by statement ALTER TABLE mytable ADD CONSTRAINT mytablefk FOREIGN KEY... But first I'd consider if there really is a relationship from table courses to table student!
Rather than creating the Foreign Key constraints at the same time as the tables with the References short-hand, you can add one or both of them afterwards with an Alter Table Add Constraint command. See the Alter Table page in the PostgrSQL manual here.
As mu pointed out, the target of a foreign key has to have a Unique or Primary Key constraint defined, so I've added that on the cid column in the example below.
In your case, it could look something like this:
create table student(sid char(20) primary key,name char(20),age int,hours char(10));
create table courses(cid char(10) primary key,cname char(10),grader char(20));
Alter Table student Add Constraint fk_student_hours_cid Foreign Key (hours) References courses(cid);
Alter Table courses Add Constraint fk_courses_grader_sid Foreign Key (grader) References student(sid);