How do you implement Table Inheritance in Kotlin Exposed? - kotlin

Example:
I have a base table called Pet with a BirthDate and Name columns.
I have a two more tables that derive from that table, one called PetDog table with column NumberOfTeeth and another called PetBird table with column BeakColor.
How to implement this using Kotlin Exposed? https://github.com/JetBrains/Exposed
Or is there any documentation on this available?

What sort of database and schema do you have in mind? How does it support table inheritance? As Михаил Нафталь already mentioned in the comment, a common approach with a relational database would be to either use one table with all columns or two tables (pet and dog, with some way to link the records in both tables to each other).
A simple example with two tables:
create table pet (id int auto_increment primary key, birthdate varchar(10) not null, "name" varchar(50) not null)
create table dog (id int auto_increment primary key, pet_id int not null, number_of_teeth int not null, constraint fk_dog_pet_id_id foreign key (pet_id) references pet(id) on delete restrict on update restrict)
Your Exposed table definition code could then look something like this:
object Pet : IntIdTable() {
val birthdate = varchar("birthdate", 10)
val name = varchar("name", 50)
}
object Dog : IntIdTable() {
val petId = reference("pet_id", Pet).nullable()
val numberOfTeeth = integer("number_of_teeth")
}

Related

Modeling subclass/superclass while maintaining relational integrity

I'm trying to capture the notion of a subclass/superclass relationship in a relational database. If I start with
abstract class A {
id: UUID
}
class B extends A {
data: String
}
class C extends A {
data: Int
}
I can write:
create table taba (id uuid not null unique, typ char not null);
create table tabb (id uuid not null unique references taba(id),
data varchar);
create table tabc (id uuid not null unique references taba(id),
data int);
Its relational integrity is guaranteed in one direction by the references clause: every derived instance B or C must have its base instance A.
But what about the other direction? I want to guarantee that every base instance A has its derived instance B or C, and ideally that it matches the typ given.
I thought about doing it in a single table, like this:
create table taball (id uuid not null unique, typ char not null,
b_data varchar,
c_ data int);
but that seems to violate the open/closed principle: every time I add a new subclass of A, I have to rewrite taball.
I don't know if this is possible at all (especially because the integrity would be necessarily violated during the actual insert), but I would appreciate any suggestions?
PostgreSQL supports inheritance for tables so you could do the exact same thing the database as in code:
create table taba (id uuid not null unique);
create table tabb (data varchar) inherits (taba);
create table tabc (data int) inherits (taba);
This way when you insert into tabb or tabc there will also be a row available in taba. Depends on the situation if this is a good way to go or not.

Design SQL tables with a list behaviour

I have one table
Client (
id SERIAL PRIMARY KEY );
Another table;
Exercise (
id SERIAL PRIMARY KEY );
And a final table;
Workout (
name VARCHAR,
creator INT REFERENCES Client(id),
exercise INT REFERENCES Exercise(id),
PRIMARY KEY(name,creator,exercise) );
My tables has some other columns aswell but these are all the relevant ones.
A workout has a creator, it is given a name (for example 'legs - monday' or whatever) and then it has a list of unique exercises one is to perform during this workout. So in an Object oriented approach this would look something like
Object Workout
string name
int creator
List<Exercise> exercises
So far this has worked well for me but now i need to create a new table that has a reference to a workout, and i am not sure how to capture this. Maybe my implementation of this is wrong?
table A (
id SERIAL PRIMARY KEY,
workout References Workout(?) );
I cannot reference (name,creator) since it is not marked as unique, and even if it was i would only be able to add one exercise then. It seems silly to reference all rows in Workout (my teacher in relational databases would skin me alive).
Would it be bad practice to just reference one arbitrary entry to a workout (name,creator,exercise)? If i have the name and the creator i can just make a select statement and get all the exercises from them. All rows where the tuple (name,creator) match are said to belong to the same workout.
Children should reference a parent, not vice versa:
create table client (
id serial primary key
);
create table workout (
id serial primary key,
name varchar,
creator int references client(id)
);
create table exercise (
id serial primary key,
workout int references workout(id)
);
Then your list view for a given workout may look like this:
select *
from workout w
left join exercise e on e.workout = w.id
where name = 'some name';
Edit. In case of many-to-many relationship the common way is to create so-called join table, e.g.:
create table workout_parts (
workout int references workout(id),
exercise int references exercise(id),
primary key (workout, exercise)
);

Creating relation between tables in Movie Database

I have created a movie database that contain following tables :
1.Film
2.People
3.Genres
4.Role
5.Users
Here is my sql
create table Film ( id INT(30),title varchar(30),images varchar(30)
primary key (id));
create table people(id INT(30),Fname varchar(30),Lname varchar(30),
primary key (id));
create table Role(id INT(30), name varchar(30),
primary key(id));
i want create relation between Film,People and Role table.SO my Question is do i need to create a table to make relation between those table and is it necessary to use auto_increment for id column?
You'd want to create some tables like:
FilmRole( FilmId INT, RoleId INT) these 2 columns would make your PK and they are also FK's to their
FilmPeople (FilmId INT, PeopleId INT) respective source tables.
FilmUsers( FilmId INT, UserId INT)
You could add a single IDENTITY (for SQL Server for example) column to each table if you wanted but in this particular case a 2 column PK is adequate as these tables simply point to other records.
You need to alter your table and add in a foreign key (Primary key in one table and attribute in another). Examples how to do it here! http://www.w3schools.com/sql/sql_foreignkey.asp
do i need to create a table to make relation between those table ?
YES ! to enforce Referential integrity read this
is it necessary to use auto_increment for id column?
Depends but it is most prefered way of creating a PK on a table

SQL one-to-many

I am trying to build an SQL schema for a system where we have channels, each with an id, and one or more fixtures. I am having difficulty finding a way to implement this one-to-many mapping. (i.e. One channel to many fixtures). I am using the H2 database engine.
I cannot have a table :
id | fixture
----|----------
1 | 1
1 | 2
2 | 3
CREATE TABLE channel(
id INT NOT NULL PRIMARY KEY,
fixture INT NOT NULL
);
... as the PRIMARY KEY id must be UNIQUE.
Similarly, I cannot map as follows:
CREATE TABLE channel(
id INT NOT NULL PRIMARY KEY,
f_set INT NOT NULL REFERENCES fixtures(f_set)
);
CREATE TABLE fixtures(
id INT NOT NULL PRIMARY KEY,
f_set INT NOT NULL
);
... as this required f_set to be UNIQUE
I am currently implementing it as follows:
CREATE TABLE channel(
id INT NOT NULL PRIMARY KEY,
f_set INT NOT NULL REFERENCES fixture_set(id)
);
CREATE TABLE fixtures(
id INT NOT NULL PRIMARY KEY,
f_set INT NOT NULL REFERENCES fixture_set(id)
);
CREATE TABLE fixture_set(
id INT NOT NULL PRIMARY KEY
);
... but this means that we can have a channel with a fixture_set which does not have any assigned fixtures (Not ideal).
I was wondering if you had any suggestions for how i may approach this (Or where my understanding is wrong). Thanks
"One-to-many" means that many items (may) reference one item. If it's one channel to many fixtures, then fixtures should reference channels, not the other way round, which means the reference column should be in the fixtures table:
CREATE TABLE channel(
id INT NOT NULL PRIMARY KEY
);
CREATE TABLE fixtures(
id INT NOT NULL PRIMARY KEY,
channel_id INT NOT NULL FOREIGN KEY REFERENCES channel (id)
);
You can add a CONSTRAINT just to check it.
Sorry for not pasting a snippet... I don't know anything about H2 specifics.
Or you could also avoid the fixture-set concept at all.
Then you would just need:
channel table, with just the id (plus other fields not involved on that matter, of course)
a channelfixtures table, with channelId and fixtureId. Primary key would be composed of (channelId, fixtureId)
a fixture table, only if you need it.

SQL database design for storing different types of "Person"

I need to create a table in a relational database using SQL for persons having the columns Name, LastName and so on.
I'll have three different kinds of People: Seller, Buyer and Customer.
Every person has other information/attributes.
Do I need to create a table for each different type of Person or can a single table be used for all three types?
If I used a single table, what if one type of "Person", say Seller, has different attributes from another Person type?
I would create one table Person , with personId as primary key that will contain common properties for all types.(Seller , Buyer , Customer)
Then I would create PersonTypes, a small reference table , that will declare codes for the different types .
Then for each type I would create a separate table with reference to Person table and
PersonType table that includes all the unique properties.
You can create 1 or two tables. Of course you can create 3 tables for each user role. It depend's on what you would like to achieve. Common solution to your question is: create two tables, one for users and one for their roles (examples for mysql:
Create table `person_role` (
id int not null,
roleName varchar(255) not null,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Create table `person`(
id int not null.
name varchar(255) not null,
lastName varchar(255) not null,
role int not null,
PRIMARY KEY(`id`),
CONSTRAINT FOREIGN KEY(`role`) REFERENCES person_role(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Can a seller ever be a buyer or a customer? If they can, put it all in the same table so that you don't have separate copies of the same data.