SQL Server - Create an identifying relationship - sql

I'm currently designing a database to be implemented in SQL Server. I created the following tables without problem:
CREATE TABLE [Client] (
[ClientId] INT NOT NULL,
[Name] VARCHAR(45) NOT NULL,
[IsEnabled] BIT NOT NULL DEFAULT 1,
CONSTRAINT PK_TCASystem PRIMARY KEY CLUSTERED (
ClientId
)
);
CREATE TABLE [Configuration] (
[ConfigId] INT NOT NULL,
[ClientId] INT NOT NULL,
[Name] VARCHAR(45) NOT NULL,
CONSTRAINT PK_Configuration PRIMARY KEY CLUSTERED (
ConfigId, ClientId
),
CONSTRAINT "FK_SystemConfiguration" FOREIGN KEY
(
ClientId
) REFERENCES [Client] (
ClientId
)
);
However, when I tried to add this one:
CREATE TABLE [Mail] (
[MailId] INT NOT NULL,
[ConfigId] INT NOT NULL,
[Recipient] VARCHAR(500) NOT NULL,
[Sender] VARCHAR(50) NOT NULL,
[Subject] VARCHAR(250) NOT NULL,
[Message] TEXT NULL,
CONSTRAINT PK_Mail PRIMARY KEY CLUSTERED (
MailId, ConfigId
),
CONSTRAINT "FK_ConfigurationMail" FOREIGN KEY
(
ConfigId
) REFERENCES [Configuration] (
ConfigId
)
);
I got an error saying that There are no primary or candidate keys in the referenced table 'Configuration' that match the referencing column list in the foreign key 'FK_ConfigurationMail'. I believe this is because the constraint is trying to reference ConfigId, only one half of the composite key, and for this to work I'd need to reference the ClientId too, is that correct?
But my problem is that I first did the design for this database in MYSQL Workbench, and there I indicated that Configuration and Mail, as well as Client and Configuration, have a 1:n identifying relationship (because a Mail instance cannot be created if there isn't a Configuration instance first, and at the same time a Configuration instance cannot exist without having being assigned to a Client first), and as such it created the composite keys for Configuration and Mail. You can see a picture of that here.
So my question is, how can I translate this identifying relationship to SQL Server? Or is that not possible?
EDIT: As suggested I will remove the composite keys from the Configuration table, albeit my question still stands: If I have a 1:n identifying relationship where one of the tables involved uses composite keys, how can I display this on SQL Server? Or is such a case never supposed to happen?
2ND EDIT: To anyone who might come across this question, this post is well worth a read. Cleared up all my confusion in the matter.

Foreign key must reference PK (the entire PK, not portion of PK) or unique index. So add this between create table [Configuration] and [Mail].
CREATE UNIQUE NONCLUSTERED INDEX [UX_Configuration] ON [Configuration]
(
[ConfigId] ASC
)
Check out at sql fiddle for the whole working script:
http://www.sqlfiddle.com/#!3/8877f

Related

Expecting 1-To-Many however creating 1-1 SQL

I want to create a one to many relationship between two tables but for some reason a one to one relationship is being created.
It's strange because identical code for two other tables in the same DB are creating 1-Many relationships as expected.
Here is my code
CREATE TABLE thing
(
ThingID INT NOT NULL,
Words VARCHAR(50) NOT NULL,
OtherWords INT NOT NULL,
CONSTRAINT pk_TRIPID PRIMARY KEY (ThingID),
)
CREATE TABLE otherthing
(
ThingID INT NOT NULL,
Cost SMALLMONEY NOT NULL,
MoreWords INT NOT NULL,
CONSTRAINT pk_Trip PRIMARY KEY (ThingID),
CONSTRAINT fk_Trip FOREIGN KEY (ThingID) REFERENCES thing(ThingID)
)
Any help you can offer is very appreciated.
Both tables have a primary key of thingid.
This prevents many being inserted in either table. The second table needs the primary key removed and ideally changed to a different primary key so that more than one row matching a given thingid can be inserted into it.

Are these FKs necessary -- and are they stopping me?

I'm having some difficulties with a database I'm creating for a summer camp, specifically with the PK and FK constraints. When I declare the FK constraint (e.g. FOREIGN KEY(PID) references Campers(CamperID)) I get an error running my code through pgAdmin (I'm using PostgreSQL). I understand that, for example, the Campers table is not yet created, and this is most likely part/all of the roadblock, however I feel like my FKs are still wrong somehow. To my understanding, a FK is a PK in another table -- but I feel like there is some redundancy or disconnect between my tables.
I've put the syntax for some of my CREATE statements below. I'm not sure if I'll get reprimanded for the quality of my (somewhat vague) question, but I feel a bit lost and would appreciate any help or advice. Thank you in advance!
DROP TABLE IF EXISTS People;
CREATE TABLE People (
PID VARCHAR(10) NOT NULL UNIQUE,
FName TEXT NOT NULL,
LName TEXT NOT NULL,
DOB DATE NOT NULL,
ArrivalDate DATE NOT NULL DEFAULT CURRENT_DATE,
DepartureDate DATE,
US_PhoneNum VARCHAR(11) NOT NULL,
StreetAddress VARCHAR(200) NOT NULL,
Sex GENDER NOT NULL,
ZIP VARCHAR(10) NOT NULL,
PRIMARY KEY(PID),
FOREIGN KEY(PID) REFERENCES Campers(CamperID),
FOREIGN KEY(PID) REFERENCES Counselors(CounselorID),
FOREIGN KEY(ZIP) REFERENCES Zip(ZIP)
);
DROP TABLE IF EXISTS Zip;
CREATE TABLE Zip (
ZIP VARCHAR(10) NOT NULL,
City TEXT NOT NULL,
State VARCHAR(2) NOT NULL,
PRIMARY KEY(ZIP)
);
DROP TABLE IF EXISTS Campers;
CREATE TABLE Campers (
CamperID VARCHAR(10) NOT NULL REFERENCES People(PID),
AgeGroup AGES NOT NULL,
CabinID VARCHAR(2) NOT NULL,
Bed BEDTYPES NOT NULL,
GroupID VARCHAR(3) NOT NULL,
PRIMARY KEY(CamperID),
FOREIGN KEY(CamperID) REFERENCES People(PID),
FOREIGN KEY(CabinID) REFERENCES Cabins(CabinID),
FOREIGN KEY(Bed) REFERENCES Beds(Bed),
FOREIGN KEY(GroupID) REFERENCES Groups(GroupID)
);
DROP TABLE IF EXISTS Counselors;
CREATE TABLE Counselors (
CounselorID VARCHAR(10) NOT NULL REFERENCES People(PID),
GroupID VARCHAR(3) NOT NULL,
CabinID VARCHAR(2) NOT NULL,
PRIMARY KEY(CounselorID),
FOREIGN KEY(GroupID) REFERENCES Groups(GroupID),
FOREIGN KEY(CabinID) REFERENCES Cabins(CabinID)
);
ERROR message for further clarification:
ERROR: relation "campers" does not exist
********** Error **********
ERROR: relation "campers" does not exist
SQL state: 42P01
There are more tables (obviously) which I can provide the create statements for, if needed.
You should really start here: Foreign key.
In the context of relational databases, a foreign key is a field (or
collection of fields) in one table that uniquely identifies a row of
another table.
What you are trying to do in your script is to create a circular link between People, Campers and Counselors. Having a Primary Key field also a Foreign Key mandates that IDs across all referenced tables are identical.
... and to create a Foreign Key the referenced table must already exist in the database. So you should start with the table that does not have any Foreign Keys and create tables that reference only those tables created previously. Alternatively you can create all tables without Foreign Keys and add them later, when all the tables are present.
... and to answer the question, Foreign Keys are never necessary, but they might help.

Two Composite Primary Key in SQL

I am trying to define table as follows:
CREATE TABLE dbo.[User]
(
Id int NOT NULL IDENTITY PRIMARY KEY,
Name nvarchar(1024) NOT NULL
);
CREATE TABLE [Group]
(
Id int NOT NULL IDENTITY PRIMARY KEY,
Name nvarchar(1024) NOT NULL
);
CREATE TABLE [UserToGroup]
(
Name VARCHER(20)
UserId int NOT NULL,
GroupId int NOT NULL,
PRIMARY KEY CLUSTERED ( UserId, Name),
PRIMARY KEY CLUSTERED ( GroupId, Name),
FOREIGN KEY ( UserId ) REFERENCES [User] ( Id ) ON UPDATE NO ACTION ON DELETE CASCADE,
FOREIGN KEY ( GroupId ) REFERENCES [Group] ( Id ) ON UPDATE NO ACTION ON DELETE CASCADE
);
How can i create table with two Composite Primary Key?
Name VARCHAR(20) NOT NULL,
UserId int NOT NULL,
GroupId int NOT NULL,
UNIQUE ( UserId, Name),
UNIQUE ( GroupId, Name)
In the relational model and in SQL there is no logical difference between one key and another so there's no very strong reason to have a different syntax for specifying one key over any other. However, for better or worse, the authors of the SQL standard decided to make a limitation that the PRIMARY KEY constraint syntax can only be used once per table and that where you need more than one key you have to use one or more UNIQUE constraints instead. Arguably it would be desirable to drop that limitation but since it's fundamentally just a bit of syntactical sugar that's unlikely to happen any time soon.

Use a common table with many to many relationship

I have two SQL tables: Job and Employee. I need to compare Job Languages Proficiencies and Employee Languages Proficiencies. A Language Proficiency is composed by a Language and a Language Level.
create table dbo.EmployeeLanguageProficiency (
EmployeeId int not null,
LanguageProficiencyId int not null,
constraint PK_ELP primary key clustered (EmployeeId, LanguageProficiencyId)
)
create table dbo.JobLanguageProficiency (
JobId int not null,
LanguageProficiencyId int not null,
constraint PK_JLP primary key clustered (JobId, LanguageProficiencyId)
)
create table dbo.LanguageProficiency (
Id int identity not null
constraint PK_LanguageProficiency_Id primary key clustered (Id),
LanguageCode nvarchar (4) not null,
LanguageLevelId int not null,
constraint UQ_LP unique (LanguageCode, LanguageLevelId)
)
create table dbo.LanguageLevel (
Id int identity not null
constraint PK_LanguageLevel_Id primary key clustered (Id),
Name nvarchar (80) not null
constraint UQ_LanguageLevel_Name unique (Name)
)
create table dbo.[Language]
(
Code nvarchar (4) not null
constraint PK_Language_Code primary key clustered (Code),
Name nvarchar (80) not null
)
My question is about LanguageProficiency table. I added an Id has PK but I am not sure this is the best option.
What do you think about this scheme?
Your constraint of EmployeeId, LanguageProficiencyId allows an employee to have more than one proficiency per language. This sounds counterintuitive.
This would be cleaner, as it allows only one entry per language:
create table dbo.EmployeeLanguageProficiency (
EmployeeId int not null,
LanguageId int not null,
LanguageLevelId int not null,
constraint PK_ELP primary key clustered (EmployeeId, LanguageId)
)
I don't see the point of table LanguageProficiency at the moment.
Same applies to the Job of course. Unless you would like to allow a "range" of proficiencies. But assuming that "too high proficiency" does not hurt, it can easilly be defined through a >= statement in our queries.
Rgds

how do I finish this conversion from SQL Server to Oracle?

I have a partially translate SQL script and several like it that look something like this:
CREATE TABLE STATUSES
( STATUS_ID CHAR(1) NOT NULL,
DESCRIPTION VARCHAR2(50) NOT NULL,
EVENT NUMBER(3) NOT NULL,
RESOLUTION NUMBER(3) NOT NULL,
CONSTRAINT PK_STATUSES PRIMARY KEY CLUSTERED (STATUS_ID ASC));
They were tables defined in SQL Server and I am looking to translate them for use in Oracle, however I am unsure how to handle the CLUSTERED part of the constraint and the ASC attribute of the Primary Key, I have seen some articles out there but they have served to be unhelpful. Can anyone help me complete this, or point me to an article that can help?
Just ignore them. You can remove both the clustered and the asc and the table should be fine in both databases.
I would be inclined to just use the primary key keyword, instead of an explicit constraint:
CREATE TABLE STATUSES (
STATUS_ID CHAR(1) NOT NULL PRIMARY KEY,
DESCRIPTION VARCHAR2(50) NOT NULL,
EVENT NUMBER(3) NOT NULL,
RESOLUTION NUMBER(3) NOT NULL
);
Your table is too small to worry about clustered indexes. It is questionable whether any index at all is useful on such a small table.