what is a better way to create table? - mysql

I have mechanic that provide some services and there may be several services provided by a mechanic and how is better way to make tables in this case?
What i have now is :
Mechanic table :
create table mechanic(
id_master int not null unique,
rating int DEFAULT 10,
start_time TIME not null,
end_time TIME not null,
work_or_not BOOL DEFAULT 1,
Constraint FK_masterID_userID FOREIGN KEY(id_master) REFERENCES user(id_user),
Constraint Check_STARTTIME_ENDTIME check(start_time<end_time),
Constraint CHECK_FOR_STARTTIME CHECK(start_time>'-1:0:0' AND HOUR(start_time)<23),
Constraint CHECK_FOR_ENDTIME CHECK(end_time>'-1:0:0' AND HOUR(end_time)<23));
and i need to show what services mechanic provides and what table should i create ?
Maybe services table that ref to mechanic table via foreign key but i also need to store services values, so what should i do?

If some mechanic may provide different services and some service may be provided by different mechanics then this is many-to-many (M:N) link which needs in additional adjacency table.
CREATE TABLE mechanic ( id_mechanic INT AUTO_INCREMENT PRIMARY KEY
-- , ... {another columns}
);
CREATE TABLE service ( id_service INT AUTO_INCREMENT PRIMARY KEY
-- , ... {another columns}
);
CREATE TABLE adjacency ( id_mechanic INT NOT NULL,
id_service INT NOT NULL,
PRIMARY KEY (id_mechanic, id_service),
FOREIGN KEY (id_mechanic) REFERENCES mechanic (id_mechanic),
FOREIGN KEY (id_service) REFERENCES service (id_service)
);

Related

passing multiple foregain values in sql cell

I have two tables tb_schools(school_id,school_name), tb_programms(pid,p_name,school_id)
If suppose multiple schools offer the same program then how can I design the DB.
I mean can I pass the list of school_ids like[sc1,sc2,sc3] in school_id of tb_programms.
note: I can't add multiple rows for a single program.
If multiple schools offer the same program you need to design your schema differently. The canonical solution would be to have a table for schools, a table for programs, and a mapping table for the programs held at each school. E.g.:
CREATE TABLE tb_schools (
school_id INT AUTO_INCREMENT PRIMARY KEY,
school_name VARCHAR(30) NOT NULL
);
CREATE TABLE tb_programs (
pid INT AUTO_INCREMENT PRIMARY KEY,
p_name VARCHAR(30) NOT NULL
);
CREATE TABLE tb_school_programs
sid INT NOT NULL,
pid INT NOT NULL,
PRIMARY KEY (sid, pid),
FOREIGN KEY (sid) REFERENCES school(school_id),
FOREIGN KEY (pid) REFERENCES programs(pid)
);

issue with database modelling of many-tom-many [duplicate]

This question already has answers here:
How to implement one-to-one, one-to-many and many-to-many relationships while designing tables?
(4 answers)
Closed 5 years ago.
I want two model 2 simple tables: Account & Manager.
Account can have multiple managers and Manager can have multiple accounts to manage. so we have many-to-many relation between them.
This is how I created them in the db:
CREATE TABLE Account (
accountId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
PRIMARY KEY (accountId)
);
CREATE TABLE Manager (
managerId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
accountId int NOT NULL,
PRIMARY KEY (managerId),
FOREIGN KEY (accountId) REFERENCES Account (accountId)
);
the problem which is probably obvious to you is that I will have duplicated names and different id's for the same manager, like here:
How would you recommend an sql newbie to do it? :)
I think the way I model it is a one-to-many...
Create a Mapping table ( Egs Account_Manager) to Map Account and Manager and AccountID and ManagerID should be foreign Key.
Regards
Abdul
I would eliminate the accountid/foreign key from manager and introduce a new table to cross reference the two tables. Something like this:
CREATE TABLE ManagerAccount(
id int not null auto_increment,
managerId int not null,
accountId int not null,
primary key(id),
foreign key(managerid) references Manager (ManagerID),
foreign key(accountId) references Account (AccountID)
)
Maybe throw a unique index over the two foreign keys.
Implement a many-to-many relationship with a third table, with foreign keys to the two related tables.
As an example:
person
id
person_name
and
club
id
club_name
A club can have zero, one or more members; a person can be a member of zero, one or more clubs. It's a many-to-many relationship.
The simplest form of the relationship table:
membership
club_id PK, FK ref club.id
person_id PK, FK ref person.id
could be defined ...
CREATE TABLE membership
( club_id INT NOT NULL COMMENT 'PK, FK ref club.id'
, person_id INT NOT NULL COMMENT 'PK, FK ref person.id'
, PRIMARY KEY (club_id, person_id)
, KEY membership_IX1 (person_id)
, CONSTRAINT FK_membership_club FOREIGN KEY (club_id) REFERENCES club (id)
, CONSTRAINT FK_membership_person FOREIGN KEY (person_id) REFERENCES person (id)
)
We note that this relationship itself might have attributes, such as date joined and date resigned. There might also be status (provisional, active, probationary), and we might want to track offices or role within the club.
The relationship might turn out to be more than just a junction or link table. It may actually be an entity in our system. And we probably want to handle it like an entity, adding a separate id column, and also consider removing the requirement that (club_id,person_id) be unique.
Usually, the best way of going about modeling a many-to-many relationship is by creating a separate table to hold it. Using your example:
CREATE TABLE Account (
accountId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
PRIMARY KEY (accountId)
);
CREATE TABLE Manager (
managerId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
PRIMARY KEY (managerId),
);
CREATE TABLE Account_Manager (
id int NOT NULL AUTO_INCREMENT,
accountId int NOT NULL,
managerId int NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (accountId) REFERENCES Account(accountId)
FOREIGN KEY (managerId) REFERENCES Manager(managerId)
);
This way, any association between a Manager and an Account will be present in the Account_Manager table (e.g. (5,1) would represent patrick's association with the account with accountId = 5). However, to fully understand why this is the most common approach, I'd recommend you read about normalization.

Usage of MySQL foreign key referencing multiple columns

I just stumbled across possibility of MySQL foreign key to reference multiple columns. I would like to know what is main purpose of multi-column foreign keys like shown bellow
ALTER TABLE `device`
ADD CONSTRAINT `fk_device_user`
FOREIGN KEY (`user_created_id` , `user_updated_id` , `user_deleted_id`)
REFERENCES `user` (`id` , `id` , `id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
My questions are
Is it the same as creating three independent foreign keys?
Are there any pros / cons of using one or another?
What is the exact use-case for this? (main question)
Is it the same as creating three independent foreign keys?
No. Consider the following.
First off, it is not useful to think of it as (id,id,id), but rather (id1,id2,id3) in reality. Because a tuple of (id,id,id) would have no value over just a single column index on id. As such you will see the schema below that depicts that.
create schema FKtest001;
use FKtest001;
create table user
( id int auto_increment primary key,
fullname varchar(100) not null,
id1 int not null,
id2 int not null,
id3 int not null,
index `idkUserTuple` (id1,id2,id3)
);
create table device
( id int auto_increment primary key,
something varchar(100) not null,
user_created_id int not null,
user_updated_id int not null,
user_deleted_id int not null,
foreign key `fk_device_user` (`user_created_id` , `user_updated_id` , `user_deleted_id`)
REFERENCES `user` (`id1` , `id2` , `id3`)
);
show create table device;
CREATE TABLE `device` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`something` varchar(100) NOT NULL,
`user_created_id` int(11) NOT NULL,
`user_updated_id` int(11) NOT NULL,
`user_deleted_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_device_user` (`user_created_id`,`user_updated_id`,`user_deleted_id`),
CONSTRAINT `device_ibfk_1` FOREIGN KEY (`user_created_id`, `user_updated_id`, `user_deleted_id`) REFERENCES `user` (`id1`, `id2`, `id3`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
show indexes from device; -- shows 2 indexes (a PK, and composite BTREE)
-- FOCUS heavily on the `Seq_in_index` column for the above
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
drop table device;
drop table user;
create table user
( id int auto_increment primary key,
fullname varchar(100) not null,
id1 int not null,
id2 int not null,
id3 int not null,
index `idkUser1` (id1),
index `idkUser2` (id2),
index `idkUser3` (id3)
);
create table device
( id int auto_increment primary key,
something varchar(100) not null,
user_created_id int not null,
user_updated_id int not null,
user_deleted_id int not null,
foreign key `fk_device_user1` (`user_created_id`)
REFERENCES `user` (`id1`),
foreign key `fk_device_user2` (`user_updated_id`)
REFERENCES `user` (`id2`),
foreign key `fk_device_user3` (`user_deleted_id`)
REFERENCES `user` (`id3`)
);
show create table device;
CREATE TABLE `device` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`something` varchar(100) NOT NULL,
`user_created_id` int(11) NOT NULL,
`user_updated_id` int(11) NOT NULL,
`user_deleted_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_device_user1` (`user_created_id`),
KEY `fk_device_user2` (`user_updated_id`),
KEY `fk_device_user3` (`user_deleted_id`),
CONSTRAINT `device_ibfk_1` FOREIGN KEY (`user_created_id`) REFERENCES `user` (`id1`),
CONSTRAINT `device_ibfk_2` FOREIGN KEY (`user_updated_id`) REFERENCES `user` (`id2`),
CONSTRAINT `device_ibfk_3` FOREIGN KEY (`user_deleted_id`) REFERENCES `user` (`id3`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
show indexes from device; -- shows 4 indexes (a PK, and 3 indiv FK indexes)
-- FOCUS heavily on the `Seq_in_index` column for the above
There are 2 sections there. The show indexes from device will show the difference of, in the top part, 2 indexes maintained. In the bottom part, 4 indexes maintained. If for some reason the index tuple in the top part is useful for the system, then that tuple approach is certainly the way to go.
The reason is the following. The tuple exists as a group. Think of it as an instance of a set that has meaning as a group. Compare that to the mere existence of the individual parts, and there is a difference. It is not that the users exist, it is that there is a user row that has that tuple as an existence.
Are there any pros / cons of using one or another?
The pros were described above in the last paragraph: existence as an actual grouping in the user table as a tuple.
They are apple and oranges and used for different purposes.
What is the exact use-case for this? (main question)
A use case would be something that requires the existence of the tuple as a group, as opposed to the existence of the individual items. It is used for what is called compositing. Compositing FK's in particular. See this answer of mine Here as one case.
In short, it is when you want to enforce special hard to think of solutions that require Referential Integrity (RI) at a composited level (groupings) of other entities. Many people think it can't be done so they first think TRIGGER enforcement or front-end Enforcement. Fortunately those use cases can be achieved via the FK Composites thus leaving RI at the db level where it should be (and never at the front-end).
Addendum
Request from OP for a better real life example than the link above.
Consider the following schema:
CREATE SCHEMA testRealLifeTuple;
USE testRealLifeTuple;
CREATE TABLE contacts
( id INT AUTO_INCREMENT PRIMARY KEY,
fullname VARCHAR(100) NOT NULL
-- etc
);
CREATE TABLE tupleHolder
( -- a tuple representing a necessary Three-some validation
-- and vetting to get financing
--
-- If you can't vett these 3, you can't have my supercomputer financed
--
id INT AUTO_INCREMENT PRIMARY KEY,
CEO INT NOT NULL, -- Chief Executive Officer
CFO INT NOT NULL, -- Chief Financial Officer
CIO INT NOT NULL, -- Chief Geek
creditWorthiness INT NOT NULL, -- 1 to 100. 100 is best
-- the unique index is necessary for the device FK to succeed
UNIQUE INDEX `idk_ContactTuple` (CEO,CFO,CIO), -- No duplicates ever. Good for re-use
FOREIGN KEY `fk_th_ceo` (`CEO`) REFERENCES `contacts` (`id`),
FOREIGN KEY `fk_th_cfo` (`CFO`) REFERENCES `contacts` (`id`),
FOREIGN KEY `fk_th_cio` (`CIO`) REFERENCES `contacts` (`id`)
);
CREATE TABLE device
( -- An Expensive Device, typically our Supercomputer that requires Financing.
-- This device is so wildly expense we want to limit data changes
--
-- Note that the GRANTS (privileges) on this table are restricted.
--
id INT AUTO_INCREMENT PRIMARY KEY,
something VARCHAR(100) NOT NULL,
CEO INT NOT NULL, -- Chief Executive Officer
CFO INT NOT NULL, -- Chief Financial Officer
CIO INT NOT NULL, -- Chief Geek
FOREIGN KEY `fk_device_2_tuple` (`CEO` , `CFO` , `CIO`)
REFERENCES `tupleHolder` (`CEO` , `CFO` , `CIO`)
--
-- Note that the GRANTS (privileges) on this table are restricted.
--
);
DROP SCHEMA testRealLifeTuple;
The highlights of this schema come down to the UNIQUE KEY in tupleHolder table, the FK in device, the GRANT restriction (grants not shown), and the fact that the device is shielded from tomfoolery edits in the tupleHolder because of, as mentioned:
GRANTS
That the FK must be honored, so the tupleHolder can't be messed with
If the tupleHolder was messed with (the 3 contacts ids), then the FK would be violated.
Said another way, it is NO WAY the same as the device having an FK based on a single column in device, call it [device.badIdea INT], that would FK back to tupleHolder.id.
Also, as mentioned earlier, this differs from merely having the contacts exist. Rather, it matters that the composition of contacts exists, it is a tuple. And in our case the tuple has been vetted, and has a credit worthiness rating, and the id's in that tuple can't be messed with, after a device is bought, unless sufficient GRANTS allow it. And even then, the FK is in place.
It may take 15 minutes for that to sink in, but there is a Huge difference.
I hope this helps.

One key as foreign key for multiple table

There are many similar question but this is bit different.
I have one table which has one foreign key that will reference to two tables.
I used below query for testing.
CREATE TABLE users
(
id int NOT NULL,
username varchar(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE admins
(
id int NOT NULL,
username varchar(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE info
(
id int NOT NULL,
fullname int NOT NULL,
user_id int,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (user_id) REFERENCES admins(id)
);
Above queries works fine.
but when I try to draw model in mysql workbench it create on new field in info table that I don't want. I want user_id should work and show relation as foreign key for users and admins table.
One more thing, am I trying to do that is not well standard? Also suggests a correct way to do it.
Table names used only for example purpose. There is no logic here. I am trying to find solution for one key as foreign key for multiple table and faced issue with mysql work bench.
Try this:
Save your DDL in a file.
Create new model in MySQL Workbench
File > Import > Reverse Engineer MySQL Create Script
Browse to file created in step 1. Ensure that 'Place imported objects on diagram' is selected.
Click 'Execute'
From a data modelling point of view you might be better off specifying a user as an admin by including an extra column on the users table. Hence:
CREATE TABLE users
(
id int NOT NULL,
username varchar(255) NOT NULL,
isAdmin boolean not null default false,
PRIMARY KEY (id)
);
CREATE TABLE info
(
id int NOT NULL,
fullname int NOT NULL,
user_id int,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id)
);

Can a table have two foreign keys?

I have the following tables (Primary key in bold. Foreign key in Italic)
Customer table
ID---Name---Balance---Account_Name---Account_Type
Account Category table
Account_Type----Balance
Customer Detail table
Account_Name---First_Name----Last_Name---Address
Can I have two foreign keys in the Customer table and how can I implement this in MySQL?
Updated
I am developing a web based accounting system for a final project.
Account Category
Account Type--------------Balance
Assets
Liabilities
Equity
Expenses
Income
Asset
Asset_ID-----Asset Name----Balance----Account Type
Receivable
Receivable_ID-----Receivable Name-------Address--------Tel-----Asset_ID----Account Type
Receivable Account
Transaction_ID----Description----Amount---
Balance----Receivable_ID----Asset_ID---Account Type
I drew the ER(Entity relationship) diagram using a software and when I specify the relationship it automatically added the multiple foreign keys as shown above. Is the design not sound enough?
create table Table1
(
id varchar(2),
name varchar(2),
PRIMARY KEY (id)
)
Create table Table1_Addr
(
addid varchar(2),
Address varchar(2),
PRIMARY KEY (addid)
)
Create table Table1_sal
(
salid varchar(2),`enter code here`
addid varchar(2),
id varchar(2),
PRIMARY KEY (salid),
index(addid),
index(id),
FOREIGN KEY (addid) REFERENCES Table1_Addr(addid),
FOREIGN KEY (id) REFERENCES Table1(id)
)
Yes, MySQL allows this. You can have multiple foreign keys on the same table.
Get more details here FOREIGN KEY Constraints
The foreign keys in your schema (on Account_Name and Account_Type) do not require any special treatment or syntax. Just declare two separate foreign keys on the Customer table. They certainly don't constitute a composite key in any meaningful sense of the word.
There are numerous other problems with this schema, but I'll just point out that it isn't generally a good idea to build a primary key out of multiple unique columns, or columns in which one is functionally dependent on another. It appears that at least one of these cases applies to the ID and Name columns in the Customer table. This allows you to create two rows with the same ID (different name), which I'm guessing you don't want to allow.
Yes, a table have one or many foreign keys and each foreign keys hava a different parent table.
CREATE TABLE User (
user_id INT NOT NULL AUTO_INCREMENT,
userName VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
userImage LONGBLOB NOT NULL,
Favorite VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id)
);
and
CREATE TABLE Event (
EventID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (EventID),
EventName VARCHAR(100) NOT NULL,
EventLocation VARCHAR(100) NOT NULL,
EventPriceRange VARCHAR(100) NOT NULL,
EventDate Date NOT NULL,
EventTime Time NOT NULL,
EventDescription VARCHAR(255) NOT NULL,
EventCategory VARCHAR(255) NOT NULL,
EventImage LONGBLOB NOT NULL,
index(EventID),
FOREIGN KEY (EventID) REFERENCES User(user_id)
);