how I can allow duplicate values in sql? - sql

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;

Related

POSTGRESQL. Insert or update on table violates foreign key constraint

I am new in Posgresql. I have 5 tables and I am trying to INSERT properties to tables. When I tried to Insert 2nd time, I have this error in 'pgadmin'.
ERROR: insert or update on table "question" violates foreign key constraint "question_id_difficulty_fkey" DETAIL: Key (id_difficulty)=(9) is not present in table "difficulty". SQL state: 23503.
my schema is here
id SERIAL PRIMARY KEY,
name varchar
);
CREATE TABLE question (
id SERIAL PRIMARY KEY,
text varchar,
correct_answer varchar,
incorrect_answer1 varchar,
incorrect_answer2 varchar,
incorrect_answer3 varchar,
id_difficulty SERIAL REFERENCES difficulty(id),
id_category SERIAL REFERENCES category (id),
id_creator SERIAL REFERENCES game (id)
);
CREATE TABLE difficulty (
id SERIAL PRIMARY KEY,
name varchar
);
CREATE TABLE category (
id SERIAL PRIAMRY KEY,
name varchar
);
CREATE TABLE user (
id SERIAL PRIMARY KEY,
name varchar
)
You would need a corresponding entry in the difficulty table with an id of 9, so that a referencing id_difficulty column in the question table.
For example, if your difficulty table contained:
id | name
----+----------------
1 | easy
2 | reasonable
3 | difficult
4 | very difficult
5 | impossible
You could only set id_difficulty for rows in the question table to one of those id values. If you set 6, or 12 or anything other than 1 to 5, it would fail because the values are constrained by the values in the foreign key.
The id_difficulty, id_category and id_creator columns shouldn't be using serial, so these should have their defaults dropped:
ALTER TABLE question ALTER COLUMN id_difficulty DROP DEFAULT;
ALTER TABLE question ALTER COLUMN id_category DROP DEFAULT;
ALTER TABLE question ALTER COLUMN id_creator DROP DEFAULT;
Postgres now recommends using generated always as instead of serial. If you do this, then the types will align much more simply:
CREATE TABLE question (
id int generated always as identity PRIMARY KEY,
text varchar,
correct_answer varchar,
incorrect_answer1 varchar,
incorrect_answer2 varchar,
incorrect_answer3 varchar,
id_difficulty int REFERENCES difficulty(id),
id_category int REFERENCES category (id),
id_creator int REFERENCES game (id)
);
CREATE TABLE difficulty (
id int generated always as identity PRIMARY KEY,
name varchar
);
This makes what is happening much clearer. The data type for a foreign key reference needs to match the data type of the primary key. Postgres knows that serial is really int. But using generated always, it is obvious that they are the same.
In addition, generated always as is more consistent with standard SQL.

Check atribute value from another table using a foreign key in table creation

Is it possible to check the value of an attribute in a different table in table creation? For example I have this table ticket:
CREATE TABLE ticket
(
id_ticket_pk NUMBER(4) PRIMARY KEY,
hand_in_date DATE NOT NULL,
num_clothes NUMBER(4) NOT NULL,
deposite NUMBER (8,2) NOT NULL,
comment VARCHAR2(40),
tax NUMBER(5,3) NOT NULL,
status VARCHAR2(15) NOT NULL,
id_counter_fk1 NUMBER(4),
id_client_fk2 NUMBER(4),
CONSTRAINT ticket_id_counter_fk1
FOREIGN KEY (id_counter_fk1) REFERENCES empleado(id_employee_pk),
CONSTRAINT ticket_id_client_fk2
FOREIGN KEY(id_client_fk2) REFERENCES client(id_client_pk)
);
This table relates to the employee table which has an attribute called type that can be equal to C - for counter, S- for secretary etc... I would like to know if its possible to add a constraint in the creation of the table that verifies that the employee inserted has an employee.type = 'C' where employe.id_pk = ticket.id_counter_fk2. Or do I have to create an external function or client App that manages this?
You seem to be asking whether you can use the foreign keying mechanism to ensure that only people with the job title of "counter" can create support tickets.
The short answer is no, you can't have a foreign key on this table that checks the employee table pk for the value given in id_counter_fk1 and enforces that the employee type be C
You could do it several other ways, the most direct being a trigger that prevents the insert if the employee linked is not a C type, but the FK mechanism exists to ensure that a remote record exists or not, not that it exists and has particular properties

SQL constraint on a foreign key

I am having problems creating a constraint for a foreign key field, so that a foreign key can only be entered if that foreign key links to a row containing a specific attribute.
To give a better idea about what I mean, I have created the following example. The Employee entity table contains a Grade field, which can either be 'S' for a senior level employee, or 'J' for a junior level employee. In the Expenses table, I want to limit any entries into the ApprovedBy field to those EmpNo values that have a Grade field containing 'S' in the Employee table.
CREATE TABLE Employee
(EmpNo INT PRIMARY KEY,
FirstName VARCHAR(15),
LastName VARCHAR(15),
Grade CHAR(1),
CONSTRAINT chk_ValidGrade CHECK (Grade IN ('J','S'))
)
CREATE TABLE Expenses
(ExpenseId INT IDENTITY(1,1) PRIMARY KEY,
Amount FLOAT,
ApprovedBy INT FOREIGN KEY REFERENCES Employee(EmpNo),
)
I instinctively want to use a join, or other relational algebra function to do this. However, my understanding is that you can't use the SELECT function within a CHECK function, so I'm not sure how I would define the constraint.
As far as I know, you cannot use check constraint for this task. You have to use a trigger for insert and update in your Expenses table.

Check if data exists in another table on insert?

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

using self referencing in sql server

create table EMP(Eid int primary key)
insert into EMP values(11e3)
--self referencing
alter table EMP
add constraint fk_EMP_Eid
foreign key (Eid) references EMP(Eid)
--now insert
insert into EMP values(12e2)
But, this insert should fail, because there is no previous value of Eid=1200 in the EMP table, so when the foreign key will reference this column , then it would not find the value, hence should fail the insert .
but why does it succeeds?
The column references itself.
So the addition of the row itself guarantees that there is a matching row. This constraint can never fail.
In fact looking at the execution plan SQL Server realises this and doesn't even bother checking it. There is no assert operator present.
If we create a more typical Employee table there are different plans for the inserts that can violate the constraint as below.
create table EMP2(Eid int primary key, boss_id int null);
alter table EMP2 add constraint fk_EMP2_Eid
foreign key (boss_id) references EMP2(Eid)
insert into EMP2 values(1,null) /*Can't violate constraint as NULL*/
insert into EMP2 values(2,1) /*Can violate constraint as NOT NULL*/
If you try multiple rows a blocking spool is added to the plan so the constraints aren't checked until all rows are inserted.
insert into EMP2 values (3,2),(4,3) /*Can violate constraint - multiple rows*/
And just for completeness as it was raised in the comments, looking at the case when the insert is to a table with a FK referencing a different one...
CREATE TABLE EmpSalaryHistory
(
Eid INT NOT NULL REFERENCES EMP(Eid),
EffectiveDate DATETIME NOT NULL,
Salary INT,
PRIMARY KEY (Eid,EffectiveDate)
)
INSERT INTO EmpSalaryHistory
VALUES (1,GETDATE(),50000),
(2,GETDATE(),50000)
In this instance no spool is added to the plan it can check as it inserts each row rather than all at the end so it can rollback earlier in the event that a row fails (the end result will be the same)
Your FK column fk_EMP_Eid probably allows nulls, therefore the relationship isn't required to exist, but if you do try to put a value in that column, then SQL Server will verify that the FK is valid or else it will error.
I created this example for self refernce key for ms sql server
CREATE TABLE Category (
CategoryId int IDENTITY(1,1) not null,
ParentId int null,
CONSTRAINT PK_CategoryId PRIMARY KEY CLUSTERED (CategoryId),
CONSTRAINT FK_ParentId FOREIGN KEY (ParentId) REFERENCES Category(CategoryId),
Title nvarchar(255) NOT NULL
);
insert into category(title)
values
('category1');
insert into category(title,parentid)
values
('category2',1);