I have table dbo.Students_Old with columns :
Name(varchar), DocNum(int), Group(varchar), Form(varchar).
It have no primary key and I need to normalize this table. So I am going to make three tables:
dbo.Students(StudentId(int primary key), Name(varchar), Group(int fk),
Form(int fk),
dbo.Forms(FormId(int pk), FName(varchar)), dbo.Groups(GroupId(int pk),
GName(varchar)).
And also I need to fill all this tables with data from dbo.Students_Old. My code is:
CREATE TABLE dbo.Groups(GroupId int IDENTITY(1,1) PRIMARY KEY, GName nvarchar(10));
GO
INSERT INTO dbo.Groups(GName)
select Group
from dbo.Students_Old
group by Group
GO
CREATE TABLE dbo.Forms(FormId int IDENTITY(1,1) PRIMARY KEY, Form nvarchar(20));
INSERT INTO dbo.Forms(Form)
select Form
from dbo.Students_Old
group by Form
GO
CREATE TABLE dbo.Students (StudentId int PRIMARY KEY, Name nvarchar(50),
Form int NOT NULL,
Group int NOT NULL,
CONSTRAINT Form FOREIGN KEY(StudentId) REFERENCES dbo.Forms(FormId),
CONSTRAINT Grup FOREIGN KEY(StudentId) REFERENCES dbo.Groups(GroupId));
GO
INSERT INTO dbo.Students(StudentId, Name, Form, Group)
select DocNum, Name, f.FormId, g.GroupId
from dbo.Students_Old s
join dbo.Forms f on s.Form=f.Form
join dbo.Groups g on s.Group=g.GName
Also Students_Old.DocNum is unique.
Tables creates normaly, but on the insert statement i have an error:
The INSERT statement conflicted with the FOREIGN KEY constraint "Form". The conflict occurred in database "DBNames", table "dbo.Forms", column 'FormId'.
Help me please.
Execute the below query on a new database
CREATE TABLE dbo.Groups(GroupId int IDENTITY(1,1) PRIMARY KEY, GName nvarchar(10));
GO
INSERT INTO dbo.Groups(GName)
select Group
from dbo.Students_Old
group by Group
GO
CREATE TABLE dbo.Forms(FormId int IDENTITY(1,1) PRIMARY KEY, Form nvarchar(20));
INSERT INTO dbo.Forms(Form)
select Form
from dbo.Students_Old
group by Form
GO
CREATE TABLE dbo.Students (StudentId int PRIMARY KEY, Name nvarchar(50),
Form int NOT NULL,
[Group] int NOT NULL,
CONSTRAINT Form FOREIGN KEY(Form) REFERENCES dbo.Forms(FormId),
CONSTRAINT Grup FOREIGN KEY(Group) REFERENCES dbo.Groups(GroupId));
GO
INSERT INTO dbo.Students(StudentId, Name, Form, Group)
select DocNum, Name, f.FormId, g.GroupId
from dbo.Students_Old s
join dbo.Forms f on s.Form=f.Form
join dbo.Groups g on s.Group=g.GName
I've changed to following lines
CONSTRAINT Form FOREIGN KEY(Form) REFERENCES dbo.Forms(FormId),
CONSTRAINT Grup FOREIGN KEY([Group]) REFERENCES dbo.Groups(GroupId));
In your code the foreign key is made on StudentID column
Not sure if that is the case, since you get the FOREIGN KEY error, but try avoiding column names like GROUP or other reserved words. While you can avoid errors on table creation step, you can face serious problems during modifications/updates on such tables.
execute below query.
CREATE TABLE dbo.Groups(GroupId int IDENTITY(1,1) PRIMARY KEY, GName nvarchar(10));
GO
INSERT INTO dbo.Groups(GName)
select [Group]
from dbo.Students_Old
group by [Group]
GO
CREATE TABLE dbo.Forms(FormId int IDENTITY(1,1) PRIMARY KEY, Form nvarchar(20));
INSERT INTO dbo.Forms(Form)
select Form
from dbo.Students_Old
group by Form
GO
CREATE TABLE dbo.Students (StudentId int PRIMARY KEY, Name nvarchar(50),
Form int NOT NULL,
[Group] int NOT NULL,
CONSTRAINT Form FOREIGN KEY(StudentId) REFERENCES dbo.Forms(FormId),
CONSTRAINT Grup FOREIGN KEY(StudentId) REFERENCES dbo.Groups(GroupId));
GO
INSERT INTO dbo.Students(StudentId, Name, Form, [Group])
select DocNum, Name, f.FormId, g.GroupId
from dbo.Students_Old s
join dbo.Forms f on s.Form=f.Form
join dbo.Groups g on s.[Group]=g.GName
Related
How primary key in one table connect to another table with the same primary key?
I am trying to make it like this, which those two primary key in the table of CustomerCreditCard is connect to the table of Customer and table of Credit card]
https://i.stack.imgur.com/lIBUE.png
--3
CREATE TABLE Customer
(
CustomerID INT IDENTITY PRIMARY KEY,
FirstName VARCHAR(50) NOT NULL,
LastName VARCHAR(50) NOT NULL,
);
--5
CREATE TABLE CreditCard
(
CreditCardNumber VARCHAR(16) PRIMARY KEY,
CreditCardOwnerName VARCHAR(50) NOT NULL,
);
--6
CREATE TABLE CustomerCreditCard
(
CreditCardNumber VARCHAR(16) NOT NULL,
CustomerID INT IDENTITY NOT NULL,
PRIMARY KEY(CreditCardNumber, CustomerID)
);
--6
CREATE TABLE CustomerCreditCard
(
CreditCardNumber VARCHAR(16) NOT NULL,
CustomerID INT NOT NULL,
CONSTRAINT pk_CustomerCreditCard
PRIMARY KEY(CreditCardNumber,CustomerID ),
CONSTRAINT fk_CustomerCreditCard_CreditCardNumber
FOREIGN KEY(CreditCardNumber)
REFERENCES CreditCard(CreditCardNumber)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_CustomerCreditCard_CustomerID
FOREIGN KEY(CustomerID)
REFERENCES Customer(CustomerID)
ON DELETE CASCADE ON UPDATE CASCADE
);
To solve the problem of this question, add the foreign key to the table that has two primary keys, then reference to other tables that you want to connect with the same primary key.
When creating the foreign key I came across this error. Below is my code.
create table tblPerson(
ID int not null primary key,
Fullname varchar(50) not null,
Email varchar(50) not null,
GenderId int
)
create table tblGender (
ID int not null primary key,
Gender varchar(50) not null
)
alter table tblPerson add constraint tblPerson_GenderId_FK
foreign key (GenderId) references tblGender(ID)
You want to identify any "do not align" rows....
I have made the below.
You won't be able to add the FK constraint, if any rows come back from the SELECT query.
I have also removed the hungarian notation for "tbl". I would advise against it.
create table dbo.Person(
ID int not null primary key,
Fullname varchar(50) not null,
Email varchar(50) not null,
GenderId int )
create table dbo.Gender (
ID int not null primary key,
Gender varchar(50) not null
)
/* any rows below? your FK creation will fail */
Select *, p.GenderId as 'HoustonWeHaveAProblemValue' from dbo.Person p Where Not Exists (Select 1 from dbo.Gender g where g.ID = p.GenderId)
alter table dbo.Person add constraint Person_GenderId_FK
foreign key (GenderId) references dbo.Gender(ID)
Hi please use the following code to achieve your goal :
1-First create tblGender:
create table tblGender (
ID int not null primary key,
Gender varchar(50) not null
)
2-Then create table tblPerson with the relationship between 2 tables since the beginning:
create table tblPerson(
ID int not null primary key,
Fullname varchar(50) not null,
Email varchar(50) not null,
GenderId int references tblGender(ID)
)
works fine.
There are three entities, Student, Class and Department. Department and Student have a one-to-many relationship. Department and Class have a one-to-many relationship too. Student and Class have a many-to-many relationship.
create table Department
(
Id int primary key,
-- ...
)
create table Student
(
Id int primary key,
DepartmentId int not null references Department(Id),
-- ....
)
create table Class
(
Id int primary key,
DepartmentId int not null references Department(Id),
....
)
The following table is for the many-to-many relationship between Student and Class. Now user can put a pair of student/class which are from different (which shouldn't be allowed) departments in the table. Is it a way to prevent it besides using a trigger?
create table StudentAndClass
(
StudentId int references Student(Id),
ClassId int references Class(Id),
-- ....
primary key (StudentId, ClassId)
)
You can do this without a trigger or special functions. The idea is to use foreign key relationships . . . by defining an extra set of keys and adding DepartmentId (redundantly) to the junction table:
create table Students (
StudentId int primary key,
DepartmentId int not null references Department(Id),
-- ....
unique (DepartmentId, StudentId)
);
create table Classes (
ClassId int primary key,
DepartmentId int not null references Department(Id),
....
unique (DepartmentId, ClassId)
);
create table StudentClasses (
DepartmentId int references Department(DepartmentId),
StudentId int,
ClassId int,
-- ....
primary key (StudentId, ClassId),
foreign key (DepartmentId, StudentId) references (DepartmentId, StudentId),
foreign key (DepartmentId, ClassId) references (DepartmentId, ClassId),
);
You may not want the redundancy, but it is possible without triggers or special functions.
You should use a CHECK CONSTRAINT
CREATE FUNCTION dbo.CheckDepartment()
RETURNS int
AS BEGIN RETURN (
SELECT count(1)
FROM StudentAndClass sc
JOIN Student s on sc.StudentId=s.id
JOIN Class c on sc.ClassId=c.id
WHERE c.DepartmentId<>s.DepartmentId
) END
go
ALTER TABLE StudentAndClass ADD CONSTRAINT chkDep CHECK (dbo.CheckDepartment() = 0);
This will guarantee that the departments will match
This question piggybacks off of Foreign Key to multiple tables
but I thought that my elaboration could use its own subject.
Say I have the following schema (adapted from #Nathan Skerl's answer in the above link):
create table dbo.PartyType
(
PartyTypeId tinyint primary key,
PartyTypeName varchar(10)
)
insert into dbo.PartyType
values(1, 'User'), (2, 'Group');
create table dbo.Party
(
PartyId int identity(1,1) primary key,
PartyTypeid tinyint references dbo.PartyType(PartyTypeId),
unique (PartyId, PartyTypeId)
)
CREATE TABLE dbo.[Group]
(
ID int NOT NULL,
Name varchar(50) NOT NULL,
PartyTypeId as cast(2 as tinyint) persisted,
foreign key (ID, PartyTypeId) references Party(PartyId, PartyTypeID)
)
CREATE TABLE dbo.[User]
(
ID int NOT NULL,
Name varchar(50) NOT NULL,
PartyTypeId as cast(1 as tinyint) persisted,
foreign key (ID, PartyTypeId) references Party(PartyID, PartyTypeID)
)
CREATE TABLE dbo.Ticket
(
ID int NOT NULL,
[Owner] int NOT NULL references dbo.Party(PartyId),
[Subject] varchar(50) NULL
)
And say I had another relation, say 'Stuff', where 'Users' could possess many items of 'Stuff', but it did not make sense for 'Groups' to have 'Stuff'. Could I have a Foreign Key in 'Stuff' reference just 'User'?
If it is possible, then how would one go about doing so? Or do I have to do all of my foreign keys of that sort directly through 'Party'?
I got an error (There are no primary or candidate keys in the referenced table 'dbo.Users' that match the referencing column 'ID' in the foreign key) when I tried myself.
Thanks in advance!
If I understand correctly, you can do what you want. The idea is to create a unique key on PartyTypeId, Id.
CREATE TABLE dbo.[User] (
ID int NOT NULL,
Name varchar(50) NOT NULL,
PartyTypeId as cast(1 as tinyint) persisted,
foreign key (ID, PartyTypeId) references Party(PartyID, PartyTypeID),
unique (PartyTypeId, Id)
);
CREATE TABLE Stuff (
StuffId int not null primary key,
UserId int,
PartyTypeId as cast(1 as tinyint) persisted,
Foreign Key (UserId) references user(PartyTypeId, userId)
);
Here is a SQL Fiddle.
This is explained in the documentation.
Yes, you can have a foreign key in Stuff reference just User:
CREATE TABLE Stuff (
StuffId int not null primary key,
UserId int,
Foreign Key (UserId) references dbo.[User](ID)
);
Can anyone please tell me how can one estabilish 1 to 0..1 and 1 to 1..* relationships between tables in SQL (Server)?
Thank you very much.
1 to 1..*
Create a Foreign key from a parent table to the primary key of the child (lookup table).
CREATE TABLE A
(
id int NOT NULL IDENTITY(1,1) PRIMARY KEY,
Somecolumn int,
SomeOtherColumn Varchar(50),
B_id int CONSTRAINT FOREIGN KEY REFERENCES B(id),
-- ...other columns
)
CREATE TABLE B
(
id int NOT NULL IDENTITY(1,1) PRIMARY KEY,
Name Varchar(50)
)
1 to 0..1
Create a table with the primary key also defined as a Foreign key to the parent table
CREATE TABLE [Master]
(
id int NOT NULL IDENTITY(1,1) PRIMARY KEY,
Somecolumn int,
SomeOtherColumn Varchar(50),
-- ...other columns
)
CREATE TABLE [Child]
(
id int NOT NULL PRIMARY KEY,
OtherColumn Varchar(50),
)
ALTER TABLE Child
ADD CONSTRAINT FK_Master FOREIGN KEY (id) REFERENCES Master(id)
One to many
Define two tables (example A and B), with their own primary key
Define a column in Table A as having a Foreign key relationship based on the primary key of Table B
This means that Table A can have one or more records relating to a single record in Table B.
If you already have the tables in place, use the ALTER TABLE statement to create the foreign key constraint:
ALTER TABLE A ADD CONSTRAINT FOREIGN KEY fk_b ( b_id ) references b(id)
* fk_b: Name of the foreign key constraint, must be unique to the database
* b_id: Name of column in Table A you are creating the foreign key relationship on
* b: Name of table, in this case b
* id: Name of column in Table B