SQL Server - Adding foreign key to a table - sql-server

As in my previous post (linked here) I have been designing a table and I'm trying to insert only some specific values into the BrothersName column which can be done by adding a constraint.
TABLE Family
(
BrothersName varchar(30)
);
However my question now is that I'm trying to do this instead by foreign key. Is the only way to do it is by making a new table and add primary key into it?
What can be the best way otherwise?

So you should have a primary key table to hold all possible master data set for brother names like below
create table MasterBrotherNames (ID int IDENTITY(1,1) PRIMARY KEY, Name nvarchar(30)) ;
insert into MasterBrotherNames(Name) values (N'Alex'),(N'Tom');
Now you should hold foreign key ID into the Family table as int, say in column BrothersNameID using following query to create FK relationship
create table Family( BrothersNameID int NOT NULL);
alter table Family add constraint fk_family_brothername foreign key ( BrothersNameID ) references MasterBrotherNames (ID);
To test out try queries below
insert into Family values (1)-- for Alex
insert into Family values (2)-- for Tom
insert into Family values (3)-- this gives error
--The INSERT statement conflicted with the FOREIGN KEY constraint "fk_family_brothername".
Based on OP's following request
is there any way to implement this without having any Id in MasterBrothersName, where only names can be inserted and accepted as values
here's the modified query
create table MasterBrotherNames ( Name nvarchar(30) PRIMARY KEY) ;
insert into MasterBrotherNames(Name) values (N'Alex'),(N'Tom');
create table Family( BrothersName nvarchar(30) NOT NULL);
alter table Family add constraint fk_family_brothername foreign key ( BrothersName ) references MasterBrotherNames (Name);
insert into Family values (N'Alex')-- for Alex
insert into Family values (N'Tom')-- for Tom
insert into Family values (N'A')-- this gives error
--The INSERT statement conflicted with the FOREIGN KEY constraint "fk_family_brothername".

Related

creating two tables that share dependencies

Im trying to create two tables in sql that share keys and im getting an error message saying:
Cannot create, drop, enable, or disable more than one constraint, column, index, or trigger named 'PK_vc_Status' in this context. Duplicate names are not allowed.
Im not very experienced with mysqlServer and am trying to figure out what's wrong with my code.
CREATE TABLE vc_VidCast (
-- Columns for the VidCast table
vc_VidCastID int identity,
VidCastTitle varchar(50) not null,
StartDateTime datetime,
EndDateTime datetime,
ScheduleDurationMinutes int,
RecordingURL varchar(50),
vc_UserID int not null,
vc_StatusID int not null,
-- Constraints on the VidCast List table
CONSTRAINT PK_vc_VidCast PRIMARY KEY (vc_VidCastID),
CONSTRAINT FK1_vc_VidCast FOREIGN KEY (vc_UserID) REFERENCES vc_User(vc_UserID),
CONSTRAINT FK2_vc_VidCast FOREIGN KEY (vc_StatusID) REFERENCES vc_Status(vc_StatusID)
)
-- End creating the VidCast table
-- Creating the Status table
CREATE TABLE vc_Status (
-- Columns for the Status table
vc_StatusID int Identity,
StatusText varchar(20),
-- Constraints on the Status Table
CONSTRAINT PK_vc_Status PRIMARY Key (vc_StatusID),
CONSTRAINT U1_vc_Status UNIQUE (StatusText),
CONSTRAINT PK_vc_Status FOREIGN KEY (vc_StatusID) REFERENCES vc_VidCast(vc_StatusID)
)
-- End Creating The Status Table

SQL FOREIGN KEY constraint in Insert

I've got a problem to insert some values into table.
Microsoft SQL server management shows that:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Players__Menager__55D59338". The conflict occurred in database
"TransferyProjekt", table "dbo.Menagers", column 'idMenager'.
My Create table script.
CREATE TABLE Menagers (
idMenager INT IDENTITY(1,1) NOT NULL,
[name] VARCHAR(30) NOT NULL CHECK (name LIKE '[A-Z]%'),
surname VARCHAR(30) NOT NULL CHECK (surname LIKE '[A-Z]%'),
phoneNumber VARCHAR(18) NOT NULL CHECK (phoneNumber LIKE '+[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'),
PRIMARY KEY (idMenager)
);
CREATE TABLE Players (
idPlayer INT IDENTITY(1,1) NOT NULL,
[name] VARCHAR(30) NOT NULL,
surname VARCHAR(30) NOT NULL,
age DATE NOT NULL check (DATEDIFF(year,age,GETDATE()) > 18),
club INT NOT NULL,
Menager INT NOT NULL,
PRIMARY KEY (idPlayer),
FOREIGN KEY (club) REFERENCES Clubs(idClub),
FOREIGN KEY (Menager) REFERENCES Menagers(idMenager)
);
My insert look like.
INSERT INTO Menagers VALUES
('Adil','Green','+232247832'),
('Wicky','Dock','+301494064'),
('Alead','King','+447499384'),
('Darmian','Dagoly','+445587849'),
('Kamila','Dobra','+958789278'),
('Mateusz','Jankowiak','+849383098'),
('Lendy','Day','+448902920'),
('Martin','Lloyd','+501044468'),
('Adam','Dosh','+045033739'),
('Cristian','Cosy','+307748735'),
('Andrew','Lloyd','+635875452'),
('Matias','Banega','+520091224'),
('Carl','Rossi','+196935415'),
('Michał','Rolnik','+156541588'),
('Denny','Nowsky','+231785387'),
('Micky','Elly','+125774609'),
('George','Taylor','+094371433'),
('Barack','Obama','+916764868'),
('Jin','Chan','+906765545'),
('Lee','Konsu','+608935829'),
('Adam','Kenzo','+417708081'),
('Bryan','Along','+939454178'),
('Robert','Leey','+183354912'),
('Tom','Vardy','+576176145'),
('Kevin','Betword','+721582207');
INSERT INTO Players VALUES
('Lionel','Messi','1986-07-13','23','4'),
('Cristiano','Ronaldo','1986-04-11','23','5'),
('Sergio','Ramos','1986-09-07','23','12'),
('Łukasz','Piszczek','1986-11-20','23','14'),
('Robert','Lewandowski','1986-12-01','2','13'),
('Michał','Pazdan','1986-06-01','3','23'),
('Łukasz','Trałka','1986-05-02','7','20'),
('Łukasz','Teodorczyk','1986-04-14','6','18'),
('Mariusz','Miley','1985-03-06','3','26');
You should define column names if your source table and destination table has different column counts or different order
INSERT INTO Menagers([name],surname, phoneNumber )
VALUES
('Adil','Green','+232247832'),
('Wicky','Dock','+301494064'),
....
INSERT INTO Players([name], surname, age, club, Menager )
VALUES
('Lionel','Messi','1986-07-13','23','4'),
('Cristiano','Ronaldo','1986-04-11','23','5'),
...
Your foreign key and primary key columns are INT type. But, you are having following SQL
INSERT INTO Players VALUES
('Lionel','Messi','1986-07-13','23','4')
where last column belongs to foreign key column and your value is string.
A foreign key is a reference to a unique value in a different table, and SQL will ensure "referential integrity" - which means it won't let you end you with "orphaned" key references. When you insert a value to a foreign key column it must be a null or a existing reference to a row in the other table, and when you delete, you must delete the row containing the foreign key first, then the row it references.
If you don't, you will get an error such as you describe.
So enter the row into the "main" table first, then enter the "dependant" table information second.
In FK column I added unfortunately referece to row who is not exists in table Managers...
('Mariusz','Miley','1985-03-06','3','26');
but I don't have 26'th row in table Managers (Blame me, now) :(

How can I create a table in SQL only if a column in another table is true?

For example, assume I want to create the following table:
CREATE TABLE Add_Friends(
PRIMARY KEY(email_1, email_2),
email_1 VARCHAR(50) FOREIGN KEY REFERENCES Normal_Users,
email_2 VARCHAR(50) FOREIGN KEY REFERENCES Normal_Users,
accepted_or_not BIT
)
CREATE TABLE Messages1(
message_ID INT PRIMARY KEY IDENTITY,
date_sent date,
message_content VARCHAR(100),
sender VARCHAR(50) FOREIGN KEY REFERENCES Normal_Users,
reciever VARCHAR(50) FOREIGN KEY REFERENCES Normal_Users
)
Users should only be able to send messages to each other if they are friends (the last column in Add_Friends). How can I define this constraint in the Messages1 table?
If I understand correctly your question:
You don't need to create a table for each conversation, you can put all the messages together in the same table and id the conversation registering the primarykey from the add frinds.
I assume you have another table with all the data of your "persons" and then Add_Friends is the table where you add realtionsship between those persons, so to do the restriction you want you need to first check if the relationship between sender and reciever exist and then do an insert if the query returns a value.
SELECT ID_FRIEND
FROM ADD_FRIENDS
WHERE email_1 = "+ID_SENDER+" AND email_2 = "+ID_RECIEVER+"
If this query returns a value it means the realationship exist and you can do the insert.
Is better to do this in two steps so you can also restrict things like if the person is or not registed, online status or even be able to write a message in the first place.
And then to search for a chat you can do:
SELECT *
FROM messages AS m INNER JOIN add_friends as AF ON M.SENDER= AF.EMAIL1
WHERE email_2 = '" + EMAIL_CONVERSION_WITH + "'"
You can achieve this in any language.
You can create a user defined function passing it the sender & receiver - that function can check if a record of those emails exists in Add_Friends and if accepted_or_not = 1 and return BIT (0 / 1). Then you can use the function in a constraint:
ALTER TABLE [Messages1]
WITH CHECK ADD CONSTRAINT [Your_Constraint_Name]
CHECK ([dbo].[Your_Function_Name]([sender], [reciever]) = 1)
ALTER TABLE [Messages1] CHECK CONSTRAINT [Your_Constraint_Name]
Instead of having a column accepted_or_notin Add_Friends, you can define another table 'Friends_Accepted':
CREATE TABLE Friends_Accepted(
Id INT PRIMARY KEY IDENTITY,
email_canSend VARCHAR(50) FOREIGN KEY REFERENCES Normal_Users,
email_canReceive VARCHAR(50) FOREIGN KEY REFERENCES Normal_Users,
)
In this table, you would add TWO lines when a friend request is accepted -- one for each direction of the conversation: (A.Email,B.Email), (B.Email, A.Email)
Now you can have the table Messages1 reference Friends_Accepted:
CREATE TABLE Messages1(
message_ID INT PRIMARY KEY IDENTITY,
date_sent date,
message_content VARCHAR(100),
fromTo_Id FOREIGN KEY REFERENCES Friends_Accepted,
)
So a message from (A to B) and a message from (B to A) will reference two DIFFERENT lines in Friends_Accepted

How to set "auto insert" foreign key value by using SQL Server?

I have created two tables and also created a relationship between them.
Table students:
create table students
(
[StudentId] NVARCHAR(50) NOT NULL PRIMARY KEY,
[Name] NVARCHAR(50) NOT NULL
);
Table studentprofile:
create table studentprofile
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
[StudentId] NVARCHAR(50) NOT NULL,
[Address] NVARCHAR(50) NOT NULL,
);
and relationship:
alter table studentprofile
add constraint students_studentprofile_FK
foreign key (StudentId)
references students(StudentId)
on delete cascade on update cascade
But, when I wrote this line:
insert into students values('110111', 'Marik')
the value of StudentId (in table studentprofile) wasn't updated automatically. Why?
Can you tell me how to set the value of StudentId (in table studentprofile) can be inserted automatically whenever I insert into table students?
There is no such thing as insert cascade.
You can implement such a thing by using a trigger for insert on your students table, inserting default values (or nulls) into the studentprofile table:
CREATE TRIGGER students_insert ON students AFTER INSERT
AS
INSERT INTO studentprofile(StudentId, Address)
SELECT StudentId, 'NO ADDRESS'
FROM inserted
Note that your Address column is defined as not null and has no default value, this is why I've used the hard coded 'NO ADDRESS' for it.
However, I agree with the comments on your question: you would be better off inserting the data to the student profile using a different insert statement (perhaps inside a transaction with the insert to students).

Is it possible to ignore varchar length when setting foreign key between tables?

There are two tables in my SQL Server 2008.
CREATE TABLE TABLE1 (
field1 varchar(20) not null,
field2 int,
CONSTRAINT PK_TABLE1 PRIMARY KEY (field1)
)
CREATE TABLE TABLE2 (
Id int,
t1 varchar(10) not null
t2 ntext
CONSTRAINT PK_TABLE2 PRIMARY KEY (Id)
)
Now I want to build a foreign key on table2 with below command :
ALTER TABLE TABLE2
ADD CONSTRAINT TABLE2_FK
FOREIGN KEY (t1) REFERENCES TABLE1 (field1)
ON DELETE CASCADE ON UPDATE CASCADE
SQL Server responds that the foreign key in Table2 is different from the column field1 in Table1 in length.
Is it possible to ask SQL Server to ignore the validation of length of foreign key ?
Thank you for your answer.
No, it is not possible. From the MSDN page on CREATE TABLE, which includes a section about foreign keys:
The REFERENCES clause of a table-level FOREIGN KEY constraint must
have the same number of reference columns as the number of columns in
the constraint column list. The data type of each reference column
must also be the same as the corresponding column in the column list.
Of course, you can make a computed column that casts the VARCHAR(10) to a VARCHAR(20) and then set the foreign key.

Resources