so i have this code with simple two tables
1-GGroup
2-TimeTable
and this is the code for them :
CREATE TABLE GGroup(
ClassRoom varchar(7),
GroupNum number(5),
C_Code varchar(6),
C_Name varchar(35), Field
Teacher varchar(30),
primary key (ClassRoom)
);
CREATE TABLE TimeTable(
ClassRoom varchar(7),
StudentID number(9),
FirstName varchar(30),
LastName varchar(30),
primary key(ClassRoom, StudentID),
foreign key(ClassRoom) references GGroup(ClassRoom)
);
And i already inserted rows in table GGroup with np!
But now im trying to insert this row
insert into GGroup values (
'A/3/54',
1608,
'ISM223',
'Data Warehouse & Data Mining',
'Dr. Yasser Al-Mshhor'
);
And i got this error:
ORA-00001: unique constraint (SQL_XAKKMDKZQBPBDDQFTDEXENGDH.SYS_C0025290829) violated ORA-06512: at "SYS.DBMS_SQL", line 1721
I think its because this row I inserted before:
insert into GGroup values (
'A/3/54',
1608,
'ISM223',
'Data Warehouse & Data Mining',
'Dr. Yasser Al-Mshhor'
);
How i can fix this ? I dont know alot about sql
As others have already pointed out in their answers above - you are having this issue because you're using ClassRoom column as the Primary Key in your GGroup table script i.e. primary key (ClassRoom).
What is PRIMARY KEY?
A table can have only ONE primary key.
The PRIMARY KEY constraint uniquely identifies each record in a table.
Primary keys must contain UNIQUE values, and cannot contain NULL values.
This means that you cannot insert a duplicate value i.e. A/3/54 in ClassRoom column. One of the easiest ways to resolve this error will be to add another column e.g. GroupId by altering or dropping the table.
Note: If you have many rows in GGroup table then use ALTER TABLE (already shown in previous answers) statement than using DROP TABLE statement.
Step 1:
DROP TABLE GGroup;
Step 2:
CREATE TABLE GGroup(
GroupId NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
ClassRoom varchar(7),
GroupNum number(5),
C_Code varchar(6),
C_Name varchar(35), Field
Teacher varchar(30)
);
Once both the steps are followed, you can then insert duplicate values without getting any ORA-00001: unique constraint error.
Table GGroup defines column ClassRoom as the primary key. This explicitly disallows duplicates in this column. Your code fails because you are trying to insert a record with ClassRoom 'A/3/54', while another record already exists in the tabe with the same value in that column.
Possible options:
change the primary key of the column to something else, that better represents your use case
change the value of ClassRoom in the newly inserted record to a value that does not yet exist in the table
ignore this error: since both records seem to be complete duplicates, that might be your best pick here
In the first table you declared the ClassRoom field as primary key
primary key (ClassRoom)
What that means is that the ClassRoom field is the unique identifier for the row, and that means it has to be unique. I'm not sure what your data is supposed to represent there, but if you mean that there are groups that are meeting in those class rooms, you might not want to use the class room as a unique identifier, as groups might reuse the same class room. How about creating a separate unique identifier for the table, like this (from your question looks like you are using Oracle, right?)
CREATE TABLE GGroup(
GGGroupId NUMBER GENERATED by default on null as IDENTITY,
ClassRoom varchar(7),
GroupNum number(5),
C_Code varchar(6),
C_Name varchar(35), Field
Teacher varchar(30)
);
Primary Keys, must be unique, your classroom is set as primary key, so you are not allowed to add it twice.
set another variable (like an increasing id) as primary key, than you are able to add the room more often.
the question is why would you add the same information twice?
if you want to fill in the rooms into your timetable table, you don't need to add a room more than once to the GGroup
You need to add an other column primary key, like an incremented ID, and create a sequence to increment your ID. you can do it with a trigger for exemple like that:
CREATE TABLE GGroup(
Id NUMBER(10) NOT NULL,
ClassRoom varchar(7),
GroupNum number(5),
C_Code varchar(6),
C_Name varchar(35), Field
Teacher varchar(30)
);
You need to add a PRIMARY KEY constraint:
ALTER TABLE GGroup
ADD (
CONSTRAINT GGroup_pk PRIMARY KEY (Id)
);
You need also to create a SEQUENCE that will be utilized to generate the unique, auto incremented value.
CREATE SEQUENCE GGroup_sequence;
Finaly you need a trigger which is a stored procedure that is executed when the insert occured:
CREATE OR REPLACE TRIGGER GGroup_on_insert
BEFORE INSERT ON GGroup
FOR EACH ROW
BEGIN
SELECT GGroup_sequence.nextval
INTO :new.Id
FROM dual;
END;
I'm writing a database in SQL Server, I have this schema
Basing on this, I've prepared UML diagram
I have written SQL code to create tables and alter them with foreign keys
CREATE TABLE Employee
(
Fname VARCHAR(20),
Minit CHAR(1),
Lname VARCHAR(30),
Ssn VARCHAR(9) CONSTRAINT pk_Employee PRIMARY KEY, -- pk key
Bdate DATE,
Address VARCHAR(30),
Sex CHAR(1),
Salary INT,
Super_ssn VARCHAR(9),
Dno INT,
CONSTRAINT chk_Employee_Ssn CHECK (LEN(Ssn)=9)
);
CREATE TABLE Department
(
Dname VARCHAR(30),
Dnumber INT CONSTRAINT pk_Department PRIMARY KEY, -- pk key
Mgr_ssn VARCHAR(9),
Mgr_start_date DATE,
CONSTRAINT chk_Department_MgrSsn CHECK (LEN(Mgr_ssn)=9)
);
CREATE TABLE Dept_locations
(
Dnumber INT,
Dlocation VARCHAR(30),
CONSTRAINT pk_Dept_locations PRIMARY KEY (Dnumber,Dlocation) -- pk key
);
CREATE TABLE Project
(
Pname VARCHAR(20),
Pnumber INT CONSTRAINT pk_Project PRIMARY KEY, -- pk key
Plocation VARCHAR(30),
Dnum INT
);
CREATE TABLE Works_on
(
Essn VARCHAR(9),
Pno INT,
Hours DECIMAL(7,2),
CONSTRAINT pk_WorksOn PRIMARY KEY (Essn,Pno), -- pk key
CONSTRAINT chk_WorksOn_Essn CHECK (LEN(Essn)=9)
);
CREATE TABLE Dependent
(
Essn VARCHAR(9) ,
Dependent_name VARCHAR(20),
Sex CHAR(1),
Bdate DATE,
Relationship VARCHAR(15),
CONSTRAINT pk_Dependent PRIMARY KEY (Essn,Dependent_name), -- pk key
CONSTRAINT chk_Dependent_Essn CHECK (LEN(Essn)=9)
);
ALTER TABLE Dependent ADD
CONSTRAINT fk_Dependent_Essn FOREIGN KEY (Essn) REFERENCES Employee(Ssn)
ALTER TABLE Department ADD
CONSTRAINT fk_Department_MgrSsn FOREIGN KEY (Mgr_ssn) REFERENCES Employee(Ssn)
ALTER TABLE Employee ADD
CONSTRAINT fk_Employee_SuperSsn FOREIGN KEY (Super_ssn) REFERENCES Employee(Ssn),
CONSTRAINT fk_Employee_Dno FOREIGN KEY (Dno) REFERENCES Department(Dnumber)
ALTER TABLE Dept_locations ADD
CONSTRAINT fk_DeptLocations_MgrSsn FOREIGN KEY (Dnumber) REFERENCES Department(Dnumber)
ALTER TABLE Project ADD
CONSTRAINT fk_Project FOREIGN KEY (Dnum) REFERENCES Department(Dnumber)
ALTER TABLE Works_on ADD
CONSTRAINT fk_WorksOn_Essn FOREIGN KEY (Essn) REFERENCES Employee(ssn),
CONSTRAINT fk_WorksOn_Pno FOREIGN KEY (Pno) REFERENCES Project(Pnumber)
Now when I'm trying to insert some data into those tables,
example:
INSERT INTO Employee(Fname, Minit, Lname, SSn, Bdate, Address, Sex, Salary, Super_ssn, Dno)
VALUES ('John', 'B', 'Smith', '123456789', '1965-01-09', 'Lazy Town', 'M', 30000, '333445555', 5);
I realize that most of those tables requires foreign keys to any other tables, which makes the insertion very weird. To insert something, I must already have other data in the database. It's like vicious circle.
My question: is there any method to insert records in effective and safe way, without errors caused by non existing records?
EDIT:
I have tried to insert some data for any of those tables, using those commends (one after another, not all at once). Every time it failed, because foreign keys can't find records in other tables :<
INSERT INTO Employee(Fname,Minit,Lname,SSn,Bdate,Address,Sex,Salary,Super_ssn,Dno) VALUES
('John','B','Smith','123456789', '1965-01-09', 'Lazy Town', 'M', 30000, '333445555',5);
INSERT INTO Dept_locations(Dnumber,Dlocation) VALUES
(1, 'Houston');
INSERT INTO Department(Dname,Dnumber,Mgr_ssn,Mgr_start_date) VALUES
('Research', 5, '333445555', '1988-05-22');
INSERT INTO Dependent(Essn,Dependent_name,Sex,Bdate,Relationship) VALUES
('333445555', 'Alice', 'F', '1986-04-05', 'Daughter');
INSERT INTO Works_on(Essn,Pno,Hours) VALUES
('333445555', 3, 10);
INSERT INTO PROJECT(Pname,Pnumber,Plocation,Dnum) VALUES
('ProductX', 1, 'Bellaire', 5);
Foreign keys are used for data consistency. These keys define relations between tables and you can see relations as a chain. So in order to add data to the structure, start by the beginning of the chain. For example, add the department first then add the employee into the department. There is no way to insert data in any linked table with a foreign key without following the chain.
Unless
If you drop/delete foreing keys, you can do inserts. But be careful! You can add the employee into the department which does not exist.
Edit:
fk_Department_MgrSsn and fk_Employee_Dno are circular references. You must delete one of them, possibly the fk_Department_MgrSsn and add a column to the Employee table named like "isManager" to carry the manager information.
I agree with #MertGülsoy, however, I need to note things out,
Your schema has 3 Main PK ( Employee.SSN, Department.Dnumber, Project.Pnumber). From these three PK, you'll have multiple relations that linked to them.
In SQL Server, the easiest method for your assignment is to create the tables first, then insert the data, then create the relations, which SQL Server will also check the existed data for the foreign keys.
Let's take a look on the foreign key Employee table (to understand the relations) :
Employee table
[PK] SSN
[FK] Super_ssn
[FK] Dno
Each employee should have a unique SSN, but can share the same Super_ssn. I think the Super_ssn meant to be the Supervisor SSN. So, in this case, the supervisor needs to have a record in employees as well in order to relate to him. So, each Supervisor SSN you use in Super_ssn must existed in SSN as well (a separate record). Same thing on Dno, which related to Department table PK. each Dno, must be existed in Department.Dnumber as well.
So, the trick that you want to do in inserting Employees is to insert first the supervisor record, then insert each employee that is related to that supervisor record.
For instance :
INSERT INTO Employee(Fname,Minit,Lname,SSn,Bdate,Address,Sex,Salary,Super_ssn,Dno) VALUES
('John','B','Smith','123456789', '1965-01-09', 'Lazy Town', 'M', 30000, '333445555',NULL);
John's supervisor SSN is not existed, those, the relation will cause an error, and to fix it you need to insert supervisor first, then John, like this :
INSERT INTO Employee(Fname,Minit,Lname,SSn,Bdate,Address,Sex,Salary,Super_ssn,Dno) VALUES
('Mike','A','Tyson','333445555', '1965-01-09', 'Lazy Town', 'M', 50000, NULL,NULL),
('John','B','Smith','123456789', '1965-01-09', 'Lazy Town', 'M', 30000, '333445555',NULL);
Mike's Super_ssn has a NULL value, as there is no supervisor linked to Mike (he's the boss).
So, now your Super_ssn link is correct because 333445555 is existed on SSN, hint, Mike's SSN.
Note that we gave Dno NULL, because we haven't created the Department table yet.
You'll do the same with the rest of the tables, just ensure that each foreign key is existed on the main PK. As for your current INSERT data some of them lakes that.
Foreign keys are there for something. If you want to be able to insert invalid data, then why you need foreign keys at all? Just delete them :)
However, foreign keys has state - they can be trusted or not. If you want to disable a foreign key, you can do it like this:
ALTER TABLE MY_TABLE NOCHECK CONSTRAINT FK_MY_TABLE_SOME_COLUMN
You can also do this for all foreign keys in the table:
ALTER TABLE MY_TABLE NOCHECK CONSTRAINT ALL
This will preserve the foreign key, so you can find out where this column points to, but the data will not be validated and you can insert rows with missing values.
When you are ready to re-enable your foreign keys (if you want to), you can do it like this:
ALTER TABLE MY_TABLE CHECK CONSTRAINT FK_MY_TABLE_SOME_COLUMN
Please note, that this command may fail if there are rows with invalid data.
About the efficiency, the most effective way to insert data usually is BULK INSERT. If you do not specify CHECK_CONSTRAINTS, it will not obey your foreign keys when inserting data, thus it will make them untrusted. However, in your example you are using simple insert statements, so I guess you do not look for ways to insert millions of rows at once. In this case foreign keys should not affect your insert in terms of efficiency (except the inconvenience with the data consistency).
See if data is populated from UI or web page level then simply design the page like that,
For Example to insert record in Employee,SSN and DNO both will be dropdown,so there is no question of Garbage data.
Suppose data is inserted from some other source then you can create Instead of Trigger.
If you bulk insert then you can use Exists clause to insert only those records whose FK value exists.
Other way of handling is to use TRY- CATCH.
So depending upon situation you can use any of those.
Don't disable FK relation.
I have the following tables:
--Competition tables
CREATE TABLE IF NOT EXISTS Tr.Competitions(
competition_id SERIAL PRIMARY KEY,
competition_name text NOT NULL
);
CREATE TABLE IF NOT EXISTS Tr.CompetitionsQuestions(
competition_id int NOT NULL,
question_id int NOT NULL,
FOREIGN KEY (competition_id) REFERENCES Tr.Competitions(competition_id),
FOREIGN KEY (question_id) REFERENCES Tr.Questions(question_id)
);
--Questions tables
CREATE TABLE IF NOT EXISTS Tr.Questions(
question_id SERIAL PRIMARY KEY,
question_text text NOT NULL
);
CREATE TABLE IF NOT EXISTS Tr.MultiQuestions(
possible_answers text ARRAY NOT NULL,
correct_answer int NOT NULL
) INHERITS(Tr.Questions);
I try to insert some dummy data into Tr.CompetitionQuestions like so:
--Test Fixtures
INSERT INTO Tr.MultiQuestions (question_text, possible_answers, correct_answer)
VALUES ('Which of the following is awesome?', '{"Indian Food","Soccer","All the above"}', 2);
INSERT INTO Tr.Competitions(competition_name)
VALUES ('Awesome Competition');
INSERT INTO Tr.CompetitionsQuestions(competition_id, question_id)
VALUES ((SELECT competition_id FROM Tr.Competitions WHERE competition_id=1),
(SELECT question_id FROM Tr.Questions WHERE question_id=1));
Having these stored in an .sql file and running \i some.sql is gerenating the following error. How do I add a question foreign key to the CompetitionsQuestions table?
ERROR: insert or update on table "competitionsquestions" violates foreign key constraint "competitionsquestions_question_id_fkey"
DETAIL: Key (question_id)=(1) is not present in table "questions".
Seems like a weird error since SELECT * FROM tr.questions WHERE question_id=1 actually gives me the stored multiquestion row.
EDIT:
Simplifying to:
INSERT INTO Tr.CompetitionsQuestions(competition_id, question_id)
VALUES (1, 1);
gives me the same error;
(Assuming, from comments, that you're using PostgreSQL's table inheritance features, since your question doesn't really contain full info about the schema and how you populate its contents):
Foreign keys don't apply across all members of an inheritance tree. They can only be to the specific table.
The same is true of a UNIQUE constraint or PRIMARY KEY.
You can see what a foreign key constraint will see in a table if you:
SELECT * FROM ONLY thetable;
The ONLY keyword tells PostgreSQL not to include child tables. That's what's used in foreign key constraint checks.
Table A
(
Table_A_ID int
)
Table B
(
Table_B_ID int
Value int
)
Say I want to insert data into Table B, where 'Value' would be the same as a Table_A_ID.
How would I make a constraint or check that the data actually exists in the table on insertion?
You probably need to enforce data integrity not only on INSERT into Table B, but also on UPDATE and DELETE in both tables.
Anyway options are:
FOREIGN KEY CONSTRAINT on Table B
TRIGGERs on both tables
As a last resort if for some reason 1 and 2 is not an option STORED PROCEDUREs for all insert, delete update operations for both tables
The preferred way to go in most cases is FOREIGN KEY CONSTRAINT.
Yap, I agree with #peterm.
Cause, if your both Table_A_ID and Table_B_Id are primary keys for both tables, then you don't even need two tables to store the value. Since, your two tables are seems to be on 'one-to-one' relationship. It's one of the database integrity issues.
I think you didn't do proper normalisation for this database.
Just suggesting a good idea!
I found this example which demonstrates how to setup a foreign key constraint.
Create employee table
CREATE TABLE employee (
id smallint(5) unsigned NOT NULL,
firstname varchar(30),
lastname varchar(30),
birthdate date,
PRIMARY KEY (id),
KEY idx_lastname (lastname)
) ENGINE=InnoDB;
Create borrowed table
CREATE TABLE borrowed (
ref int(10) unsigned NOT NULL auto_increment,
employeeid smallint(5) unsigned NOT NULL,
book varchar(50),
PRIMARY KEY (ref)
) ENGINE=InnoDB;
Add a constraint to borrowed table
ALTER TABLE borrowed
ADD CONSTRAINT FK_borrowed
FOREIGN KEY (employeeid) REFERENCES employee(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
NOTE: This tells MySQL that we want to alter the borrowed table by adding a constraint called ‘FK_borrowed’. The employeeid column will reference the id column in the employee table – in other words, an employee must exist before they can borrow a book.
The final two lines are perhaps the most interesting. They state that if an employee ID is updated or an employee is deleted, the changes should be applied to the borrowed table.
NOTE: See the above URL for more details, this is just an excerpt from that article!
Create a foreign key constraint on the column 'Value' on table B that references the 'Table_A_ID' column.
Doing this will only allow values that exist in table A to be added into the 'Value' field of table B.
To accomplish this you first need to make Table_A_ID column the primary key for table A, or it at least has to have some sort of unique constraint applied to it to be a foreign key candidate.
BEGIN TRANSACTION -- REMOVE TRANSACTION AND ROLLBACK AFTER DONE TESTING
--PUT A PRIMARY KEY ON TABLE A
CREATE TABLE A
( Table_A_ID int CONSTRAINT PK_A_Table_A_ID PRIMARY KEY)
--ON VALUE ADD A FOREIGN KEY CONSTRAINT THAT REFERENCEs TABLE A
CREATE TABLE B
( Table_B_ID int,
[Value] int CONSTRAINT FK_B_Value_A REFERENCES A(Table_A_ID)
)
-- TEST VALID INSERT
INSERT A (Table_A_ID) VALUES (1)
INSERT B (Table_B_ID, [Value]) VALUES (1,1)
--NOT ALLOW TO INSERT A VALUE THAT DOES NOT EXIST IN A
--THIS WILL THROW A FOREIGN KEY CONSTRAINT ERROR
INSERT B (Table_B_ID, [Value]) VALUES (1,2) -- 2 DNE in table A
ROLLBACK
Note: there is no magic to 'FK_B_Value_A' or 'PK_A_Table_A_ID' it simply a naming convention and be called anything. The syntax on the foreign key and primary key lines work like this:
column-definition CONSTRAINT give-the-constraint-a-name REFERENCES table-name ( table-column )
column-definition CONSTRAINT give-the-constraint-a-name PRIMARY KEY
How to enforce a constraint of foreign key on columns of same table in SQL while entering values in the following table:
employee:
empid number,
manager number (must be an existing employee)
Oracle call this a self-referential integrity constraint. The documentation is here for a description,
You create a self-referential constraint in the same manner you would a normal one:
alter table employees
add constraint employees_emp_man_fk
foreign key ( manager_no )
references employees ( emp_id )
on delete set null
;
I'm assuming that your manager_no is nullable. I've added set null here as a delete cascade would probably wipe out a significant amount of your table.
I can't think of a better way of doing this. Deleting a manager should not result in the deletion of all their employees so you have to set null and have a trigger on the table to alert you to anyone with no manager.
I always like this site, which is good for simple references. and don't forget to have an index on the FK as well or Tom will yell at you :-).
One can also utilise standard Oracle syntax to create a self-referential FK in the create table statement, which would look like the following.
create table employees
( emp_id number
, other_columns ...
, manager_no number
, constraint employees_pk
primary key (emp_id)
, constraint employees_man_emp_fk
foreign key ( manager_no )
references employees ( emp_id )
on delete set null
);
EDIT:
In answer to #popstack's comment below:
Whilst you can do this in one statement not being able to alter a table is a fairly ridiculous state of affairs. You should definitely analyze a table that you're going to be selecting from and you will still want an index on the foreign key ( and possibly more columns and / or more indexes ) otherwise whenever you use the foreign key you're going to do a full table scan. See my link to asktom above.
If you're unable to alter a table then you should, in descending order of importance.
Find out how you can.
Change your DB design as a FK should have an index and if you can't have one then FKs are probably not the way to go. Maybe have a table of managers and a table of employees?
SELF REFERENCES QUERY...
Alter table table_name ADD constraints constraints_name foreign key(column_name1,column_name2..) references table_name(column_name1,column_name2...) ON DELETE CASCADE;
EX- ALTER TABLE Employee ADD CONSTRAINTS Fr_key( mgr_no) references employee(Emp_no) ON DELETE CASCADE;
CREATE TABLE TABLE_NAME (
`empid_number` int ( 11) NOT NULL auto_increment,
`employee` varchar ( 100) NOT NULL ,
`manager_number` int ( 11) NOT NULL ,
PRIMARY KEY (`empid_number`),
CONSTRAINT `manager_references_employee`
FOREIGN KEY (`manager_number`) REFERENCES (`empid_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Hope it helps!