I am thinking of three tables;
Employee with emp_id an, emp_name and other related data.
and
Person table with person_id, person_name and other related data.
and
GroupList with grp_list_id, member_id (either emp_id or person_id) and is_employee (true for employee and false for person) and other related data.
This is the first time I am trying to do a table whose foreign key can come from two different tables. Can someone please suggest the best way to achieve it?
Related
I'm doing an exercise to learn database designs. This is some kind of fantasy soccer teams. I have this initial tables, users and teams. One team can have many users and a user can join and belongs to one team.
USERS
PK id
FK team_id -> TEAMS.id
username
TEAMS
PK id
name
But I also want to allow users to create their own teams if they don't want to join another team. What if I added owner_id in teams table?
TEAMS
PK id
FK owner_id -> USERS.id
name
I feel like this is not the right way to do. What is the best way to do this?
You could have a flag in users that indicates if the user owns the team they're a member of and a partial unique index to restrict this flag only being set once for a team.
CREATE TABLE teams
(id serial,
owner_id integer,
PRIMARY KEY (id));
CREATE TABLE users
(id serial,
team_id integer
NOT NULL,
is_owner boolean
NOT NULL
DEFAULT FALSE,
PRIMARY KEY (id),
FOREIGN KEY (team_id)
REFERENCES teams
(id));
CREATE UNIQUE INDEX users_team_id_is_owner
ON users
(team_id)
WHERE is_owner;
db<>fiddle
The index only includes the row that satisfy the WHERE clause, thus all of them have the flag is_owner set to true. Within that subset of rows the team_id must be unique which follows that there can not be any two rows with the same team_id and is_owner set to true.
To ensure a user must be a member of a team, set the team_id to be NOT NULL.
There can be teams without owners in that schema though. But as I understood your question, that is OK.
If i have three type of users. Let's say seller, consumers, and sales persons. Should i make individual table for there details like name, email passwords and all other credentials etc with a role_type table or separate table for each of them. Which is the best approach for a large project considering all engineering principles for DBMS like normalization etc.
Also tell me Does it effect the performance of the app if i have lots of joins in tables to perform certain operations?
If the only thing that distinguishes those people is the role but all details are the same, then I would definitely go for a single table.
The question is however, can a single person have more than one role? If that is never the case, then add a role_type column to the person table. Depending on how fixed those roles are maybe use a lookup table and a foreign key, e.g.:
create table role_type
(
id integer primary key,
name varchar(20) not null unique
);
create table person
(
id integer primary key,
.... other attributes ...,
role_id integer not null references role_type
);
However, in my experience the restriction to exactly one role per person usually doesn't hold, so you would need a many-to-many relation ship
create table role_type
(
id integer primary key,
name varchar(20) not null unique
);
create table person
(
id integer primary key,
.... other attributes ...,
);
create table person_role
(
person_id integer not null references person,
role_id integer not null references role_type,
primary key (person_id, role_id)
);
It sounds like this is a case of trying to model inheritance in your relational database. Complex topic, discussed here and here.
It sounds like your "seller, consumer, sales person" will need lots of different attributes and relationships. A seller typically belongs to a department, has targets, is linked to sales. A consumer has purchase history, maybe a credit limit, etc.
If that's the case,I'd suggest "class table inheritance" might be the right solution.
That might look something like this.
create table user_account
(id int not null,
username varchar not null,
password varchar not null
....);
create table buyer
(id int not null,
user_account_id int not null(fk),
credit_limit float not null,
....);
create table seller
(id int not null,
user_account_id int not null(fk),
sales_target float,
....);
To answer your other question - relational databases are optimized for joining tables. Decades of research and development have gone into this area, and a well-designed database (with indexes on the columns you're joining on) will show no noticeable performance impact due to joins. From practical experience, queries with hundreds of millions of records and ten or more joins run very fast on modern hardware.
I have 4 Tables
Customer(cust_id (PK), cust_phone, name)
Order((order_id,cust_id) (PK), order_date, order_amt)
Order_line((order_id,Product_id)(PK), qty)
Product(product_id, Product_name, product_price)
The order table has a composite key saying an order only exists with a customer.
The Order_line table has a composite key as it is a bridge table between product and order table. the order_amt is a calculated column, its the total order value.
The question is how do i insert data into the order table and the Order_line table? using procedure, triggers or a temp table or any other way? I am really stuck at this. Help!!
Do I need to make any changes in the model?
Hello
I have a main table BASECOMPANYDATA with BaseCompanyDataID as a PK. This is inhereted by
2 other tables CUSTOMERS & PRODUCTCOMPANIES. Now I have the table CONTACTS which I
want to connect with the 2 others as the customers and the productcompanies will have 0 or
more contacts. So I made a FK(BaseCompanyID) in CONTACTS and connected to the
BASECOMPANYDATA PK(BaseCompanyDataID). But when I am trying to insert a contact for
a record which exists in CUSTOMERS I get the following error:
ERROR: insert or update on table "xxxxx" violates foreign key contrain "xxxxx"
DETAIL: Key (BaseCompanyDataID)=(17) is not present in table "BaseCompanyData".
This ID exists in the above inherited table (BaseCompanyData).
Can someone explain why is this happening?
Thanks in advance
PS:Well, I have 4 tables:
1.BASECOMPANYDATA with BaseCompanyDataID as PK and some other fields.
2.CUSTOMERS which inherits from the above table so it has CustomerID as PK and has the fields of the BASECOMPANYDATA table namely BaseCompanyDataID etc.
3.PRODUCTCOMPANIES which inherits from BASECOMPANYDATA so it has the fields ProductCompanyID as PK and the fields of the inherited table like BaseCompanyDataID etc.
4.CONTACTS with ContactID as PK and BaseCompanyDataID as a FK. I tried to connect the table CONTACTS with 2 different ways. a. CONTACTS->BaseCompanyID with CUSTOMERS->BaseCompanyDataID and CONTACTS->BaseCompanyID with PRODUCTCOMPANIES->BaseCompanyDataID b. CONTACTS->BaseCompanyID with BASECOMPANYDATA->BaseCompanyDataID The result was the same error. Any answer on how I can create the FK using the inheritance, if there is. Thanks in advance
Did you read through the inheritance docs? Especially the 5.8.1. Caveats section?
http://www.postgresql.org/docs/9.0/static/ddl-inherit.html
...
Similarly, if we were to specify that cities.name REFERENCES some other table, this constraint would not automatically propagate to capitals. In this case you could work around it by manually adding the same REFERENCES constraint to capitals.
edit:
Inheritance is only half implemented in Postgsresql. If you want to save typing check out like in create table
In your first question I see the person recommended exactly the same thing I said. And now you have a problem? Hmm ...
This is pseudo sql I get from your repost:
base
baseid
customers(base)
baseid
id
products(base)
baseid
id
contacts
id
baseid references base(baseid)
Just do it the good old fashioned way!
base
id
customers
base_id references base(id)
id
products(base)
base_id references base(id)
id
contacts
id
base_id references base(id)
Hopefully my description is a little better than the title, but basically I'm having an issue with one part of a new application schema and i'm stuck on what is the most manageable and elegant solution in table structure.
Bare bones table structure with only relevant fields showing would be as follows:
airline (id, name, ...)
hotel (id, name, ...)
supplier (id, name, ...)
event (id, name,...)
eventComponent (id,name) {e.g Food Catering, Room Hire, Audio/Visual...}
eventFlight (id, eventid, airlineid, ...)
eventHotel (id, eventid, hotelid, ...)
eventSupplier (id, eventid, supplierid, hotelid, eventcomponentid, ...)
So airline, hotel, supplier are all reference tables, and an Event is create with 1 to many relationships between these reference tables. E.g an Event may have 2 flight entries, 3 Other components entries, and 2 hotel entries. But the issue is that in the EventSupplier table the supplier can be either a Supplier or an existing Hotel. So after the user has built their new event on the front-end i need to store this in a fashion that doesn't make it a nightmare to then return this data later.
I've been doing a lot of reading on Polymorphic relations and exclusive arcs and I think my scenario is definitely more along the lines or an Exclusive Arc relationship.
I was thinking:
CREATE TABLE eventSupplier (
id SERIAL PRIMARY KEY,
eventid INT NOT NULL,
hotelid INT,
supplierid INT,
CONSTRAINT UNIQUE (eventid, hotelid, supplierid), -- UNIQUE permits NULLs
CONSTRAINT CHECK (hotelid IS NOT NULL OR supplierid IS NOT NULL),
FOREIGN KEY (hotelid) REFERENCES hotel(id),
FOREIGN KEY (supplierid) REFERENCES supplier(id)
);
And then for the retrieval of this data just use an outer join to both tables to work out which one is linked.
select e.id as eventid, coalesce(h.name,s.name) as supplier
from eventSupplier es
left outer join
supplier s on s.id = es.supplierid
left outer join
hotel h on h.id = es.hotelid
where h.id is not null OR s.id is not null
My other options were to have a single foreign key in the eventSupplier table with another field for the "type" which seems to be a harder solution to retrieve data from, though it does seem quite flexible if I want to extend this down the track without making schema changes. Or alternately to store the hotelid in the Supplier table direct and just declare some suppliers as being a "hotel" though there were then be redundant data which I don't want.
Any thoughts on this would be much appreciated!
Cheers
Phil
How about handling events one-by-one and using an EventGroup to group them together?
EDIT:
I have simply renamed entities to fit the latest comments. This as close as I can get to this -- admittedly I do not understand the problem properly.
A good way to test your solution is to think about what would happen if an airline became a supplier. Does your solution handle that or start to get complicated.
Why do you explicitly need to find hotel data down the supplier route if you don't need that level of data other types of supplier? I would suggest that a supplier is a supplier, whether its a hotel or not for these purposes.
If you want to flag a supplier as a hotel, then simply put hotelid on the supplier table or else wait and hook in the supplier later via whatever mechanism you use to get detail on other suppliers.