How to place unique contraint on multiple column - sql

EmpID DeptID
1 1
1 2
2 1
3 2
4 5
5 2
1 1
2 1
I would like to have a constraint that will make sure that the pair of field is always unique ,such data as last two shown in the example should not be insert-able into the table .in the above table
please note that last two rows are duplicates ,I would like to prevent such data from occuring .
How do I achieve this in sqlserver 2005.Thanks

ALTER TABLE <YourTable, sysname, Emp>
ADD CONSTRAINT <YourConstraintName, sysname, uix>
UNIQUE NONCLUSTERED (EmpID,DeptID)
(Paste into SSMS and use (CTRL + Shift + M))
Or to do this at table creation and as it sounds as though there is no alternative key use.
CREATE TABLE EMPLOYEE_DEPARTMENT(
EmpID int NOT NULL REFERENCES EMPLOYEE(EmpID),
DeptID int NOT NULL REFERENCES DEPARTMENT(DeptID),
CONSTRAINT PK_EMPLOYEE_DEPARTMENT PRIMARY KEY CLUSTERED (EmpID ASC,DeptID ASC)
)

After you've gone through and removed the duplicates, run the following (substituting appropriate names)
ALTER TABLE table ADD CONSTRAINT UQ_EmpID_DeptID UNIQUE (EmpID,DeptID)
Or when creating your table:
CREATE TABLE T1 (
EmpID int not null,
DeptID int not null,
/* Other Columns */
constraint PK_T1 PRIMARY KEY (EmpID,DeptID)
)
(May as well make it the primary key, unless you've got another one in the table)

ALTER TABLE dbo.YOURTABLE ADD CONSTRAINT IX_YOURTABLE UNIQUE NONCLUSTERED (EmpID, DeptID)

select empID, deptID from table
group by empID, deptID
EDIT:
If you are saying this data must be unique in table itself, i.e. The insertion of duplicates should not be allowed, then you need to define a composite key (empID, deptID) on this table.
alter table <tablename> add constraint <compositekeyname> primary key (empID, deptID)

Related

Foreign key without correspondence in the referenced table

I'm trying to come up with a solution for an exercise in which I have to create 3 tables: one for employees, one for projects, and one for projects and employees, in which I have to insert the employee's ID and associate with a project ID. In the project_employee table, since it has only 2 columns that reference other tables, I thought I could set them bot as foreign keys, like this:
CREATE TABLE employee_project
(
id_employee numeric FOREIGN KEY REFERENCES employee(id_employee),
id_project numeric FOREIGN KEY REFERENCES project(id_project)
)
Then I stumbled upon a problem: when inserting values on the 3 tables, I noticed that one of the employee's ID number was 4, but on the table employee there was no line with ID 4. Of course, this line wasn't created, but I want to understand: is there a way I could create a line whose ID has no matching record in the referenced table? Could it be a possible mistake in the question, or is there something I'm missing? Thanks in advance for your time!
If there is no rows in employee table with id_employee value 4 then there should not be rows in employee_project table with id_employee value 4. SQL Server will give you an error like below:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__employee__id__75F77EB0". The conflict occurred in database "test", table "dbo.employee", column 'id_employee'.
But if you want to create employee_project with composite primary key on both the column you can try this:
CREATE TABLE employee_project
(
id_employee int not null,
id_project int not null,
primary key(id_employee, id_project )
)

Allowing only unique combination in sql table

I'm trying to create a sql table in net frame work in VS that has room and user id ,but I want that only one of each combination can exist in the table:
Want:
room --- user id
1 2
1 3
3 2
2 1
1 1
3 1
Dont want:
room --- user id
1 2
1 2
how can I make it so that only unique combination can be entered?
You can enforce uniqueness using a unique constraint or index:
create unique index unq_t_room_userid on t(room, user_id);
or:
alter table t add constraint unq_t_room_userid
unique (room, user_id);
Looks like you want Room, UserId to be the PRIMARY KEY on that table.
CREATE TABLE Occupancy
(
RoomId INT NOT NULL
,UserId INT NOT NULL
,CONSTRAINT PK_Occupancy PRIMARY KEY CLUSTERED (RoomId,UserId)
)
When you try to insert a duplicate value:
INSERT dbo.Occupancy (RoomId,UserId)
VALUES
(1,1)
,(1,2)
,(1,1)
GO
You will get a message like this:
Violation of PRIMARY KEY constraint 'PK_Occupancy'. Cannot insert
duplicate key in object 'dbo.Occupancy'. The duplicate key value is
(1, 1).

Best way to delete duplicate rows in an intersection table based on foreign key column

I'm looking for a way to delete dupicate rows from an intersection table based on a foreign key from one of the tables from the opposite ends of the intersection table. For the sake of clarity, I'll say based on a foreign key value from the intersection table on the left 'tableA'.
CREATE TABLE tableA
(
link varchar(64) NOT NULL PRIMARY KEY,
name varchar(64) NOT NULL
)
CREATE TABLE tableB
(
link varchar(64) NOT NULL PRIMARY KEY,
name varchar(64) NOT NULL
)
CREATE TABLE tableA_AND_tableB--Intersection Table
(
link varchar(64) NOT NULL PRIMARY KEY,
LtableA varchar(64) references tableA(link),
LtableB varchar(64) references tableB(link)
)
Basically, I want to delete all duplicate rows in the intersection table based on the 'LtableA' foreign key field. For instance: Say I have 20 duplicates of 'LtableA = id20140722' in 'tableA_AND_tableB', how do I go about deleting all the rows matching the value 'id20140722' in 'tableA_AND_tableB' without affecting anything else?
Hope my question makes sense.
Delete from tableA_AND_tableB where LtableA = 'id20140722'
This will remove all rows from that table sepcifically with that ID. Alternatively you can see this question for something that will delete all duplicates. Though that answer will keep either the first or last duplicate.
If you want to delete duplicates but still keep one distinct copy of each row:
WITH t AS (
SELECT ROW_NUMBER() OVER(PARTITION BY LtableA, LtableB ORDER BY link) row_num
FROM tableA_AND_tableB
)
DELETE
FROM t
WHERE row_num > 1
AND LtableA = 'id20140722'

How do I create a composite foreign key going backwards down a relationship?

Sorry about the title, couldn't think of a better way to write it.
Here's my problem...
I have 2 tables in my database [Drawings] and [Revisions];
[Drawings] 1-----* [Revisions]
ProjectId(pk) ProjectId(pk)(fk)
DrawingNo(pk) DrawingNo(pk)(fk)
RevisionNo(pk)
LatestRevision
There is a foreign key in [revisions] referencing [drawings] on [ProjectId] and [DrawingNo].
I need to implement a way of enforcing that the drawings latest revision number equals a corresponding revision number in the revisions table:
... WHERE [Drawings].[LatestRevision] NOT IN (
SELECT [RevisionNo]
FROM [Revisions]
WHERE [Drawings].[ProjectId] = [Revisions].[ProjectId]
AND [Drawings].[DrawingNo] = [Revisions].[DrawingNo])
How would I put something like this into a foreign key?
I need this to work on sql server 2008 express onwards.
Thanks in advance for any help!
Schema:
TABLE Drawings
( ProjectId varchar,
DrawingNo varchar,
LatestRevisions varchar,
...other columns
PRIMARY KEY(ProjectId, DrawingNo)
)
TABLE Revisions
( ProjectId varchar,
DrawingNo varchar,
RevisionNo varchar,
...other columns
PRIMARY KEY(ProjectId, DrawingNo, RevisionNo)
FOREIGN KEY(ProjectId, DrawingNo) REFERENCES (Drawings(ProjectId, DrawingNo))
)
Drawing 'A' can have revision '1', and Drawing 'B' can have a different revision '1',
Revision number by itself is not unique
I will take the schema as follows:
TABLE drawings
( projectid integer,
drawingno integer,
latestRevision integer,
primary key (projectid, drawingno)
)
TABLE revisions
( revisionno integer primary key,
projectid integer,
drawingno integer,
foreign key (projectid, drawingno)
references (drawings (projectid, drawingno))
)
In this case, I would issue:
ALTER TABLE drawings
ADD FOREIGN KEY (latestRevision)
REFERENCES (revisions(revisionNo))
This would mean that every revisions.revisionNo is unique and the column drawings.latestRevision is a foreign key that references the primary key of revisions table, that is, revisionNo.
Please let me know if there are any changes to the schema you have.
Also, the foreign key is enforced only if it is referencing a primary key of another table. If revisions.revisionno is not a primary key or if the primary key constraint is disabled on this column, then the ALTER TABLE .. ADD FOREIGN KEY statement is bound to return an error.
The following structures replaces your tables with views and looks similar to what you describe, except it's instead maintained behind the scenes rather than being an explicit foreign key. I don't know what operations you'd want to support on Revisions, at the moment I only support INSERT:
create table dbo._Drawings (
ProjectId int not null,
DrawingId int not null,
constraint PK_Drawings PRIMARY KEY (ProjectID,DrawingID)
)
go
create table dbo._Revisions (
ProjectID int not null,
DrawingID int not null,
RevisionNo int not null,
_PreviousRevision as CASE WHEN RevisionNo > 1 THEN RevisionNo - 1 END persisted,
_NextRevision int null,
constraint PK_Revisions PRIMARY KEY (ProjectID,DrawingID,RevisionNo),
constraint FK_Revisions_Drawings FOREIGN KEY (ProjectID,DrawingID)
references _Drawings (ProjectID,DrawingID),
constraint CK_RevisionNos CHECK (RevisionNo >= 1),
constraint UK_Revisions_Previous UNIQUE (ProjectID,DrawingID,_PreviousRevision),
constraint UK_Revisions_Next UNIQUE (ProjectID,DrawingID,_NextRevision),
constraint FK_Revisions_Previous FOREIGN KEY (ProjectID,DrawingID,_PreviousRevision)
references _Revisions (ProjectID,DrawingID,RevisionNo),
constraint FK_Revisions_Next FOREIGN KEY (ProjectID,DrawingID,_NextRevision)
references _Revisions (ProjectID,DrawingID,RevisionNo)
)
The above two tables are the "backing store" for the data. The _Revisions table ensures that the revision sequences are strictly monotonically increasing from 1. Each row maintains a foreign key to its immediate preceding and succeeding revisions, except the first and last, for which NULLs substitute (but the unique constraints ensure only one of each exists for each ProjectID,DrawingID combination.
create view dbo.Drawings
with schemabinding
as
select
d.ProjectID,
d.DrawingID,
r.RevisionNo as LatestRevision
from
dbo._Drawings d
left join
dbo._Revisions r
on
d.ProjectId = r.ProjectID and
d.DrawingId = r.DrawingID and
r._NextRevision is null
The above view mimics your asked for Drawings table and would be used for any actual data access. If you wanted to enforce an invariant that each drawing must have at least one revision, you could switch the left join to an inner join and make this an indexed view. You'd need to add a trigger to support INSERTs, in much the same way as the below does for Revisions, which then populates both tables.
create view dbo.Revisions
with schemabinding
as
select
ProjectID,
DrawingID,
RevisionNo
from
dbo._Revisions
This view creates the impression that Revisions is as simple as in your query
create trigger T_Revisions_I
on dbo.Revisions
instead of insert
as
;with SplitData as (
select ProjectID,DrawingID,RevisionNo,RevisionNo-1 as Prev, Seq
from inserted cross join (select 1 union all select 2) t(Seq)
)
merge into dbo._Revisions r
using SplitData s
on
r.ProjectID = s.ProjectID and
r.DrawingID = s.DrawingID and
(
(s.Seq = 1 and r.RevisionNo = s.Prev) or
(s.Seq = 2 and r.RevisionNo = s.RevisionNo)
)
when matched and s.Seq = 1
then update set _NextRevision = s.RevisionNo
when not matched and s.Seq = 2
then insert (ProjectID,DrawingID,RevisionNo) values (s.ProjectID,s.DrawingID,s.RevisionNo)
;
And finally, this trigger is responsible for maintaining the _Revisions structure in the way that the constraints I created above require. The trick is that we use a MERGE statement so that at the same time as we insert the new row, we also update the previous row so that it's _NextRevision column is no longer null and references the row that we're inserting.
More triggers can be added to support more advanced usage.

ORA-02437: cannot validate <name> - primary key violated

I have a table:
CREATE TABLE MY_TABLE (
MY_ID NUMBER NOT NULL,
COLUMN_1 NUMBER,
COLUMN_2 NUMBER
);
ALTER TABLE MY_TABLE ADD CONSTRAINT PK_FOO PRIMARY KEY (MY_ID);
at a later point, when executing the following sql, I get an error:
ALTER TABLE MY_TABLE DROP PRIMARY KEY DROP INDEX;
ALTER TABLE MY_TABLE ADD CONSTRAINT PK_FOO PRIMARY KEY (MY_ID)
ORA-02437: cannot validate PK_FOO - primary key violated
My table only contains 3 entries all with a different primary key which is also not null.
Anyone has an idea what this could be?
Thanks,
Peter
My table only contains 3 entries all with a different primary key which is also not null.
You must forgive a certain amount of scepticism on our part. Because that error definitely indicates a duplicate value.
What you need to do is use the exceptions clause. This will show you the ROWIDs of the records which are violating your constraint. You may need to create the target table: by default the script creates a table called EXCEPTIONS:
SQL> ALTER TABLE MY_TABLE ADD CONSTRAINT PK_FOO PRIMARY KEY (MY_ID);
ALTER TABLE MY_TABLE ADD CONSTRAINT PK_FOO PRIMARY KEY (MY_ID)
*
ERROR at line 1:
ORA-02437: cannot validate (APC.PK_FOO) - primary key violated
SQL> #%ORACLE_HOME%\rdbms\admin\utlexpt1.sql
Table created.
SQL> ALTER TABLE MY_TABLE ADD CONSTRAINT PK_FOO PRIMARY KEY (MY_ID)
2 exceptions into exceptions
3 /
ALTER TABLE MY_TABLE ADD CONSTRAINT PK_FOO PRIMARY KEY (MY_ID)
*
ERROR at line 1:
ORA-02437: cannot validate (APC.PK_FOO) - primary key violated
SQL> select * from exceptions
2 /
ROW_ID OWNER TABLE_NAME CONSTRAINT
------ ----- ---------- ----------
AABQXcAAEAAAXUPAAD APC MY_TABLE PK_FOO
AABQXcAAEAAAXUPAAB APC MY_TABLE PK_FOO
SQL>
Edit
You need to figure out what is different between your install code and the simplification you posted here. The chances are you have one or more INSERT statements which are accidentally executed more than once while the constraint is not in force. Adding the EXCEPTIONS INTO clause to your code might help you track it down.
from here
Cause: You tried to tried to enable a
primary key constraint, but the
columns in the primary key either
contained NULL values or duplicates..
The maim reason of violation of primary ki is the atrrbute you making is nullable or you have some dupliactes in table for that id or attribute
create table client_master
(
client_no varchar2(6),
client_name varchar2(20),
city varchar2(25),
state varchar2(15),
pin number(6),
balance_due number(10,2));
for e.g,
after inserting values
0008 Mukul NYCT NYC 199560 2500
0006 Rukmini bombay maharastra 100001 0
0007 Krishna mathura up 900050 100000
0008 Mukul NYCT NYC 199560 2500
or your id is nullable
so just MODIFY THE ATTRIBUTE is and set to NOT NULL
also remove duplicates if any
DELETE client_master
WHERE rowid NOT IN
(SELECT MAX(rowid)
FROM client_master
GROUP BY client_no,client_name,city,state,pin,balance_due);
then you we will be able to add primary key to client _no
Are 2 primary keys identical?
This error is usually thrown when you try to create/enable a primary key on a table
I'm upvoting APC's answer, but since you seem to have some problems implementing it, could you just post the results of this query:
select my_id, count(*) from my_table group by my_id having count(*) >1
This will give us (and you) some idea of the problematic keys.