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.