How do I translate relationships (that have attributes) into relational schema/sql? - sql

I am relatively new to database design.
I've recently learnt that relationships in EER can possess attributes, and thus, have constructed the following entities.
LibraryMembers
(memberID)
Books
(bookID)
The two entities are connected through the relationship "reserve", each book able to be reserved by 0 to 1 LibraryMember, and each LibraryMember being able to reserve 0 to many books.
Now, here comes the problem. I have assigned attributes such as time and date to the "reserve" relationship, and I have no idea how to translate this into relational schema. The relationship between LibraryMembers and Books is not a many to many, is it still possible to create a table called "reserve" to link them?
(I've been taught that an additional table is only created when the relationship maps from a many to many EER)
Help would be very much appreciated, thank you.

You can map members and books in reservations like this
CREATE TABLE members(
member_id INT,
member_name VARCHAR(64),
PRIMARY KEY(member_id)
);
CREATE TABLE books(
book_id INT,
title VARCHAR(64),
PRIMARY KEY(book_id)
);
CREATE TABLE reservations(
reservation_id INT,
book_id INT,
member_id INT,
reservation_date DATETIME,
PRIMARY KEY(reservation_id),
CONSTRAINT FOREIGN KEY (book_id) REFERENCES books (book_id),
CONSTRAINT FOREIGN KEY (member_id) REFERENCES members (member_id)
);
But you still need to implement logic that prevents a book to be reserved twice at the same time as #Najzero commented.

Related

Should i make the Painting and Sculpture table weak entities? Does that mean they don't need primary keys

So I have three tables: Art, Sculpture and Painting (The latter two are subclasses of the first one). Since the subclasses already have the ArtID reference, in my opinion, they don't need their own primary keys (SculptureID and PaintingID). Should I make these subclasses weak entities (meaning I'll remove the primary keys). And in they ERD diagram, should I represent them as weak entities?
What I really want to ask is, can a superclass have subclasses that are weak entities?
If there is a foreign key reference in the subclasses, would they still remain a weak entity?
--Creating Subclass of Asset; Art itself is a superclass
CREATE TABLE Art(
ArtID Varchar(50) NOT NULL PRIMARY KEY,
ArtName Varchar(50),
AssetID VARCHAR(50) FOREIGN KEY REFERENCES Asset(AssetID),
ArtistId VARCHAR(50) FOREIGN KEY REFERENCES Artist(ArtistID),
MadeBy VARCHAR(50) FOREIGN KEY REFERENCES Artist(ArtistName),
CONSTRAINT UC_Person UNIQUE (ArtName)
);
--Creating table for Art types: Painting :
CREATE TABLE Painting(
PaintingID Varchar(50) NOT NULL PRIMARY KEY,
ArtID VARCHAR(50) FOREIGN KEY REFERENCES Art(ArtID),
CanvasType VARCHAR(50),
);
--Creating table for Art types: Sculpture :
CREATE TABLE Sculpture(
SculptureID Varchar(50) NOT NULL PRIMARY KEY,
ArtID VARCHAR(50) FOREIGN KEY REFERENCES Art(ArtID),
Material VARCHAR(50),
Style VARCHAR(50),
Dimension VARCHAR(50),
);
When you say "remove the primary keys" I think what you really mean is "remove the surrogate keys. The subclass tables would both still have a primary key, but the primary key would be ArtID. This would be both a primary key as well as a foreign key to the Art table, creating a "zero or one to one" relationship from each subtype to the parent type.
The short answer is that yes, you should remove the surrogate keys. They are not serving any purpose unless you explicitly want to be able to have one artwork be referenced by more than one painting or more than one sculpture, which seems semantically unlikely. In fact the only thing they are doing right now is allowing that many-to-one relationship to happen, which I expect would be a mistake in the model.
Having said that, I can imagine a scenario where you might want to say "this artwork is made up of multiple sculptures and I want to track the sculptures independently", but given that you are referring to this as a subtyping relationship, that doesn't seem to be the situation you're in.
The next question is: is this an exclusive subtype relationship? That is to say, is it true that an artwork can be either a painting, or a sculpture, but not both? Or is it true that an artwork can be both a sculpture and a painting?
Again, using normal language semantics, I expect the former is true - the artwork must be either a painting or a sculpture, not both. So it's an exclusive subtype relationship.
If that's true, then the following schema does not guarantee the desired subtype exclusivity, because nothing prevents me from putting the same ArtId in both the Paintings table and the Sculptures table (I am going to use plural table names, because tables are sets):
create table Artworks (ArtId int primary key);
create table Paintings (ArtId int primary key, foreign key references Artworks);
create table Sculptures (ArtId int primary key, foreign key references Artworks);
So the next question is, how strictly do you want the database to enforce the real world domain constraints? The above schema "works" if you just want a place to store data. It doesn't model all of the domain constraints, i.e. it allows data to exist that would contradict the real world being modelled. But enforcing the domain constraints correctly means doing more work on the schema, and adding things that look "strange", like this:
create table Artworks
(
ArtId int unique,
SubType char check (SubType in ('p', 's')),
primary key (ArtId, SubType)
);
create table Paintings
(
ArtId int,
SubType char default ('p') check (SubType = 'p'),
primary key (ArtId, SubType),
foreign key (ArtId, SubType) references Artworks
);
create table Sculptures
(
ArtId int,
SubType char default ('s') check (SubType = 's'),
primary key (ArtId, SubType),
foreign key (ArtId, SubType) references ArtWorks
);
This now enforces the exclusive subtype relationship. But it's "a bit strange", because now the Artworks table has a check constraint on it that is aware of all possible subtypes. This is an odd sort of dependency inversion - the subtype obviously has to be an artwork, but it's not the case that artworks should have to be aware of all possible subtypes. But in this relational implementation, enforcing that exclusivity does require it. It also means if you want to add more subtypes later you have to update the constraint on Artworks. So we've enforced the domain constraint at the cost of creating a bit of necessary smelliness in the schema.
There is a lot more that could be said on this topic. As The Impaler mentioned in their comment, there are a few ways of doing subtyping in a relational model, and at the end of the day there are tradeoffs in terms of schema complexity, domain integrity, and the amount of typing required to query the system.
But no matter what you decide to go with, I say remove the surrogate keys. They are only doing harm.

Duplicate Primary Keys?

Looking at an example from Java Persistence with Hibernate, there are 2 tables:
create table USERS (
USER_ID bigint not null primary key,
USERNAME varchar(15) not null unique,
NAME varchar(50) not null,
...
)
create table BILLING_DETAILS (
BILLING_DETAILS_ID bigint not null primary key,
ACCOUNT_NUMBER VARCHAR(10) not null unique,
ACCOUNT_NAME VARCHAR(50) not null,
ACCOUNT_TYPE VARCHAR(2) not null,
USER_ID bigint foreign key references USERS
)
The book mentions that the following indicates a many-to-one relationship:
USER_ID bigint foreign key references USERS
Next, it says that the following SQL statements show one-to-one associations:
USER_ID bigint unique foreign key references USERS
BILLING_DETAILS_ID bigint primary key foreign key references USERS
As I understand, the first statement means that USER_ID of the BILLING_DETAILS table will be unique and reference the primary_key of the USERS table, i.e. references USERS.
The second makes the BILLING_DETAILS_ID the primary_key and reference the USERS's primary key.
If we used both of these one-to-one relationships, then we'd have duplicate fields: USER_ID and BILLING_DETAILS_ID since they effectively are the same data?
They aren't necessarily the same data in the absence of an additional CHECK() constraint that requires user ID and billing details ID to be equal.
I have not read the book, but as a database professional, I'd consider that implementation of a one-to-one relationship to be in error. A unique constraint on billing_details.user_id, along with its obvious foreign key constraint, is sufficient to guarantee a one-to-one relationship between the two tables. (That kind of relationship doesn't make much sense in the real world, though, when you think about what billing details means.)
From a database viewpoint, letting billing_details.user_id be nullable seems questionable, too.
Later . . .
I just thought of an alternative explanation of what the book says. When it says
USER_ID bigint unique foreign key references USERS
BILLING_DETAILS_ID bigint primary key foreign key references USERS
it's describing two different ways to implement a one-to-one relationship. It's not saying you should use both statements to implement one one-to-one relationship.
But this, too, is an error, in that USER_ID isn't declared to be NOT NULL.
BILLING_DETAILS_ID is practically the primary key, which means it cannot be duplicated. However, USER_ID is NOT, you can have duplicated USER_ID in the table BILLING_DETAILS, it is treated as a data which should have a reference in the table USER.
the relationship between BILLING_DETAILS and USER is one(USER)-to-many(BILLING_DETAILS)

Translating diagram to SQL Database

I'm having trouble seeing how I should translate this diagram into my database with tables. I'd like to add that I'm very new to this. This is a picture of an example that I want to translate into my SQL Database:
I'm not really sure how a diagram like this could look in my SQL Database, haven't really worked with inheritance. Would really appreciate if someone could demostrate how this could look with tables in SQL.
Thanks.
EDIT:
create table Person(
IDCode CHAR(10) UNIQUE NOT NULL,
primary key (IDCode),
);
create table Student(
IDCode CHAR(10) UNIQUE NOT NULL,
Name VARCHAR(15),
Course VARCHAR(15)
primary key (Name),
foreign key (IDCode) references Person (IDCode)
);
create table Teacher(
IDCode CHAR(10) UNIQUE NOT NULL,
Name VARCHAR(15),
Course VARCHAR(15)
primary key (Name),
foreign key (IDCode) references Person (IDCode)
);
create table StudentTeacherRelationship(
StudentName VARCHAR(15),
TeacherName VARCHAR(15),
primary key(StudentName,TeacherName),
foreign key(StudentName) references Student (Name),
foreign key(TeacherName) references Teacher (Name),
It means:
a person has a id number
both students and teachers are persons and they have their id information in person table, and one student/teacher has only one id
a student can have many teachers
a teacher can teach to many students
so there should be 4 tables(just psudo pseudo code to give you an idea):
person table:
id_person, (the primary key)
real_id (the real id, can be anything)
student table:
id_student,
id_person,
name,
other_stuff
teacher table:
id_teacher
id_person,
name,
other_stuff
a techer_student table (which make it many to many)
id_student
id_teacher
There are several ways to deal with inheritance situation in databases, JPA, for example, defines 3 strategies for inheritance in databases, these are: Single Table, Table for Class and Joined, they are all best described (including table/class examples) in the following link

Help me normalize my simple book catalog schema

This is a simple database model for an online library catalog. I am trying to normalize it, if possible. What do you think I should change or do differently?
For example, I am not sure about the table authors. It has only one column "name" which is also a primary key and I use it also as a foreign key in another table. Is that a good practice? Also should I put two columns there ("first_name" and "last_name") instead of just one?
CREATE TABLE books (
isbn VARCHAR2(13) NOT NULL PRIMARY KEY,
title VARCHAR2(200),
summary VARCHAR2(2000),
date_published DATE,
page_count NUMBER
);
CREATE TABLE authors (
name VARCHAR2(200) NOT NULL PRIMARY KEY
);
CREATE TABLE books_authors_xref (
author_name VARCHAR2(200),
book_isbn VARCHAR2(13),
CONSTRAINT pk_books_authors_xref PRIMARY KEY (author_name, book_isbn),
CONSTRAINT fk_books_authors_xref1 FOREIGN KEY (author_name) REFERENCES authors (name),
CONSTRAINT fk_books_authors_xref2 FOREIGN KEY (book_isbn) REFERENCES books (isbn)
);
CREATE TABLE book_copies (
barcode_id VARCHAR2(100) NOT NULL PRIMARY KEY,
book_isbn VARCHAR2(13),
CONSTRAINT fk_book_copies FOREIGN KEY (book_isbn) REFERENCES books (isbn)
);
It's reasonably normalized. I'd add a numeric "author_id" to the authors table and use that instead of author_name in the books_authors_xref table and use that for the relationships, which lets you do things like deal with two authors with the same name, and change how you store the name later without making a mess. :-)
I think all four tables are in 5NF. What do you think?
But . . .
Author names aren't unique. Adding an ID number to the authors table identifies the row, but it doesn't identify the author. For example, assume there are two authors with the name "Richard Knop". You can't enter both into your existing table, because there's a primary key constraint on author names. If you try to fix that by adding an ID number, you might end up with this.
author_id author_name
--
1 Knop, Richard
2 Knop, Richard
Which one of those is you? How do you know?
In addition to using an "author_id" as mentioned by Christo and Catcall, you might also consider using a "book"id" for the primary key on your book table. Not all things published/printed have an ISBN-- either because the book predates ISBN or it was printed by someone that didn't think it needed an ISBN (such as a lot of the training material that I've seen over the years).
I try this and it simply works... I make little bit change and table is created. Moreover,
ISBN is used as foreign key.
CREATE TABLE book_copies
( barcode_id VARCHAR2(100) NOT NULL PRIMARY KEY,
ISBN VARCHAR2(13),
CONSTRAINT FK_BOOK_COPIES FOREIGN KEY (ISBN )REFERENCES books (isbn))

How Can I Reference Multiple Primary Keys For A Vector Type Primary Key

I have the following scenario: a table of projects and a table of persons, working on one or several projects. Also, I have a project id column (of type int), in the first table, which is a primary key there and I have a vector of project ids, as a column of type int, in my second table (persons), that references primary keys from the first table.
What is the correct syntax for referencing multiple primary keys, from a vector foreign key.
This is the way I am trying to create the table, but I am not sure what to place at the indicated line:
CREATE TABLE Persons(
Person_Id int,
...,
ProjectsList int[],
FOREIGN KEY (ProjectsList) REFERENCES Projects(Project_id) -- not sure what how to define the link here
);
I hope my explanations are not over-complicated. Thank you in advance for helping!
I assume you're using PostgreSQL, since that's one of the rare databases that supports array data types.
There is no syntax for declaring a foreign key that applies to the elements of an array.
You could write a trigger or a CHECK constraint as mentioned here.
But the better solution is to add a table to implement the many-to-many relationship between Projects and Persons, as Lukáš Lalinský shows. This supports First Normal Form.
No database I know can do that (using real foreign keys, not some custom triggers). You might want to normalize the tables:
CREATE TABLE Persons (
Person_ID int,
...
PRIMARY KEY (Person_ID)
);
CREATE TABLE PersonProjects (
Person_ID int,
Project_ID int,
PRIMARY KEY (Person_ID, Project_id),
FOREIGN KEY (Person_ID) REFERENCES Persons(Person_ID),
FOREIGN KEY (Project_ID) REFERENCES Projects(Project_ID)
);