I am building an e learning website. I have three types of users : novice, intermediate and expert. I have 3 tables: lecture,chapter and pages.For each of these table I have to differentiate them by adding for which type of user is that lecture,chapter and page.
Is this a good practice to add same column name category (which can be either novice, intermediate or expert) to all the 3 tables ?
If you want to add more characteristics later to your user categories, the best is to create a separate table for this (eg: user_categories) and refer to this table in all 3 content tables. It would look like this:
CREATE TABLE user_types (id int PRIMARY KEY, name VARCHAR(20));
CREATE TABLE lectures (id int PRIMARY KEY, user_type int REFERENCES user_types(id));
You can also refer to this post to decide how to proceed in your case:How far to take normalization in database design?
Related
Let’s assume there are some rows in a table cars, and each of these rows has an owner. If this owner were always a person (conveniently situated in a table persons), this would be your standard one-to-many relation.
However, what if the owner could not only be a person, but also a company (in a table companies)? How would this relationship be modeled and how would it be handled in PHP?
My first idea was to create a column person and a column company and check that one of them always stays NULL, while the other is filled – however, that seems somewhat inelegant and becomes impractical once there is a higher number of possible related tables.
My current assumption would be to not simply create the foreign key as an integer column person in the table, but to create a further table called tables, which gives IDs to the tables, and then split the foreign key into two integer columns: owner_table, containing the ID of the table (e.g. 0 for persons and 1 for companies), and owner_id, containing the owner ID.
Is this a viable and practical solution or is there some standard design pattern regarding such issues? Is there a name for this type of problem? And are there any PHP frameworks supporting such relations?
EDIT: Found a solution: Such structures are called polymorphic relations, and Laravel supports them.
There are multiple ways to do it.
You can go with two nullable foreign keys: one referencing company and the other user. Then you can have a check constraint which assure you one is null. With PostgreSQL:
CREATE TABLE car{
<your car fields>
company_id INT REFERENCES car,
person_id INT REFERENCES person,
CHECK(company_id IS NULL AND person_id IS NOT NULL
OR company_id IS NOT NULL AND person_id IS NULL)
};
Or you can use table inheritance (beware their limitations)
CREATE TABLE car_owner{
car_owner_id SERIAL
};
CREATE TABLE company{
<company fields>
} INHERITS(car_owner);
CREATE TABLE person{
<person fields>
} INHERITS(car_owner);
CREATE TABLE car{
<car fields>
car_owner_id INT REFERENCES car_owner
};
I need tips when it comes to designing tables in a database. I am designing an employee meal system that monitors and processes meal logs of employees (like an attendance) My problem is here, I have 2 tables: The employee_table and the log_table. The employee table contains basic employee information and it has a unique key (not a primary one) which is employee_number. And then, there's another table, log_time, which contains the swipe data of the employees. Now, the two tables contain and employee_number column. How do I make relation out of them? Can I bind them together so that when I call for the employee_number column on the log_time it will get the basic information of the employee on the other table as well? Sorry because I'm having a hard time when it comes to designing a database.
SQL syntax for a relation might look something like this:
CREATE TABLE employee_table(
FOREIGN KEY (employee_number) REFERENCES employees(number),
...other stuff...
)
With another table that looks like
CREATE TABLE employees(
number INT(10) NOT NULL
)
Here's a great site on SQL foreign keys:
http://www.sitepoint.com/mysql-foreign-keys-quicker-database-development/
I am making a page for a website where customers of the website that rented/bought printers from the company can fill in the amount of printed documents (of every printer they own) in the last period.
Now, I need to translate this to MySQL. The idea is when the customer logs in the webpage it loads an overview with the printers they own, all of them in seperate boxes.
Those boxes each get an input field for the number they are required to submit.
So to make this work I need to put in a Database that, for example, a customer owns 6 different types of printers.
MySQL
--Table for Customers--
create table TBL_Pers (
Clientnr int,
Name varchar,
Post char(6),
Cont char(1),
Contdr tinyint,
p_p_a smallmoney)
--Table for Printer--
create table TBL_Printer (
PNr int,
PBrand varchar,
PName varchar,
Serialnr varchar)
The problem I run with is I have no clue how to link those different printers to a person let alone if I have to deal with 200 customers and 15 different kinds of printers the company offers.
So as you could probably tell I'm pretty new with MySQL :)
You need an association table to relate the two.
This would look like:
create table TBL_Pers_Printer (
Per_Printer_Id int auto_increment primary key,
Clientnr int references TBL_Person(ClientNr),
Pnr int references TBL_Printer(Pnr)
);
You might want to include additional information in this table, such as the date the person got the printer.
What you are looking for is called "many-to-many relationship". You implement it by adding another table:
create table TBL_Pers_Printer (
LnkNr int,
ClientNr int,
PNr int,
foreign key (ClientNr) references TBL_Pers(ClientNr),
foreign key (PNr) references TBL_Printer(PrinterNr)
);
And then insert corresponding pairs of person-printer numbers into it. Here's one of a multitude of resources explaining the concept of many-to-many relationship in a relational database.
You should have a link table TBL_CustomerPrinter (Clientnr, PNr/ SerialNo) where PNr/SerialNo would be the printer, a foreign key and the clientNr would be the client.
the table will allow multiple clients like below
clientID PrinterID
1 1
1 6
1 7
2 8
i.e. define a set of rules for link table:
one client can have multiple printers
one printer can have multiple clients - here is the question - is this possible with your schema?
Basically you need a correspondence table between client and printer, and you have to define a set of rules for this.
Hope this helps
I have a person table and I want users to be able to create custom many to many relations of information with them. Educations, residences, employments, languages, and so on. These might require different number of columns. E.g.
Person_languages(person_fk,language_fk)
Person_Educations(person,institution,degree,field,start,end)
I thought of something like this. (Not correct sql)
create Tables(
table_id PRIMARY_KEY,
table_name_fk FOREIGN_KEY(Table_name),
person_fk FOREIGN_KEY(Person),
table_description TEXT
)
Table holding all custom table name and descriptions
create Table_columns(
column_id PRIMARY_KEY,
table_fk FOREIGN_KEY(Tables),
column_name_fk FOREIGN_KEY(Columns),
rank_column INT,
)
Table holding the columns in each custom table and the order they are to be displayed in.
create Table_rows(
row_id PRIMARY_KEY,
table_fk FOREIGN_KEY(Tables),
row_nr INT,
)
Table holding the rows of each custom table.
create Table_cells(
cell_id PRIMARY_KEY,
table_fk FOREIGN_KEY(Tables),
row_fk FOREIGN_KEY(Table_rows),
column_fk FOREIGN_KEY(Table_columns),
cell_content_type_fk FOREIGN_KEY(Content_types),
cell_object_id INT,
)
Table holding cell info.
If any custom table starts to be used with most persons and becomes large, the idea was to maybe then extract it into a separate hard-coded many-to-many table just for that table.
Is this a stupid idea? Is there a better way to do this?
I strongly advise against such a design - you are on the road to an extremely fragmented and hard to read design.
IIUC your base problem is, that you have a common set of (universal) properties for a person, that may be extended by other (non-universal) properties.
I'd tackle this by having the universal properties in the person table and create two more tables: property_types, which translates a property name into an INT primary key and person_properties which combines person PK, propety PK and value.
If you set the PK of this table to be (person,property) you get the best possible index locality for the person, which makes requesting all properties for a person a very fast query.
I have a website that allows users to be different types. Each of these types can do specific things. I am asking if I should set up 1 table for ALL my users and store the types in an enum, or should I make different tables for each type. Now, if the only thing different was the type it would be easy for me to choose only using one table. However, here's a scenario.
The 4 users are A, B, C, D.
User A has data for:
name
email
User B has data for:
name
email
phone
User C has data for:
name
email
phone
about
User D has data for:
name
email
phone
about
address
If I were to create a single table, should I just leave different fields null for the different users? Or should I create a whole separate table for each user?
Much better if you could create a single table for all of them. Though some fileds are nullable. And add an extra column (enum) for each type of users. If you keep your current design, you will have to use some joins and unions for the records. (which adds extra overhead on the server)
CREATE TABLE users
(
ID INT,
name VARCHAR(50),
email VARCHAR(50),
phone VARCHAR(50),
about VARCHAR(50),
address VARCHAR(50),
userType ENUM() -- put types of user here
)
Another suggested design is to create two tables, one for user and the other one is for the types. The main advantage here is whenever you have another type of user, you don't have to alter the table but by adding only extra record on the user type table which will then be referenced by the users table.
CREATE TABLE UserType
(
ID INT PRIMARY KEY,
name VARCHAR(50)
)
CREATE TABLE users
(
ID INT,
name VARCHAR(50),
email VARCHAR(50),
phone VARCHAR(50),
about VARCHAR(50),
address VARCHAR(50),
TypeID INT,
CONSTRAINT rf_fk FOREIGN KEY (TypeID) REFERENCES UserType(ID)
)
Basic database design principals suggest one table for the common elements and additional tables, JOINed back to the base table, for the attributes that are unique to each type of user.
Your example suggests one and only one additional field per user-type in a straightforward inheritance hierarchy. Is that really what the data looks like, or did you simply for the example? If that's a true representation of your requirements, I might be tempted (for expedience) to use a single table. But if the real requirements are more complex, I'd bite the bullet and do it "correctly".
Try creating four tables:
Table 1: Name, email
Table 2: Name, phone
Table 3: Name, about
Table 4: Name, address
Name is your primary key on all four tables. There are no nulls in the database. You're not storing an enumerated type but derive the type from table joins:
To find all User A select all records in table 1 not in table 2
To find all User B select all records in table 2 not in table 3
To find all User C select all records in table 3 not in table 4
To find all User D select all records in table 4
You should not create tables for different people because this will lead to a bloated database. It's best to create a single table with all the fields you need. If you don't use the field, pass in null values.
I would suggest that you use 1 single table with nullable fields. And a table of something like roles.