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
Related
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'
'''
CREATE TABLE Employee
(
employeeID INT (10) PRIMARY KEY,
Name CHAR (20)
);
'''
'''
CREATE TABLE SALARY
(
employeeID INT (10) PRIMARY KEY,
Salary INT (10)
);
'''
Is it possible to use the same primary key in both tables?
Yes. You can have same column name as primary key in multiple tables.
Column names should be unique within a table. A table can have only one primary key, as it defines the Entity integrity.
If this question is about data modelling parent-child relationship, There are two types. You are read more on this.
Identifying relationship : Child identifies itself by the help of parent. Here, Employee & Salary will share the same primary key. Primary key of parent table (EmployeeId) will be primary key of child table also (Salary).
Non-Identifying relationship: Child is having its own identity. Here, Employee & Salary will have different primary key. Child table will have its own primary key(say SalaryId) and will have primary key of parent as a Foreign key(EmployeeId).
If your question is if you can use the same EMPLOYEEID column as the primary ID on multiple tables, the answer is "YES, YOU CAN"
You can use the same column as primary index on multiple tables, but you cannot have more than one primary index on a table
Yes, you can. You would make salary.employeeid both the table's primary key and a foreign key to the employee table:
CREATE TABLE salary
(
employeeid INT (10) NOT NULL,
salary INT (10) NOT NULL,
CONSTRAINT pk_salary PRIMARY KEY (employeeid,
CONSTRAINT fk_salary_employeeid FOREIGN KEY (employeeid) REFERENCES employee (employeeid)
);
This creates a {1}:{0,1} relationship between the tables and ensures that you cannot store a salary without having stored the employee and that you cannot store more than one salary for one employee.
This is something we rarely do. (We would rather make the salary a column in the employee table.) The only advantage of a separate salary table I see is that you can grant rights on the employee table but revoke them on the salary table, so as to make the salary table invisible to some database users.
You can do this, however, it is bad design.
I would suggest having the EmployeeId as the PK on the employee table and the EmployeeId as a Foreign Key on the Salary table, with the Salary table having it's own PK (most likely SalaryId).
Also the field [Name] I would personally steer clear of too, as "Name" is a reserved word in SQL.
CREATE TABLE dbo.Employee
(
EmployeeId BIGINT IDENTITY(1,1)
,EmployeeName VARCHAR(20) NOT NULL
,CONSTRAINT PK_Emp PRIMARY KEY (EmployeeId)
);
GO
CREATE TABLE dbo.Salary
(
SalaryId BIGINT IDENTITY(1,1)
,EmployeeId BIGINT NOT NULL
,Salary INT NOT NULL
,CONSTRAINT PK_Sal PRIMARY KEY (SalaryId)
,CONSTRAINT FK_EmpSal FOREIGN KEY (EmployeeId)
REFERENCES Employee(EmployeeId)
);
GO
All of that said, I think a little more thought into the db structure you should most likely end up with 3 tables. It is likely that many staff will have the same salary, lets say 5 employees are on 40,000 and 3 are on 50,000, etc.
You will end up storing the same Salary value multiple times.
A better way is to store that value once and have a third table that links an employee with a salary (in this case I have called it [Earnings]).
With this structure the salary of say 40,000 is stored 1 time in the db and you can link an employeeId to it multiple times.
CREATE TABLE dbo.Employee
(
Id BIGINT IDENTITY(1,1)
,EmployeeName VARCHAR(20) NOT NULL
,CONSTRAINT PK_Emp PRIMARY KEY (Id)
);
GO
CREATE TABLE dbo.Salary
(
Id BIGINT IDENTITY(1,1)
,Salary INT NOT NULL
,CONSTRAINT PK_Sal PRIMARY KEY (Id)
);
GO
CREATE TABLE dbo.Earnings
(
Id BIGINT IDENTITY(1,1)
,EmployeeId BIGINT NOT NULL
,SalaryId BIGINT NOT NULL
,CONSTRAINT PK_Ear PRIMARY KEY (Id)
,CONSTRAINT FK_EmpEar FOREIGN KEY (EmployeeId)
REFERENCES Employee(Id)
,CONSTRAINT FK_SalEar FOREIGN KEY (SalaryId)
REFERENCES Salary(Id)
);
GO
Technically, it is possible.
However, it is advisable to use Foreign key. This will:
-Avoid redundancy
-Help in maintaining db structure
-Improve readability
For this example, use:
CREATE TABLE Employee ( EmployeeID INT PRIMARY KEY, Name CHAR (20), Primary Key (EmployeeId) );
CREATE TABLE SALARY ( SalaryId INT , EmployeeID INT , Salary INT (10), Primary Key (SalaryId), Foreign Key (EmployeeId) REFERENCES Employee );
*An even better approach would be to add a constraint instead of just mentioning
[key names]
Like:
CREATE TABLE Employee(
EmployeeId INT,
Name CHAR(20)
)
ALTER TABLE Employee ADD CONSTRAINT PK_EmployeeId PRIMARY KEY
Can do by differents ways
I have a "Main" table named "Peoples" with "peopleId" as PK Identity
"Child" tables
"PeopleDocs" with "peopleId" PK
"PeopleImages" with "peopleId" PK
"PeopleKeys" with "peopleId" PK.
So, when i create one
record on "Peoples" i populate the "childs" with empty records to work
later.
This logic is about a federal law on my country and some people
informations has a life cicle and must be deleted if the life cicle
ends or the owner of the data demands. So we split the people
sensitive data on child tables to not lose all bussiness records,
refferences and log about that people.
Col1 as Primary key on both tables
SELECT
P.COL1,
P.COL2,
C.COL2,
C.COL3
FROM
TBL1 P, TBL2 C
WHERE
C.COL1 = P.COL1
Or using joins
SELECT
P.COL1,
P.COL2,
C.COL2,
C.COL3
FROM
TBL1 AS P
INNER JOIN
TBL2 AS C
ON
C.COL1 = P.COL1
I have these tables:
user
id
permission
id
user_id
old_permission
user_id
value
Values:
user
id
1
2
3
permission
id user_id
1 1
2 2
old_permission
user_id value
1 f
2 f
3 t
As the table names suggest, I am migrating from a legacy permissions system. What I want to do is:
When old_permission.value is 't', i want any matching rows in permission for the user to be deleted. So if user 3 had an entry in the permission table, it would be deleted if its old_permission.value = 't'.
I also want to create a row in the permission table if the associated old_permission.value = 'f'
How can I create a constraint like this?
I would create a Stored Procedure that refreshes the Permission table based on the Old_Permission table:
CREATE PROCEDURE RefreshPermissions()
AS
BEGIN
DELETE
Permission
WHERE
EXISTS
(SELECT
NULL
FROM
Old_Permission
WHERE
Permission.user_id = Old_Permission.user_id
AND Old_Permission.Value = 't');
INSERT INTO
Permission (user_id)
SELECT
Old_Permission.user_id
FROM
Old_Permission
LEFT JOIN Permission ON Old_Permission.user_id = Permission.user_id
WHERE
Old_Permission.Value = 'f'
AND Permission.user_Id IS NULL;
END;
Then I would suggest using triggers on the Old_Permission table to modify the Permission table as needed. Something like this:
CREATE TRIGGER
TR_Old_Permission
AFTER INSERT OR UPDATE OR DELETE ON
Old_Permission
EXECUTE PROCEDURE
RefreshPermissions();
The PL/SQL is part of Oracle. And Constraints are part of SQL not PL/SQL. You cannot create constraints like this. You need to write some code, could be procedures and/or triggers that would delete and insert according to your logic. Basically, while migrating, and I do not know what exactly you are doing to migrate and how, you loop through records then delete and insert records according to your conditions/filters. It is hard to suggest anything more as I need more details to decide how and what to do exactly in your case.
i am not able to understand the exact problem of yours,for that i thought of making u to understand the concept of the constraints in sql,including its defination and types.
Constraints are used to limit the type of data that can go into a table.
Constraints can be specified when a table is created (with the CREATE TABLE statement) or after the table is created (with the ALTER TABLE statement).
types of constraints:
•NOT NULL
•UNIQUE
•PRIMARY KEY
•FOREIGN KEY
•CHECK
•DEFAULT
Explanitation of the types of constraints with small examples for each:-
SQL NOT NULL Constraint
•The NOT NULL constraint enforces a column to NOT accept NULL values.
•The NOT NULL constraint enforces a field to always contain a value. This means that you
cannot insert a new record, or update a record without adding a value to this field.
•The following SQL enforces the "P_Id" column and the "LastName" column to not accept NULL
values:
•CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
SQL UNIQUE Constraint
The UNIQUE constraint uniquely identifies each record in a database table.
SQL UNIQUE Constraint on CREATE TABLE
The following SQL creates a UNIQUE constraint on the "P_Id" column when the "Persons" table
is created:
MySQL:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
UNIQUE (P_Id)
)
SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL UNIQUE,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
To allow naming of a UNIQUE constraint, and for defining a UNIQUE constraint on multiple
columns, use the following SQL syntax:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
)
SQL UNIQUE Constraint on ALTER TABLE
To create a UNIQUE constraint on the "P_Id" column when the table is already created,
use the following SQL:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD UNIQUE (P_Id)
To allow naming of a UNIQUE constraint, and for defining a UNIQUE constraint on multiple
columns, use the following SQL syntax:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
To DROP a UNIQUE Constraint
To drop a UNIQUE constraint, use the following SQL:
MySQL:
ALTER TABLE Persons
DROP INDEX uc_PersonID
SQL Server / Oracle / MS Access:
ALTER TABLE Persons
DROP CONSTRAINT uc_PersonID
SQL PRIMARY KEY Constraint
The PRIMARY KEY constraint uniquely identifies each record in a database table.
Primary keys must contain unique values.
A primary key column cannot contain NULL values.
Each table should have a primary key, and each table can have only ONE primary key.
SQL PRIMARY KEY Constraint on CREATE TABLE
The following SQL creates a PRIMARY KEY on the "P_Id" column when the "Persons" table is
created:
MySQL:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (P_Id)
)
SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL PRIMARY KEY,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
To allow naming of a PRIMARY KEY constraint, and for defining a PRIMARY KEY constraint on
multiple columns, use the following SQL syntax:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
)
SQL FOREIGN KEY Constraint on CREATE TABLE
The following SQL creates a FOREIGN KEY on the "P_Id" column when the "Orders" table is
created:
MySQL:
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
SQL Server / Oracle / MS Access:
CREATE TABLE Orders
(
O_Id int NOT NULL PRIMARY KEY,
OrderNo int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)
To allow naming of a FOREIGN KEY constraint, and for defining a FOREIGN KEY constraint on
multiple columns, use the following SQL syntax:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)
SQL CHECK Constraint on CREATE TABLE
The following SQL creates a CHECK constraint on the "P_Id" column when the "Persons" table
is created. The CHECK constraint specifies that the column "P_Id" must only include integers greater than 0.
MySQL:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CHECK (P_Id>0)
)
SQL DEFAULT Constraint
The DEFAULT constraint is used to insert a default value into a column.
SQL DEFAULT Constraint on CREATE TABLE
The following SQL creates a DEFAULT constraint on the "City" column when the "Persons"
table is created:
My SQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255) DEFAULT 'Sandnes'
)
The DEFAULT constraint can also be used to insert system values, by using functions like
GETDATE():
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
OrderDate date DEFAULT GETDATE()
)
above explination is in general format of using constraints,hope it may help you to overcome from your problem...........................
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've got SQL database in SQL Server 2008 generated as follows:
CREATE TABLE Client (
ID bigint,
Code varchar(50),
ClientID int NOT NULL
);
ALTER TABLE Client
ADD CONSTRAINT PK_Client PRIMARY KEY CLUSTERED (ClientID);
CREATE TABLE Company (
ID bigint,
Description nvarchar(100),
SubsidiaryOf bigint,
companyID int NOT NULL,
FK_Client_Company int,
PK_Company int
);
ALTER TABLE Company
ADD CONSTRAINT PK_Company PRIMARY KEY CLUSTERED (companyID);
ALTER TABLE Company
ADD CONSTRAINT (ID = ID) FOREIGN KEY (FK_Client_Company)
REFERENCES Client (ClientID);
ALTER TABLE Company
ADD CONSTRAINT (SubsidiaryOf = ID) FOREIGN KEY (PK_Company)
REFERENCES Company (companyID);
CREATE TABLE ContactData (
ID bigint,
LocationID bigint,
Contact nvarchar(50),
contactDataID int NOT NULL,
PK_Location int
);
ALTER TABLE ContactData
ADD CONSTRAINT PK_ContactData PRIMARY KEY CLUSTERED (contactDataID);
ALTER TABLE ContactData
ADD CONSTRAINT (LocationID = ID) FOREIGN KEY (PK_Location)
REFERENCES Location (locationID);
CREATE TABLE Location (
ID bigint,
CompanyID bigint,
Country nvarchar(50),
ZIPCode nvarchar(50),
locationID int NOT NULL,
PK_Company int
);
ALTER TABLE Location
ADD CONSTRAINT PK_Location PRIMARY KEY CLUSTERED (locationID);
ALTER TABLE Location
ADD CONSTRAINT (CompanyID = ID) FOREIGN KEY (PK_Company)
REFERENCES Company (companyID);
And would like to delete all the Companies with ID > 140000 (with related rows in other tables). I tried some combination of INNER JOINs all together in one transaction, but there is still a problem with FK_Client_Company constraint. Can anyone help me?
One more thing - I cannot add anything/modify DB structure/constraints. It has to be a query-base-solution.
First delete those companies' clients
delete client where id in (select fk_client_company from company where id > 140000)
After that you should be able to run the delete statement on the company table
delete company where id > 140000
I'm 'fairly' sure that's the answer you're looking for but I'm not a 100% positive only because your naming scheme seems a little odd. I'm making the assumption that company.fk_client_company = client.id.