DBMS design for multivalued attributes - mysql

I have to design a database where some information about usage of printer resource is to be recorded in a mysql database. What is the best way to design the database?
I do not want to create a table for each student as there would be around 6000 tables and which would keep growing each year if archives are to be maintained. Also it is difficult to create tables based on registration number of student. Is there a better way than storing multivalued attribute for details of printing. Please suggest some solutions. Also querying should be effective.

There is no need to create different tables for each student.
Just create a Table STUDENT which will contain the personal details of the student identified by their Registration number (lets say Regno-PrimaryKey).
And then another Table RESOURCE, which will have the following schema:
-RecNo Integer PK
-StudentID Foriegn key referenced to Regno in the Student Table
-Usage
or Data,Time(if you require)
This will work for and you need not have to create 6000 or more tables.

You have given very few information, but here is a shot:
create table student
(
registration_no varchar(50) not null primary key,
first_name varchar(50),
last_name varchar(50),
registration_year integer not null
);
create table printer
(
printer_id integer not null primary key,
printer_name varchar(50) not null,
ip_address varchar(50) not null,
queue_name varchar(50) not null
);
create unique index idx_printer_name on printer (printer_name);
create table printer_usage
(
usage_id integer not null primary key,
student_reg_no integer not null,
printer_id integer not null,
usage_date datetime not null,
pages integer not null
);
alter table printer_usage
add constraint fk_usage_student
foreign key (student_reg_no) references student (registration_no);
alter table printer_usage
add constraint fk_usage_printer
foreign key (printer_id) references printer (printer_id);
You will probably need to add more columns to the tables to store all the things you need. I was just guess stuff that you might want to store.

Related

Best approach to store 100+ columns in one table in MySQL

I am working on a data model where I need to store Employee's basic details and his rating of skillsets in MySQL database.
The number of skillsets for each employee is more than 100.
So the information I need to store is as following:
Employee ID, Name , Department , Contact info, Skillset1,Skillset2,Skillset3, ... , Skillset115
Is creating one table with approximately 120 columns is good approach?
If not, what is the best practice to deal with this kind of requirement.
No. You should have a separate table with one row per employee and per skill:
create table employeeSkills (
employeeSkillId int auto_increment primary key,
employeeId int not null,
skill varchar(255),
constraint fk_employeeSkills_employeeid foreign key (employeeId) references employees(employeeId)
);
In fact, you should really have two extra tables. The skills themselves should be stored in a separate table and the above should really be:
create table employeeSkills (
employeeSkillId int auto_increment primary key,
employeeId int not null,
skillId int,
constraint fk_employeeSkills_employeeid foreign key (employeeId) references employees(employeeId),
constraint fk_employeeSkills_skillid foreign key (skillId) references skills(skillId)
);
This type of table is called a "junction table", and is common in any properly constructed data model.
You need to create two tables that would handle the skills and the assigned skill for each employee.
This would give you a proper order in your database and also will extend your options in the future. It'll be better in search, add and assign skills to each employee. It's even more organized and would be able to be expanded easily such as adding skills category and sub-category.
The two tables schema should be something like this :
CREATE TABLE Skills (
Skill_ID INT NOT NULL AUTO_INCREMENT,
Skill_Description VARCHAR(250),
PRIMARY KEY (`Skill_ID`)
);
CREATE TABLE EmpolyeeSkills (
ES_ID INT NOT NULL AUTO_INCREMENT,
Skill_ID INT,
Employee_ID INT,
PRIMARY KEY (`ES_ID`),
CONSTRAINT FK_EMPLOYEEID FOREIGN KEY (Employee_ID) REFERENCES Employees(Employee_ID),
CONSTRAINT FK_SKILLID FOREIGN KEY (Skill_ID) REFERENCES Skills(Skill_ID)
);
The Skills table will assign an ID for each skill, and it'll be in a separate table. This will make you have a unique skills list, there won't be any redundancy. Then, you'll use EmployeeSkills to save the assigned skills on each Employee_ID. Which you can use it later on to join it with other records.
The FOREIGN KEY on Employee_ID and Skill_ID will help you in monitoring the skills between them.
The ES_ID primary key for EmpolyeeSkills will be an additional advantage that can be helpful in the future. For instance, if you want to know the latest skill that has been assigned, then your faster approach will be getting the last ES_ID as it's an AUTO_INCREMENT. This is just one advantage from tons of others.

Auto increment with composite primary key

I am not entirely sure what to search so I apologize if this is in fact a duplicate.
I have a table (or at least would like to) as follows:
ID
Company Name
SomeOtherInfo
The primary key would be ID and Company name (composite primary key). What I would like is so that the ID auto increments on each company.
Ex:
1-google
2-google
3-google
1-yahoo
4-google
2-yahoo
This way they are always unique, but each one increments for each company individually.
Is this possible from simple SQL create commands, would rather not have 2 tables and join them using a secondary ID.
Let me know, thanks.
If I follow the question. Create a single table with an identity on the ID column. Then create a unique index on the Company Name.
MySql Version
CREATE TABLE Company (
CompanyID int NOT NULL AUTO_INCREMENT,
CompanyName varchar(255) NOT NULL,
OtherData varchar(255),
PRIMARY KEY (CompanyID)
);
CREATE UNIQUE INDEX CompanyUniqueComposite
ON Company (CompanyID , CompanyName );

How do you create a constraint on parent tables that also constrains the child tables?

I am not sure how to phrase the question so I'll illustrate the tables and the explain what I want to achieve.
-- static table of the entity classes supported by the application
create table entity_type (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- static table of statuses supported by the application
create table entity_status (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- table of valid combinations
create table entity_type_entity_status_link (
entity_type_id integer not null,
entity_status_id integer not null,
unique key(entity_type_id, entity_status_id),
foreign key(entity_type_id) references entity_type(id),
foreign key(entity_status_id) references entity_status(id),
);
-- The tables where user types and statuses are defined
create table user_type (
id integer not null auto_increment,
name varchar(30) not null,
entity_type_id integer not null,
primary key(id),
foreign key(entity_type_id) references entity_type(id)
);
create table user_status (
id integer not null auto_increment,
name varchar(30) not null,
entity_status_id integer not null,
primary key(id),
foreign key(entity_status_id) references entity_status(id)
);
-- table of valid pairs
create table user_type_user_status_link (
user_type_id integer not null,
user_status_id integer not null,
unique key(user_type_id, user_status_id),
foreign key(user_type_id) references user_type(id),
foreign key(user_status_id) references user_status(id),
);
The basic premise behind these tables is that the system supports core types and statuses and the user is able to create their own user types and statues that derive from these.
The question I have is that I cannot see a way of creating any database constraints on the user_type_user_status_link table to ensure that the you cannot insert a file_type - file_status pair where the parent entity_type - entity_status is itself not valid. Or is this something that would have to be done with triggers.
The basic premise behind these tables is that the system supports core
types and statuses and the user is able to create their own user types
and statues that derive from these.
Although that sounds like a laudable goal on the surface, the effect is to delegate database design to your users. Database design, because the effect of your desire to set foreign key references to a subset of the rows in entity_type_entity_status_link means each of those subsets is a defacto, unnamed table.
This approach never ends well.
What you've developed is the "One True Lookup Table". Google that for a host of reasons why OTLT is an anti-pattern.
The best solution is to model real things in your tables. (Entity isn't a real thing. It's an abstraction of a real thing.) Something along the lines of either
create table file_status (
file_status varchar(30) primary key
);
or
create table file_status (
file_status_id integer primary key,
file_status varchar(30) not null unique
);
would work well for file statuses.
In the case of the second one, you can set a foreign key reference to either the id number (saves space, requires an additional join) or to the status text (takes more space, eliminates a join). Note that you need the unique constraint on the status text; your original design allows the user to enter the same text multiple times. (You could end up with 30 rows where entity_type.name is 'File'.
You should use triggers for that.
MySQL does not support constraints of the form that will prevent what you want.

help with database modeling

I have two tables: one for areas (like science, sport, education), and another for professions (like scientist, designer, golf player). There is a foreign relationship between the two tables, which works without any problems at the moment.
But now I need another table to put "number of workers", "average age", "years in the company" (this list is possibly different for each profession). What is the best way to do this? Create another table? What would be the parent? Basically, it is a third statement.
CREATE TABLE group (
id smallint(5) unsigned NOT NULL auto_increment,
area varchar(30),
PRIMARY KEY (id)
)
CREATE TABLE job (
ref int(10) unsigned NOT NULL auto_increment,
jobid smallint(5) unsigned NOT NULL,
job varchar(50),
PRIMARY KEY (ref)
)
ALTER TABLE job
ADD CONSTRAINT FK_job
FOREIGN KEY (jobid) REFERENCES group(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
From what I understand I would set up a third table as follows
Table: Employee
First_Name varchar(30)
Last Name varchar(30)
Age (int(3))
Employment Date (DATE)
Active (Yes/No)
JobFK (Points to emprego.PK)
With this kind of setup you can use joins on your tables to calculate how many workers are in the same profession. The average age of those employees, and how long they have been with the company. Given more information about your current tables I could even describe the sql queries for that information.

How should I structure my MySQL database?

First of all, sorry if this might be a stupid question. I'm very new to the world of MySQL, so...
Anyway, my question is this: I'm planning on having a database that deals with (for now) two types of users, let's say Admins and Users. My aim is to have ONE table containing all users, aptly named "users". Below is a rough outline of my MySQL command (which I haven't tested yet so errors are likely):
CREATE TABLE users {
user_id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_type int NOT NULL REFERENCES user_types(user_type_id),
ssn char(10) NOT NULL,
password varchar(40) NOT NULL,
first_name varchar(30) NOT NULL,
last_name varchar(30) NOT NULL,
address varchar(80) NOT NULL
} engine = InnoDB;
The "user_type" column above will refer to another table called "user_types", which lists the different user types for the website (I'm doing this for the sake of having the option to add more user types later):
CREATE TABLE user_types {
user_type_id int UNSIGNED NOT NULL PRIMARY KEY,
user_type_desc varchar(10) NOT NULL
} engine = InnoDB;
INSERT INTO user_types (user_type_id, user_type_desc) VALUES(1,'Admin'),(2,'User');
My aim is to link "Users" with "Admins"; one "User" (child) can have one "Admin" (parent), but one "Admin" (parent) can have several "Users" associated (children). The goal for me is to create a simple appointment calendar, and for that I need to connect users with their admins (one-to-one relationships in the sense that the appointment is between one user and one admin). Now the question is:
1) Is it possible to achieve this by having ONE table for all users? If so, how do I do it in a good way? Right now I was thinking of creating a table called "assignments":
CREATE TABLE assignments {
assign_id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
patient_id int NOT NULL REFERENCES users(user_id),
doctor_id int NOT NULL REFERENCES users(user_id)
} engine = InnoDB;
But the above code looks strange to me; can I do that kind of foreign key linking to the same table without any dangers? Below is also the SQL 'code' for the "appointments" table:
CREATE TABLE appointments {
appointment_id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
assign_id int FOREIGN KEY REFERENCES assignments(assign_id),
date_time datetime NOT NULL,
description varchar(200) NOT NULL
};
That is, every entry in the "appointments" table points to a certain assignment between an "Admin" and a "User".
2) How can I achieve the one-to-many relationship between "Admins" and "Users" in an easy way, or rather, a proper way?
Any help or suggestions would be greatly appreciated, and sorry if these questions are stupid!
Your proposed assignments table would work if you had a many-to-many relationship between Users and Admins. Since you've described the relationship as 1-to-many (one Admin may have many Users), I would simply add an admin_id column to your users table and make it a self-referencing foreign key back to the users table.
CREATE TABLE users {
user_id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_type int NOT NULL REFERENCES user_types(user_type_id),
ssn char(10) NOT NULL,
password varchar(40) NOT NULL,
first_name varchar(30) NOT NULL,
last_name varchar(30) NOT NULL,
address varchar(80) NOT NULL,
admin_id int REFERENCES users(user_id)
} engine = InnoDB;
In the users table add admin_userid that References users(user_id)
That way, each user points back to users table to the admin user they belong to.
Using this column a doctor can list all his patients and the assignements table can be used with appointments.
But will a certain user ALWAYS get a meeting with the same doctor/admin?
What about vacations?