I have a table with 3 values and a foreign table.
Tbl_Person
ID int PRIMARY KEY IDENTITY(1,1)
CarID int REFERENCES Tbl_Car(ID)
Name nvarchar(20)
Tbl_Car
ID int PRIMARY KEY IDENTITY(1,1)
Color nvarchar(30)
I now want to create a new Person with a new Car without caring about the Car table, sort of like this:
INSERT INTO Tbl_Person (Car, Name)
VALUES ('dont know what goes here', 'Timmy')
I'm not sure what to put inside the Car column since I just want it to exist but not care about its values just yet.
I'm sure its quite easy to find online but I have no idea how to Google for this particular problem.
You could alter the logical model to denormalize 'CarID' (remove it from 'Persons' table) and create a new table to store persons' cars called 'Person_Cars'. This avoids inserting NULL values into the model when the car is unknown. Depending on which table constraints are applied it also could allow for persons to have more than 1 car. Also, prefixing tables with 'tbl_' is not necessary. Also, both Persons and Cars seem likely to benefit from a unique constraint on the NVARCHAR column(s).
Persons
ID int not null PRIMARY KEY IDENTITY(1,1)
Name nvarchar(20) unique not null
Cars
ID int not null PRIMARY KEY IDENTITY(1,1)
Car nvarchar(30) unique not null
Person_Cars
ID int not null PRIMARY KEY IDENTITY(1,1)
PersonID int not null REFERENCES Persons(ID)
CarID int not null REFERENCES Cars(ID)
You can use NULL:
CREATE TABLE Tbl_Car (
ID int PRIMARY KEY IDENTITY(1,1),
Color nvarchar(30));
CREATE TABLE Tbl_Person (
ID int PRIMARY KEY IDENTITY(1,1),
CarID int REFERENCES Tbl_Car(ID),
Name nvarchar(20));
INSERT INTO Tbl_Person (CarID, Name) VALUES (NULL, 'Timmy');
DBFIDDLE
You have to do a logical operation. You can not just give the car an ID but it must have a name.
change Tbl_Car to :
CREATE TABLE Tbl_Car (
ID int PRIMARY KEY IDENTITY(1,1),
CarName nvarchar(30),
Color nvarchar(30));
To enter the Tbl_Person table, you must know the name of the person's car :
INSERT INTO Tbl_Person VALUES(CarID,Name)
SELECT ID,'Timmy'
FROM Tbl_Car
WHERE CarName = 'BMW'
Related
I have the schema below - Let's pretend that there are 2 countries, A and B.
Country A has 1000 teams whereas country B has 100,000,000 - If I want to quickly query results based off which country the team is in, how would I construct my index?
Teams cannot change country if that helps.
Indexing a table depend upon knowing real schema.
For this simple table schema, I will create only Trusted FK between tables, at least this will be my first try.
Assuming Countryid,Teamid,Resultid are auto increment.
CREATE TABLE Country
(
id INT IDENTITY(1, 1) PRIMARY KEY,
CountryName VARCHAR(100) NOT NULL
);
CREATE TABLE Team
(
id INT IDENTITY(1, 1) PRIMARY KEY,
TeamName VARCHAR(100) NOT NULL,
CountryID INT NOT NULL
);
ALTER TABLE dbo.Team WITH CHECK
ADD CONSTRAINT FK_Team_CountryID
FOREIGN KEY(CountryID) REFERENCES dbo.Country(id);
ALTER TABLE dbo.Team WITH CHECK
CHECK CONSTRAINT FK_Team_CountryID;
--Just verify that newly created FK is trusted or not.
SELECT
name,
is_disabled,
is_not_trusted
FROM
sys.foreign_keys
WHERE
name = 'FK_Team_CountryID';
CREATE TABLE Result
(
id INT IDENTITY(1, 1) PRIMARY KEY,
TeamId INT NOT NULL,
Result INT NOT NULL
);
-- I have no idea how you are storing Result,so ignore it
ALTER TABLE dbo.Result WITH CHECK
ADD CONSTRAINT FK_Result_TeamId
FOREIGN KEY(TeamId) REFERENCES dbo.Team(id);
ALTER TABLE dbo.Result WITH CHECK
CHECK CONSTRAINT FK_Result_TeamId;
May be after seeing query plan of real query, I will De-normalise Result table to add Countryid , but for now it is not require since country table will be small
For example, when I have a multi-value table that is the languages a person can speak. There are, let's say, 5 columns for storing the languages.
CREATE TABLE Languages
(
PersonID int primary key, //this is FOREIGN KEY to a Person, "REFERENCES Person(ID)" for example
Lang1 varchar(30),
Lang2 varchar(30),
Lang3 varchar(30),
Lang4 varchar(30),
Lang5 varchar(30)
)
What are the solutions if there is someone who can speak more than 5 languages?
Your design is broken and cannot handle the scenario you describe. You need to fix the design, the normal design for this situation would be:
CREATE TABLE Person
(
PersonID int identity (1,1) primary key,
Forename varchar(128),
Surname varchar(128)
-- etc etc
)
CREATE TABLE Language
(
LanguageID int primary key,
[Name] varchar(128)
-- etc etc
)
CREATE TABLE PersonLanguage
(
-- Optional to have a specific PK for a linking table - I prefer to
PersonLanguageID int identity (1,1) primary key,
PersonID int foreign key reference Person (PersonId),
LanguageID int foreign key reference Language (LanguageId)
)
Then you can add as many languages as you like e.g.
-- First insert will give ID 1
insert into Person (Forename, Surname)
values ('Bob', 'Test');
-- Insert will give IDs 1-7
insert into Language ([Name])
values ('English'), ('Spanish'), ('French'), ('German'), ('Dutch'), ('Portuguese'), ('Greek');
-- Add as many languages as you like
insert into PersonLanguage (PersonId, LanguageId)
values (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7);
I have these tables I want to create for a Grooming Shop:
CREATE TABLE Pets(
Id int NOT NULL PRIMARY KEY IDENTITY
,Name varchar(20)
,Breed varchar(35)
,[Weight] decimal (10,2) NOT NULL
,Cat bit NOT NULL
,Dog bit NOT NULL
)
CREATE TABLE UserInfo(
Id int NOT NULL PRIMARY KEY IDENTITY
,FirstName varchar(15) NOT NULL
,LastName varchar(30) NOT NULL
,PhoneNumber varchar(10) NOT NULL
,EmailAddress varchar(30) NOT NULL
,AddressId int NOT NULL FOREIGN KEY REFERENCES [Address](Id)--Address Table already created
,PetId int NOT NULL FOREIGN KEY REFERENCES Pets(Id)
)
CREATE TABLE Appointments(
Id int NOT NULL PRIMARY KEY IDENTITY
,[Date] date NOT NULL
,UserInfoId int NOT NULL FOREIGN KEY REFERENCES UserInfo(Id)
,PetId int NOT NULL FOREIGN KEY REFERENCES Pets(Id)--?
)
My Appointments table will have the UserInfo but should it also have the Pets info? If there can be more than 1 pet for each appointment, and more than on appointment for each pet... When I wanted the UserInfo to point to the Pets table, because each user will have at least one pet.
No, you needn't have pets info in appointment table because the information related to pet can be retrieved from the UserInfo table itself.
Since each user will have one or more pets and a pet presumably has only one owner, I suggest you add UserInfoId to the Pets table and remove PetId from the UserInfo table. I also suggest you remove PetId from the Appointment table and create a separate table for the pets included in the appointment. So the appointment is actually with the owner, who may bring one or more pets.
CREATE TABLE UserInfo(
Id int NOT NULL PRIMARY KEY IDENTITY
,FirstName varchar(15) NOT NULL
,LastName varchar(30) NOT NULL
,PhoneNumber varchar(10) NOT NULL
,EmailAddress varchar(30) NOT NULL
,AddressId int NOT NULL FOREIGN KEY REFERENCES [Address](Id)
);
CREATE TABLE Pets(
Id int NOT NULL PRIMARY KEY IDENTITY
,UserInfoId int NOT NULL FOREIGN KEY REFERENCES UserInfo(Id)
,Name varchar(20)
,Breed varchar(35)
,[Weight] decimal (10,2) NOT NULL
,Cat bit NOT NULL
,Dog bit NOT NULL
);
CREATE TABLE Appointments(
Id int NOT NULL PRIMARY KEY IDENTITY
,[Date] date NOT NULL
,UserInfoId int NOT NULL FOREIGN KEY REFERENCES UserInfo(Id)
);
CREATE TABLE AppointmentPets(
AppointmentId int NOT NULL
,PetId int NOT NULL
CONSTRAINT PK_AppointmentPets PRIMARY KEY(AppointmentId, PetId)
);
You can have petID in appoinment table but it's not needed since you can link appoinment -> userinfo using UserInfoId relationship and then you can link userinfo -> pets using petid relationship.
This scenario is very well known as Transitive relationship. I.e, If A -> B and B -> C exist then A -> C can be formed.
You should know how you intend to use these tables, that is, what are your business rules. Then, you will have a better design for your table. If you are not sure, then you might have to redesign your tables again.
Here are some points to think about:
You don't want to repeat user info for each pet they have, right ? (Normalization)
You can map users to pets in a separate table or in appointments table. Its possible that you have a many to many relationship between users and pets, that is multiple users have one pet and multiple pets are owned by a user. You could link users to pets in a separate table.
You could split user info into two tables - userinfo and useraddress table and link them with user id, since family in the same home can share a pet. (Normalization)
Replace cat bit, dog bit columns by animal column. (Minor suggestion)
I have a table School and a table Teacher having a one-to-many relationship. However, one of the teachers is the school's principle, and only one teacher can be the school principle. So I thought of saving the teachers id (principle) in the School table as follows:
CREATE TABLE School (
ID INT PRIMARY KEY,
Name VARCHAR(40),
PrincipleID INT FOREIGN KEY REFERENCES Teacher.ID
)
CREATE TABLE Teacher (
ID INT PRIMARY KEY,
Name VARCHAR(40),
SchoolID INT FOREIGN KEY REFERENCES School.ID
)
I know I could loose the foreign key reference in the school table, but that's not an option.
Should I make the reference after the table creation? If yes, how?
Another solution is to create a new table, let's say SchoolsPrinciples with just two fields:
CREATE TABLE SchoolsPrinciples
(
SchoolId int,
TeacherId int,
CONSTRAINT uc_SchoolTeacher UNIQUE (SchoolId, TeacherId)
)
A UNIQUE constraint let you obtain exactly one teacher per each school.
When building the tables, you'll need to add the constraint as a separate alter statement. Note also that when creating foreign keys, you should only specify the table name, not the referenced column (the column is implied by the primary key).
CREATE TABLE School (
ID INT PRIMARY KEY,
Name VARCHAR(40),
PrincipleID INT);
CREATE TABLE Teacher (
ID INT PRIMARY KEY,
Name VARCHAR(40),
SchoolID INT
CONSTRAINT FK_Teacher_School
FOREIGN KEY REFERENCES School);
ALTER TABLE School add
CONSTRAINT FK_School_Teacher
FOREIGN KEY (PrincipleID) REFERENCES Teacher;
When you add data, you'll need to set the PrincipleID field as a separate update:
insert into School (ID, Name)
values (1, 'Blarg Elementary');
insert into Teacher (ID, Name, SchoolID)
values (1, 'John Doe', 1),
(2, 'Bob Smith', 1),
(3, 'Adam Walker', 1);
update School set PrincipleID = 2 where ID = 1;
Put a boolean IsPrincipal on the Teacher table instead. Or add a third relationship table
CREATE TABLE SchoolPrincipals (
INT SchoolID PRIMARY KEY FOREIGN KEY REFERENCES School.ID,
INT TeacherID FOREIGN KEY REFERENCES Teacher.ID
)
Keeps everything tidy without painful delete logic.
You can take a column in Teacher table as
IsPrincipal where only one row will have value as true as referred
by jonnyGold,
This can be checked by triggers.
OR
You can use filtered index if using Sql Server 2008.
Create unique filtered index where SchoolID, IsPrincipal
is NOT NULL and are unique
Boss where this will contain ID of principal hence creating employee manager relationship which in your case is not suitable.
CREATE TABLE EmpManager
(
TeacherID int
SchoolID int
IsPrincipal bit
)
And use filtered index or trigger to handle the scenario.
EDIT:
CREATE TABLE [dbo].[Teacher](
[ID] [int] NOT NULL primary key,
[Name] [varchar](40) NULL,
[SchoolID] [int] NULL,
)
GO
CREATE TABLE [dbo].[School](
[ID] [int] NOT NULL primary key,
[Name] [varchar](40) NULL,
[PrincipleID] [int] NULL,
)
GO
ALTER TABLE [dbo].[Teacher] WITH CHECK ADD CONSTRAINT [FK_Teacher_School] FOREIGN KEY([SchoolID])
REFERENCES [dbo].[School] ([ID])
GO
ALTER TABLE [dbo].[School] WITH CHECK ADD CONSTRAINT [FK_School_Teacher] FOREIGN KEY([PrincipleID])
REFERENCES [dbo].[Teacher] ([ID])
GO
Better design should be the one suggested by ADC
I have two tables:
Person(personID, name, phone, email);
Relation(child_personID, parent_playerID);
The relationship table helps identify children and their parent but to do this the personID from the person table has to be referenced twice as foreign. How exactly would I go about doing this?
Could look something like this.
create table Person
(
personID int primary key,
name varchar(50),
phone varchar(50),
email varchar(50)
)
create table Relation
(
child_personID int references Person(personID),
parent_playerID int references Person(personID),
primary key (child_personID, parent_playerID)
)