Transform Many to Many relation to One to Many relation - sql

I have the following tables (simplified):
create table dbo.Users
(
User_Id int identity not null
constraint PK_Users_Id primary key clustered (Id),
);
create table dbo.UsersSeals
(
UserId int not null,
SealId int not null,
constraint PK_UsersSeals_UserId_SealId primary key clustered (UserId, SealId)
);
create table dbo.Seals
(
Seal_Id int identity not null
constraint PK_Seals_Id primary key clustered (Id),
);
alter table dbo.UsersSeals
add constraint FK_UsersSeals_UserId foreign key (UserId) references Users(Id) on delete cascade on update cascade,
constraint FK_UsersSeals_SealId foreign key (SealId) references Seals(Id) on delete cascade on update cascade;
So I have a MANY to MANY relation between Users and Seals. One user can have many seals and on seal can have many users. I need a ONE to MANY where one user can have many seals but a seal has only one user.
Yes, I could remove the UsersSeals table and add a UserId into Seals table. However, I am using seals, the same way, with other tables.
I would like to have only one Seals tables with One to Many relation with Users tables and other tables.
Can this be done?

Add a separate unique constraint on the UsersSeals table on your SealID column
You then guarantee that this table is unique on SealID, which means that one seal can be associated with only one user but a user can have many seals.

Related

SQL table stopping me from adding foreign key

I'm creating a SQL table in VS that stores what rooms each client is, So the table has RoomId (int) and UserID (int).
Because I only want to add to the table only rooms and clients that exist they are both keys that have a foreign key to 2 tables, one that stores RoomID and Name and another that stores Client ID and Name.
Room and UserId tables:
CREATE TABLE [dbo].[UsersInRoomsTable]
(
RoomId INT NOT NULL,
UserId INT NOT NULL,
CONSTRAINT PK_RS PRIMARY KEY(RoomId, UserId),
CONSTRAINT [fk_room] FOREIGN KEY([RoomId]) REFERENCES [dbo].[RoomsTable]([RoomId]),
CONSTRAINT [fk_user] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserInfoTable] ([UserId])
);
Table that stores all the users:
CREATE TABLE [dbo].[UserInfoTable]
(
[UserName] NVARCHAR (50) NOT NULL,
[UserId] INT NOT NULL,
CONSTRAINT [PK_roomuser] PRIMARY KEY CLUSTERED ([UserName] ASC, [UserId] ASC)
);
Table that stores all the rooms
CREATE TABLE [dbo].[RoomsTable]
(
[RoomId] INT NOT NULL,
[RoomName] NVARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([RoomId] ASC)
);
Everything works except the last line in the Rooms and users table:
CONSTRAINT [fk_user] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserInfoTable] ([UserId])
When I try to Update the table I get an error SQL71516:
SQL71516: The referenced table '[dbo].[UserInfoTable]' contains no primary or candidate keys that match the referencing column list in the foreign key.
If the referenced column is a computed column, it should be persisted
How can I solve this problem and what is causing it?
Edit: I think I know what is code is colliding: For some reason I can not have a foreign key connecting to a key that contains 2 indexes IE: fk_user is a Fk to table UserInfoTable that has 2 keys (UserID and UserName)
is there a way to pass this obstacle?
The columns of a foreign key have to match the columns they reference by number, type and order.
You have a primary key on userinfotable of (username, userid). But in usersinroomstable you are trying to let the foreign key (userid) to reference that. The number of columns doesn't match, so the foreign key cannot be added.
Presumably the username shouldn't really be part of the primary key of userinfotable and got there by accident. Remove it from the primary key constraint.
Or, if username has to be in the primary key, add such a column to the table usersinroomstable and add it to the foreign key constraint.

PostgreSQL | How to store user answers in survey?

I have task to create survey which aviable only by invitation to certain people. One person can take the survey once. The survey is only available for a specific period of time. I am tring to create database structure for this future application. As database I use PostgreSQL.
As I understand one survey can have many questions. In the same time one question can be reused in many surveys. It's many to many relationship.
Thats how I created tables which solve this first task. Please correct me if I'm somewhere missed or did wrong.
QUESTIONS TABLE:
CREATE TABLE QUESTIONS(
ID SERIAL PRIMARY KEY,
TEXT TEXT NOT NULL
);
SURVEYS TABLE:
CREATE TABLE SURVEYS(
ID UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
NAME VARCHAR NOT NULL,
DESCRIPTION TEXT,
START_PERIOD TIMESTAMP,
END_PERIOD TIMESTAMP
);
SURVEYS_QUESTIONS TABLE:
CREATE TABLE SURVEYS_QUESTIONS(
ID SERIAL,
SURVEY_ID UUID NOT NULL,
QUESTION_ID INT NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SURVEY_ID) REFERENCES SURVEYS (ID) ON DELETE CASCADE,
FOREIGN KEY (QUESTION_ID) REFERENCES QUESTIONS (ID) ON DELETE CASCADE
);
Right now I don't understand how correctly connect users with surveys and how correctly store user answers.
Create a TAKEN_SURVEYS table with a foreign key to the SURVEYS table and a foreign key to the USERS table. If you want to ensure there can be only one taken survey record per user, create a unique index on the TAKEN_SURVEYS table.
Consider replacing your last table with two new tables. This would align with classic 101 example of Customers-Orders-Products (here being Users-Surveys-Q&A).
CREATE TABLE USER_SURVEYS (
ID SERIAL,
USER_ID UUID NOT NULL,
SURVEY_ID UUID NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (USER_ID) REFERENCES USERS (ID) ON DELETE CASCADE,
FOREIGN KEY (SURVEY_ID) REFERENCES SURVEYS (ID) ON DELETE CASCADE
);
CREATE TABLE USER_SURVEYS_QA (
ID SERIAL,
USER_SURVEY_ID INT NOT NULL,
QUESTION_ID INT NOT NULL,
ANSWER VARCHAR(255),
OTHER_SPECIFY VARCHAR(255),
PRIMARY KEY (ID),
FOREIGN KEY (USER_SURVEY_ID) REFERENCES USER_SURVEYS (ID) ON DELETE CASCADE,
FOREIGN KEY (QUESTION_ID) REFERENCES QUESTIONS (ID) ON DELETE CASCADE
);

How to establish foreign key relationship

I got three tables.
User
Project
WorkFlow
In workflow ProjectId, UserId together should never repeat. Thats my
requirement.I mean the combination should never repeat.
And the ProjectId should be present in the Project table and UserId
should be present in the User table.
This is the requirement.
Steps i tried :
I made ProjectId, UserId as composite key in workFlow. But cant be able to maintain foreign key since two columns are not available in single table.
How to resolve this.
I am open to change my design also, since this is the initial stage of my development.
Main reuirement is
One table to store project (project table) related informations and
the other one(workFlow) hold the record which project is assigned to
which user.
Foreign keys do not control uniqueness; they only control referential integrity. For uniqueness, you need unique constraints:
create table dbo.Workflow (
Id int identity(1,1) primary key,
ProjectId int not null,
UserId int not null,
foreign key (ProjectId) references dbo.Project (Id),
foreign key (UserId) references dbo.[User] (Id),
unique (UserId, ProjectId)
);
EDIT: If you don't need a surrogate key in this table, and don't care much about its possible children, you can simplify the structure by switching from surrogate primary key to the natural one. With table becoming more narrow, it will increase performance in high load scenarios by reducing its disk footprint:
create table dbo.Workflow (
ProjectId int not null,
UserId int not null,
primary key (UserId, ProjectId)
foreign key (ProjectId) references dbo.Project (Id),
foreign key (UserId) references dbo.[User] (Id),
);
And yes, constraints should be uniquely named, it will make schema comparisons and updates much easier.

Is it possible to reference a primary key in one table as a foreign key constraint across more than 2 tables?

I am currently making a database back end system on an airport, using sql through the phpmyadmin server. The criteria is not meant to be perfect but one of the ideas behind the queries is to imagine that either a customer or flight dispatch officer might be looking at the tables. I was wondering if it was possible to reference a primary key as a foreign key across 2 or more tables. In the example below, I want to reference the model number as a foreign key in the bottom 2 tables. I have ensured that the type and character count are the same.
CREATE TABLE Aircraft_Model
(Model_Number varchar (12) NOT NULL,
seat_capacity int (3),
CONSTRAINT pk7 primary key (Model_Number));
CREATE TABLE Licence_type
(Rank varchar (25) NOT NULL,
Model_Number varchar (12),
CONSTRAINT pk9 primary key (Rank));
CREATE TABLE Aircraft
(Aircraft_ID varchar (4) NOT NULL,
Model_Number varchar(12),
airport_base text(13),
CONSTRAINT pk1 PRIMARY KEY (Aircraft_ID));
Is this possible? I only want the database to be able to perform about 12-15 simple queries.
Would the syntax of adding a foreign key be something like this?
ALTER TABLE Aircraft
ADD CONSTRAINT fk1 FOREIGN KEY(Model_Number)
REFERENCES Aircraft_Model
Does the same foreign key being referenced from a separate table such as Licence_type need a separate constraint to be added or can it be added from the same one with the same fk1 number?
I was wondering if it was possible to reference a primary key as a
foreign key across 2 or more tables.
If you mean, "Can two or more tables have foreign keys that reference the same column?", then, yes, you can do that. This seems to be what you mean, but it's not what most people mean when they talk about "a foreign key across 2 or more tables".
Declare two different, separate constraints.
ALTER TABLE Aircraft
ADD CONSTRAINT fk1 FOREIGN KEY(Model_Number)
REFERENCES Aircraft_Model (Model_Number);
ALTER TABLE License_Type
ADD CONSTRAINT fk2 FOREIGN KEY(Model_Number)
REFERENCES Aircraft_Model (Model_Number);

Problem creating foreign keys in mySql

I created a foreign key in my sql by the following statemnt..
ALTER TABLE `users` ADD FOREIGN KEY ( `id`)
REFERENCES `user_login` (`user_id`)
ON DELETE CASCADE ;
The creation appears to succeed then after that I execute a delete statement
DELETE From user_login WHERE user_id = 1576;
yet in users the row still exists that is referencing that. I open up the mysql workbench and it doesn't show any signs that the foreign key was created. Does anyone know why this would be? Or what I am doing wrong? It is a one-to-one relationship in the two tables.
The table may be in MyISAM format, which does not support foreign keys.
Try converting it to InnoDB first:
alter table users engine=InnoDB;
You have to also make sure that both users.id and user_login.user_id have an index each.
Copy and paste this code in your Mysql script editor and run. You will have two tables categories and products these tables having cat_id as foreign key.
CREATE DATABASE IF NOT EXISTS dbdemo;
USE dbdemo;
CREATE TABLE categories(
cat_id int not null auto_increment primary key,
cat_name varchar(255) not null,
cat_description text
) ENGINE=InnoDB;
CREATE TABLE products(
prd_id int not null auto_increment primary key,
prd_name varchar(355) not null,
prd_price decimal,
cat_id int not null,
FOREIGN KEY fk_cat(cat_id)
REFERENCES categories(cat_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
)ENGINE=InnoDB;