I've 3 profile tables:
-student
-teacher
-staff
All profile tables have different columns(few common columns).
These tables must be connected user table, each staff, teacher, student must be having account in user table:
user table
-id
-login
-password
-etc.
What is the best ways of connecting profiles tables to user table.
I've found one solution:
Storing User Profile as properties and values in tables
*i.e. Table to store possible options, table to store user_id, option_id and value*
-No redundant data stored, all data is relevant
-Most normalised method
-Slower to retrieve and update data
updated
Below, I've created db as #user1032531 said.
Create a super table called "people". Put all attributes in this table that are common to students, teachers, and staff.
Then create a table for students, teachers, and staff where each table's primary key is a 1-to-1 to the people table, and put unique attributes in these tables.
-- MySQL Script generated by MySQL Workbench
-- 07/30/14 05:51:12
-- Model: New Model Version: 1.0
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`people`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`people` (
`idpeople` INT UNSIGNED NOT NULL,
`name` VARCHAR(45) NULL,
`birthday` DATE NULL,
`sex` CHAR(1) NULL,
PRIMARY KEY (`idpeople`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`teachers`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`teachers` (
`people_idpeople` INT UNSIGNED NOT NULL,
`unique_column` VARCHAR(45) NULL,
PRIMARY KEY (`people_idpeople`),
CONSTRAINT `fk_teachers_people`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`students`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`students` (
`people_idpeople` INT UNSIGNED NOT NULL,
`unique_column` VARCHAR(45) NULL,
PRIMARY KEY (`people_idpeople`),
CONSTRAINT `fk_students_people1`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`staff`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`staff` (
`people_idpeople` INT UNSIGNED NOT NULL,
`unique_column` VARCHAR(45) NULL,
PRIMARY KEY (`people_idpeople`),
CONSTRAINT `fk_staff_people1`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
Related
I have an entity which has NOT NULL requirements based on the group it belongs to. For instance...
There are three types of churches: Buddhist, Muslim, and Christian.
All churches have some common required properties, however, each type of church has additional required properties.
All people have some common required properties, however, they have additional required properties based on the church type they belong to.
People must belong to one and only one church, however, may change their church to any other one of any religion provided that the above rules are met. The "type" of person they are is based on the church type they belong to.
How should entities who's required properties are based on the group which the entity belongs to be modeled? Or given my scenario, how should churches and people be modeled?
This is currently what I am doing, but it does not seem right. For instance, a person can be added before they become a Buddhist, Muslim, or Christian which breaks the rules. Also, a person or church can be more than one type which also breaks the rules.
-- MySQL Script generated by MySQL Workbench
-- 02/10/17 21:41:31
-- Model: New Model Version: 1.0
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`churches`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches` (
`idchurches` INT NOT NULL,
`name` VARCHAR(45) NOT NULL,
`address` VARCHAR(45) NOT NULL,
`members` INT NOT NULL,
PRIMARY KEY (`idchurches`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`churches_buddhist`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches_buddhist` (
`churches_idchurches` INT NOT NULL,
`number_of_buddas_in_church` VARCHAR(45) NOT NULL,
PRIMARY KEY (`churches_idchurches`),
CONSTRAINT `fk_churches_buddhist_churches`
FOREIGN KEY (`churches_idchurches`)
REFERENCES `mydb`.`churches` (`idchurches`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`churches_muslim`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches_muslim` (
`churches_idchurches` INT NOT NULL,
`savior` VARCHAR(45) NOT NULL,
PRIMARY KEY (`churches_idchurches`),
CONSTRAINT `fk_churches_muslim_churches1`
FOREIGN KEY (`churches_idchurches`)
REFERENCES `mydb`.`churches` (`idchurches`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`churches_christian`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches_christian` (
`churches_idchurches` INT NOT NULL,
`savior` VARCHAR(45) NOT NULL,
`number_of_crosses_in_church` INT NOT NULL,
PRIMARY KEY (`churches_idchurches`),
CONSTRAINT `fk_churches_christian_churches1`
FOREIGN KEY (`churches_idchurches`)
REFERENCES `mydb`.`churches` (`idchurches`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`people`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`people` (
`idpeople` INT NOT NULL,
`name` VARCHAR(45) NOT NULL,
`age` TINYINT NOT NULL,
`race` VARCHAR(45) NOT NULL,
`gender` VARCHAR(45) NOT NULL,
`favoriteVegitable` VARCHAR(45) NOT NULL,
PRIMARY KEY (`idpeople`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`buddhists`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`buddhists` (
`people_idpeople` INT NOT NULL,
`WidthOfBelly` BIGINT NOT NULL,
`LevelOfCconsciousness` INT NOT NULL,
`churches_buddhist_churches_idchurches` INT NOT NULL,
PRIMARY KEY (`people_idpeople`),
INDEX `fk_buddhists_churches_buddhist1_idx` (`churches_buddhist_churches_idchurches` ASC),
CONSTRAINT `fk_buddhists_people1`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_buddhists_churches_buddhist1`
FOREIGN KEY (`churches_buddhist_churches_idchurches`)
REFERENCES `mydb`.`churches_buddhist` (`churches_idchurches`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`muslims`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`muslims` (
`people_idpeople` INT NOT NULL,
`DaysOffTakenForRamadan` INT NOT NULL,
`favoriteMeat` VARCHAR(45) NOT NULL,
`churches_muslim_churches_idchurches` INT NOT NULL,
PRIMARY KEY (`people_idpeople`),
INDEX `fk_muslims_churches_muslim1_idx` (`churches_muslim_churches_idchurches` ASC),
CONSTRAINT `fk_muslims_people1`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_muslims_churches_muslim1`
FOREIGN KEY (`churches_muslim_churches_idchurches`)
REFERENCES `mydb`.`churches_muslim` (`churches_idchurches`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`christians`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`christians` (
`people_idpeople` INT NOT NULL,
`ChristmasPresentsReceived` INT NOT NULL,
`HolyMarysSaidPerDay` INT NOT NULL,
`favoriteMeat` VARCHAR(45) NOT NULL,
`FavoritePork` VARCHAR(45) NOT NULL,
`churches_christian_churches_idchurches` INT NOT NULL,
PRIMARY KEY (`people_idpeople`),
INDEX `fk_christians_churches_christian1_idx` (`churches_christian_churches_idchurches` ASC),
CONSTRAINT `fk_christians_people1`
FOREIGN KEY (`people_idpeople`)
REFERENCES `mydb`.`people` (`idpeople`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_christians_churches_christian1`
FOREIGN KEY (`churches_christian_churches_idchurches`)
REFERENCES `mydb`.`churches_christian` (`churches_idchurches`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
One idiom declaratively enforcing disjoint subtypes:
add type discriminator/tag column religion_type to parent and child tables
add superkey UNIQUE NOT NULL (id, religion_type)to parent tables
add FOREIGN (super) KEY (id, religion_type) to child tables, referencing parents
add constraint CHECK( religion_type = 'religion' ) or constant computed column with value religion to child tables
This still doesn't enforce that every parent is a child. From this answer:
One needs triggers to reasonably constrain SQL databases. One uses idioms to get what declarative constraints one can.
Just find the straightforward predicate for each relevant application relationship and give it a table. Here, that's parent and child tables. The constraints follow from the predicates and possible situtations. Declare them to prevent impossible updates. Whenever values in some columns must appear in other columns we declare a FK. You don't have to think about a special case for subtyped entity ids. Certain ids will end up in certain tables because certain things are true of them. It is ultimately their satisfying different predicates that makes things of different "types", rather than vice versa.
I have a supertype table called "vehicles". I also have three subtype tables called "airplanes", "automobiles", and "bicycles", and one and only one of these subtype tables must be linked to the vehicles supertype table (or in other words, must use the vehicles primary key ID as its primary key ID).
How should this be modeled to enforce this behavior?
EDIT Proposed schema recommended by Mike Brant.
-- MySQL Script generated by MySQL Workbench
-- 05/25/16 09:20:17
-- Model: New Model Version: 1.0
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`vehicle_types`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`vehicle_types` (
`type` CHAR(8) NOT NULL,
PRIMARY KEY (`type`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`vehicles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`vehicles` (
`idvehicles` INT NOT NULL AUTO_INCREMENT,
`type` CHAR(8) NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`idvehicles`),
INDEX `fk_vehicles_vehicle_types_idx` (`type` ASC),
CONSTRAINT `fk_vehicles_vehicle_types`
FOREIGN KEY (`type`)
REFERENCES `mydb`.`vehicle_types` (`type`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`airplanes`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`airplanes` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_airplanes` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_airplanes_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`automobiles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`automobiles` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_automobiles` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_automobiles_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`bicycles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`bicycles` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_bicycles` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_bicycles_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
I think inserting in vehicles and any of other sub types should be simultaneously. Therefore you can get the vehicle ID and put as new sub-type PK ID. If you have all information at the same time you can create a transcation and insert the vehicle record first then the sub-type record. Then commit your transscation otherwise rollback it. IF you want to know which record belongs to which sub-type table record you can add a column to your vehicle table that for example can have 3 different values such as 0,1,2 that shows which record belongs to which sub-table. Enum in java can be used in something like that for more clarification
Looking at your proposed schema, I see no reason whatsoever for you to have separate tables for each vehicle type, or even a separate table to contain the allowable vehicle types. Your vehicle-specific tables are all basically the same thing meaning you can easily collapse into a single table, and you can use ENUM field to enforce allowable vehicle types.
Why not just have a single vehicles table like the following?
CREATE TABLE IF NOT EXISTS `mydb`.`vehicles` (
`idvehicles` INT NOT NULL AUTO_INCREMENT,
`type` ENUM('airplane', 'automobile', 'bicycle') NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`idvehicles`),
INDEX `fk_vehicles_vehicle_types_idx` (`type` ASC))
ENGINE = InnoDB;
This approach totally eliminates 4 of your 5 tables, meaning you no longer have to consider using joins, foreign key constraints, etc. when performing CRUD operations against these records.
To enforce exclusive subtypes, copy the type indicator into each of the subtype tables and use composite foreign key constraints:
CREATE TABLE IF NOT EXISTS `mydb`.`airplanes` (
`vehicles_idvehicles` INT NOT NULL,
`type` CHAR(8) NOT NULL,
`data_for_airplanes` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_airplanes_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`, `type`)
REFERENCES `mydb`.`vehicles` (`idvehicles`, `type`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Next you need to restrict the value of type in each table. Unfortunately, MySQL doesn't support check constraints, so you would need to use triggers:
DELIMITER ;;
CREATE TRIGGER airplanes_insert_type_check
BEFORE INSERT ON airplanes
FOR EACH ROW
BEGIN
IF NEW.`type` != 'airplane' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Invalid type in airplanes';
END IF;
END;;
CREATE TRIGGER airplanes_update_type_check
BEFORE UPDATE ON airplanes
FOR EACH ROW
BEGIN
IF NEW.`type` != 'airplane' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Invalid type in airplanes';
END IF;
END;;
DELIMITER ;
Thus, the type indicator in the supertype table will match only one of the subtype tables' type indicators due to the trigger restrictions, and will be enforced via foreign key constraint, preventing overlapping subtypes.
I am trying to move my database model from mysql workbench to mysql server. I am using the reverse engineer sql create script but when importing it gives me an error. I have tried to google the problem but no luck to my situation.
-- -----------------------------------------------------
-- Table `MapLibrary`.`Books`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `MapLibrary`.`Books` ;
CREATE TABLE IF NOT EXISTS `MapLibrary`.`Books` (
`ISBN` VARCHAR(13) NOT NULL,
`date_of_publication` INT NULL,
`book_title` VARCHAR(45) NULL,
PRIMARY KEY (`ISBN`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `MapLibrary`.`Genre`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `MapLibrary`.`Genre` ;
CREATE TABLE IF NOT EXISTS `MapLibrary`.`Genre` (
`genre_code` INT NOT NULL,
`genre_name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`genre_code`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `MapLibrary`.`Books_By_Genre`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `MapLibrary`.`Books_By_Genre` ;
CREATE TABLE IF NOT EXISTS `MapLibrary`.`Books_By_Genre` (
`genre_code` INT NOT NULL,
`ISBN` VARCHAR(13) NOT NULL,
PRIMARY KEY (`genre_code`, `ISBN`),
INDEX `Books_idx` (`ISBN` ASC),
CONSTRAINT `Books`
FOREIGN KEY (`ISBN`)
REFERENCES `MapLibrary`.`Books` (`ISBN`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `Genre`
FOREIGN KEY (`genre_code`)
REFERENCES `MapLibrary`.`Genre` (`genre_code`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
ERROR:
ERROR 1022 (23000) at line 89: Can't write; duplicate key in table 'books_by_genre'
Operation failed with exitcode 1
The problem is that the ISBN is NOT a unique identifier on its own in the referenced tables.
I assume, that the Books table is your base table and the three referenced tables are M:N link tables. If this is true, then your foreign keys are pointing in the wrong direction. (Try to drag the connection in the other direction?)
Is there anything different between the two? All I see is the additional index which I don't believe fundamentally changes anything.
I would expect the first allows each t1_1 entity to be joined to multiple t1_2 entities, and the opposite as well.
For the second, I would expect each t2_1 entity to be joined to a maximum of one t2_2 entity.
But the resulting schema's generated by MySQL Workbench appear to be basically the same.
PS. Why I am doing this? Learning about super/sub tables, and went off on a tangent.
-- MySQL Script generated by MySQL Workbench
-- 08/05/15 08:12:21
-- Model: New Model Version: 1.0
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`t1_1`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t1_1` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t1_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t1_2` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t1_1_has_t1_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t1_1_has_t1_2` (
`t1_1_id` INT NOT NULL,
`t1_2_id` INT NOT NULL,
PRIMARY KEY (`t1_1_id`, `t1_2_id`),
INDEX `fk_t1_1_has_t1_2_t1_21_idx` (`t1_2_id` ASC),
INDEX `fk_t1_1_has_t1_2_t1_1_idx` (`t1_1_id` ASC),
CONSTRAINT `fk_t1_1_has_t1_2_t1_1`
FOREIGN KEY (`t1_1_id`)
REFERENCES `mydb`.`t1_1` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_t1_1_has_t1_2_t1_21`
FOREIGN KEY (`t1_2_id`)
REFERENCES `mydb`.`t1_2` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t2_1`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t2_1` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t2_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t2_2` (
`id` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`t2_1_hs_t2_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t2_1_hs_t2_2` (
`t2_1_id` INT NOT NULL,
`t2_2_id` INT NOT NULL,
PRIMARY KEY (`t2_1_id`, `t2_2_id`),
INDEX `fk_t2_1_hs_t2_2_t2_21_idx` (`t2_2_id` ASC),
CONSTRAINT `fk_t2_1_hs_t2_2_t2_11`
FOREIGN KEY (`t2_1_id`)
REFERENCES `mydb`.`t2_1` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_t2_1_hs_t2_2_t2_21`
FOREIGN KEY (`t2_2_id`)
REFERENCES `mydb`.`t2_2` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
IMO, talking in perspective of database design (not mysql workbench)
When using 1-n relation, we mean a not null foreign key inside cross table.
When using 1-1 relation, we mean a not null foreign key inside cross table that is the or part of a unique key of cross table.
Consider tables having these records:
T1_1(A1, B1, C1)
T2_1(A2, B2, C2)
In 1-n relation, we can have (A1, A2) multiple times in T1_has_T2 table
In 1-1 relation, we can not have (A1, A2) multiple times in T1_has_T2 table.
So Achieving 1-1 could be possible by putting foreign keys inside primary key or defining a unique key(index) on combination the foreign key columns.
I am having trouble figuring out how to design a database for an invoicing system. I want to have an invoice table and an tasks table. I want a record in the invoices table to be able to have a variable amount of tasks associated with it but also keep referential integrity so that a task cannot be added that does not exist on the tasks table.
So far I have come up with a task_id1, task_id2, etc... fields on the invoices table that are foreign keys to the task_id field in the tasks table but it feels limiting in the number of tasks that can be put on one invoice.
Alternatively the invoices table could have a comma separated list of task_id's that would allow for a variable amount of tasks per invoice but I cant figure out how to create the foreign key if the column types are not the same. (Plus this feels a little sloppy).
Im sure there is an easy answer I am not seeing.
So far I have come up with a task_id1, task_id2, etc... fields on the
invoices table that are foreign keys to the task_id field
Alternatively the invoices table could have a comma separated list of
task_id's that would allow for a variable amount of tasks per invoice
NOO!!!
Make a many-to-many tables between invoices and tasks, and make the constraint between this table and both the invoice and task table.
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`invoices`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`invoices` (
`id` INT NOT NULL AUTO_INCREMENT ,
`date` DATETIME NULL ,
`amount` DECIMAL(7,2) NULL ,
`whatever` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`tasks`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`tasks` (
`id` INT NOT NULL AUTO_INCREMENT ,
`whatever` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`invoices_has_tasks`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`invoices_has_tasks` (
`invoices_id` INT NOT NULL ,
`tasks_id` INT NOT NULL ,
PRIMARY KEY (`invoices_id`, `tasks_id`) ,
INDEX `fk_invoices_has_tasks_tasks1_idx` (`tasks_id` ASC) ,
INDEX `fk_invoices_has_tasks_invoices_idx` (`invoices_id` ASC) ,
CONSTRAINT `fk_invoices_has_tasks_invoices`
FOREIGN KEY (`invoices_id` )
REFERENCES `mydb`.`invoices` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_invoices_has_tasks_tasks1`
FOREIGN KEY (`tasks_id` )
REFERENCES `mydb`.`tasks` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
To create the invoice table
CREATE TABLE invoice (
invoice_id INT NOT NULL,
PRIMARY KEY (invoice_id)
) ENGINE=INNODB;
To create the tasks table use
CREATE TABLE tasks (
task_id INT,
invoice_id INT,
INDEX par_ind (invoice_id),
FOREIGN KEY (invoice_id)
REFERENCES invoice(invoice_id)
ON DELETE CASCADE
) ENGINE=INNODB;
That is all you need