I have 3 types of tables. Categories
, Candidates
, Voters
.
To be describing the problem as short as possible, Candidates
can belong to only 1 category. Voters
can vote for each category and only one person from a category. There can not be second person to vote for 1 category. I mean, If Voter votes for Paul, which Paul is a candidate for President, the same voter can not vote for a second presidential candidate, but can vote for Vice President and Secretary.
So the main problem is creating a structure for 1 Voter can vote for 3 types of categories and for only 1 candidate inside of the category
Here are the tables.
CREATE TABLE Categories(
Id INT PRIMARY KEY IDENTITY(1,1),
Name NVARCHAR(20) NOT NULL UNIQUE,
);
CREATE TABLE Candidates(
Id INT PRIMARY KEY IDENTITY(1,1),
Name NVARCHAR(20) NOT NULL,
Surname NVARCHAR(20) NOT NULL,
Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
);
CREATE TABLE Voters(
Id INT PRIMARY KEY IDENTITY(1,1),
Name NVARCHAR(20) NOT NULL,
Surname NVARCHAR(20) NOT NULL,
Age INT NOT NULL CHECK(Age>=18),
);
Here is the table which I encountered with the problem on
CREATE TABLE VotersCandidates(
Id INT PRIMARY KEY IDENTITY(1,1),
Voter_Id INT FOREIGN KEY REFERENCES Voters(Id) NOT NULL,
Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
Candidate_Id INT FOREIGN KEY REFERENCES Candidates(Id) NOT NULL,
);
Thank you to lend a hand!
Advertisement
Answer
The primary key on VoterCandidates
is fine. What you are describing is a unique constraint:
CREATE TABLE VotersCandidates (
Id INT PRIMARY KEY IDENTITY(1,1),
Voter_Id INT FOREIGN KEY REFERENCES Voters(Id) NOT NULL,
Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
Candidate_Id INT FOREIGN KEY REFERENCES Candidates(Id) NOT NULL,
CONSTRAINT unq_VotersCandidates_Voter_Category UNIQUE (Voter_Id, Category_Id)
);
Now, you have another issue . . . it is possible for the category in this table to be inconsistent with the category in the candidates table. To fix that, use another unique constraint and foreign key reference:
CREATE TABLE Candidates (
Id INT PRIMARY KEY IDENTITY(1,1),
Name NVARCHAR(20) NOT NULL,
Surname NVARCHAR(20) NOT NULL,
Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
CONSTRAINT unq_Candidates_Candidate_Category UNIQUE (Category_Id, id)
);
Then use this for the foreign key relationship in the votes table:
CREATE TABLE VotersCandidates (
Id INT PRIMARY KEY IDENTITY(1,1),
Voter_Id INT FOREIGN KEY REFERENCES Voters(Id) NOT NULL,
Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
Candidate_Id INT NOT NULL,
CONSTRAINT fk_voterscandidates_candidates FOREIGN KEY (Category_Id, Candidate_Id) REFERENCES Candidates (Category_Id, Id)
CONSTRAINT unq_VotersCandidates_Voter_Category UNIQUE (Voter_Id, Category_Id)
);
And one final comment. I recommend naming the primary key after the table. So instead of candidates.id
, it would be candidates.candidate_id
. That way, the foreign key relationships are usually on columns with the same name — a form of self-documentation.