Best normalised practice to map phone numbers with user or office - mysql

I am designing a DB in MySQL. I have a user table, office table and a phone number table as I intend to allow multiple phone numbers to a user or for an office. so I know I need to add foreign keys in phone number table to office table and to user table rather than the other way round. But how do I do it without a null record?
What is the best-normalized way to make this with neither officeId not userId in the phone number record null?
MY Phone number table
CREATE TABLE `phonenumber` (
`Id` varchar(36) NOT NULL,
`Title` varchar(100) DEFAULT NULL,
`UserId` varchar(36) DEFAULT NULL,
`SchoolId` int(11) DEFAULT NULL,
`CreatedOn` datetime NOT NULL,
`ModifiedOn` datetime NOT NULL,
`CreatedBy` varchar(36) NOT NULL,
`ModifiedBy` varchar(36) NOT NULL,
`Number` varchar(20) NOT NULL,
PRIMARY KEY (`Id`),
KEY `FK_Phone_User` (`UserId`),
KEY `FK_Phone_School` (`SchoolId`),
CONSTRAINT `FK_Phone_School` FOREIGN KEY (`SchoolId`) REFERENCES `school` (`Id`),
CONSTRAINT `FK_Phone_User` FOREIGN KEY (`UserId`) REFERENCES `user` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
My User Table
CREATE TABLE `user` (
`Id` varchar(36) NOT NULL,
`UserName` varchar(20) NOT NULL,
`DisplayName` varchar(100) DEFAULT NULL,
`OfficialName` varchar(100) DEFAULT NULL,
`PasswordHash` varchar(50) DEFAULT NULL,
`CreatedOn` datetime DEFAULT NULL,
`CreatedBy` varchar(36) DEFAULT NULL,
`ModifiedOn` datetime DEFAULT NULL,
`ModifiedBy` varchar(36) DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `UserName` (`UserName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
My School table
CREATE TABLE `school` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(100) NOT NULL,
`AddressId` varchar(36) DEFAULT NULL,
`CreatedOn` datetime NOT NULL,
`ModifiedOn` datetime NOT NULL,
`CreatedBy` varchar(36) NOT NULL,
`ModifiedBy` varchar(36) NOT NULL,
PRIMARY KEY (`Id`),
KEY `FK_School_Address` (`AddressId`),
CONSTRAINT `FK_School_Address` FOREIGN KEY (`AddressId`) REFERENCES `address` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

You simply have to allow for NULL fields during the creation of the Phone_numbers table. What you were warned against is having a whole record with NULLs. You are correctly handling the field that but not saying anything or saying NULL. Here's an example:
CREATE TABLE Phone_numbers(
phone_number VARCHAR(15) NOT NULL,
user_id INT UNSIGNED,
office_id INT UNSIGNED,
PRIMARY KEY (phone_number),
CONSTRAINT RefUsers1 FOREIGN KEY (user_id)
REFERENCES Users(user_id),
CONSTRAINT RefOffices2 FOREIGN KEY (office_id)
REFERENCES Offices(office_id)
)ENGINE=INNODB
;
For this simple model

Related

Alter table foreign key constraint fails

When I try to do this:
ALTER TABLE credit_card ADD CONSTRAINT fk_company FOREIGN KEY (company_id) REFERENCES company (id);
I got the error a foreign key constraint fails, but I don't understand why. The company_id column has same type of company.id column as you can see:
Company table
CREATE TABLE `company` (
`id` bigint NOT NULL AUTO_INCREMENT,
`code` varchar(10) NOT NULL,
`description` varchar(50) NOT NULL,
`currency_id` bigint NOT NULL,
`language_id` bigint DEFAULT NULL,
`address_id` bigint DEFAULT NULL,
`creation_time` datetime NOT NULL,
`modification_time` datetime DEFAULT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT '0',
`cost_center_modifiable` tinyint(1) DEFAULT NULL,
`use_colleague_cost_center` tinyint(1) DEFAULT NULL,
`fixed_guest_company` varchar(50) DEFAULT NULL,
`info_number` int DEFAULT NULL,
`use_kilometric_rate` tinyint(1) DEFAULT NULL,
`use_multiple_km_rate` tinyint(1) DEFAULT NULL,
`email_required` tinyint(1) DEFAULT NULL,
`logo` varchar(255) DEFAULT NULL,
`holding_id` bigint NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`),
KEY `fk_company_address1` (`address_id`),
KEY `fk_company_currency1` (`currency_id`),
KEY `company_language_FK` (`language_id`),
KEY `company_holding_FK` (`holding_id`),
CONSTRAINT `company_currency_FK` FOREIGN KEY (`currency_id`) REFERENCES `currency` (`id`),
CONSTRAINT `company_holding_FK` FOREIGN KEY (`holding_id`) REFERENCES `holding` (`id`),
CONSTRAINT `company_language_FK` FOREIGN KEY (`language_id`) REFERENCES `language` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=142 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Credit_card table
CREATE TABLE `credit_card` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`pan` varchar(16) NOT NULL,
`account` varchar(50) DEFAULT NULL,
`begin_date` date NOT NULL,
`end_date` date NOT NULL,
`disabled` tinyint(1) NOT NULL DEFAULT '0',
`creation_time` datetime NOT NULL,
`modification_time` datetime DEFAULT NULL,
`company_id` bigint NOT NULL,
PRIMARY KEY (`id`),
KEY `username` (`username`),
KEY `pan` (`pan`),
CONSTRAINT `fk_credit_card_user_ext` FOREIGN KEY (`username`) REFERENCES `users_extension` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=utf8mb3
Dont make auto increment columns as foreign keys or unless not sure, dont reference these to autoincrement columns as it may end up making the table with foreign key issue a constraint violation if redundant entries are expected to be made in either of the tables.
Might be the case the related data is already ingested and then the table is altered

Trouble getting my primary and foreign key to work

I keep getting errors when I try to run the relational part of the database to pull the 3 columns in the relation table from the customer table and bill table.
DROP DATABASE IF EXISTS CreateDB2;
CREATE DATABASE CreateDB2;
USE CreateDB2;
CREATE TABLE `tbl_employee` (
`tbl_EmployeeName` varchar(20) NOT NULL,
`tbl_Department` varchar(15) NOT NULL,
`employee_id` int(11) NOT NULL AUTO_INCREMENT,
`department_location` varchar(20) NOT NULL,
`department_name` varchar(15) NOT NULL,
`supervisor` varchar(15) NOT NULL,
PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `customer` (
`c_ID` varchar(15) NOT NULL,
`c_address` varchar(50) NOT NULL,
`c_Time` time NOT NULL,
`c_order` int(100) NOT NULL,
PRIMARY KEY (`c_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `bill` (
`b_items` double DEFAULT NULL,
`b_price` double DEFAULT NULL,
`b_discount` double DEFAULT NULL,
`b_deliveryFee` double DEFAULT NULL,
`b_tax` double DEFAULT NULL,
`b_tip` double DEFAULT NULL,
`b_total` double NOT NULL,
`quantity` int(11) NOT NULL,
PRIMARY KEY (`b_total`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `food` (
`code` int(11) NOT NULL AUTO_INCREMENT,
`f_catagory` varchar(20) NOT NULL,
`f_item` varchar(10) NOT NULL,
`f_info` varchar(50) NOT NULL,
`f_price` int(11) NOT NULL,
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `restaurantinfo` (
`name` varchar(20) NOT NULL,
`address` varchar(50) DEFAULT NULL,
`phone` int(13) DEFAULT NULL,
`email` varchar(20) DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `relationaltable` (
`c_ID` varchar(15) NOT NULL,
`c_order` int(100) NOT NULL,
`b_total` double NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `customer` ADD CONSTRAINT `c_ID` FOREIGN KEY (`c_ID`) REFERENCES `relationaltable`(`c_ID`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `order` ADD CONSTRAINT `c_order` FOREIGN KEY (`c_order`) REFERENCES `relationaltable`(`c_order`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `bill` ADD CONSTRAINT `b_total` FOREIGN KEY (`b_total`) REFERENCES `relationaltable`(`b_total`) ON DELETE RESTRICT ON UPDATE RESTRICT;
On the last part here, it is not working. It gives error code 1005
The alter table at the bottom is the probably the issue. I am just not sure how to fix it. Any help is appreciated. Thanks.
The foreign key is incorrectly formed.
You connect customer.c_ID should be equal to relationaltable.c_order
customer.c_ID is varchar(15) NOT NULL
relationaltable.c_order is int(100) NOT NULL
The data type and also the length has to be matching

Foreign key referring to primary key in the same table Mysql

# Sql to create userdetails table:
CREATE TABLE `userdetails` (
`user_details_id` int(3) unsigned NOT NULL AUTO_INCREMENT,
`user_group_id` int(1) unsigned NOT NULL,
`name` varchar(50) NOT NULL,
`email_id` varchar(50),
`password` varchar(50) NOT NULL,
`mobile_no` varchar(10) NOT NULL,
`company_id` int(3) unsigned,
`vehicle_id` varchar(10),
`date_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`date_updated` datetime NOT NULL,
`created_by` int(3) unsigned NOT NULL,
`status` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`user_details_id`),
UNIQUE KEY `email_id` (`email_id`),
FOREIGN KEY (`user_group_id`) REFERENCES `usergroups` (`user_group_id`),
FOREIGN KEY (`company_id`) REFERENCES `companies` (`company_id`),
FOREIGN KEY (`created_by`) REFERENCES `userdetails` (`user_details_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Focusing on the 'user_details_id' and 'created_by' columns, the conflict arises when created_by is not referring to an existing user_details_id.
Meaning, if I am creating my own profile with the required details, my user_details_id has not been generated yet and hence I do not know what value to input into the created_by field (which is ideally supposed to contain my user_details_id).
I would appreciate if anyone can guide me in the right direction on how to approach such a conflict, and if there is a way to determine what the value of the user_details_id field could be before it's even generated.
Thanks.
You can't handle it by temporarily disabling foreign key checks by setting server variable foreign_key_checks
SET FOREIGN_KEY_CHECKS=0;
INSERT INTO cities userdetails(....);
SET FOREIGN_KEY_CHECKS = 1;
# Sql to create userdetails table:
CREATE TABLE `userdetails` (
`user_details_id` int(3) unsigned NOT NULL AUTO_INCREMENT,
`user_group_id` int(1) unsigned NOT NULL,
`name` varchar(50) NOT NULL,
`email_id` varchar(50),
`password` varchar(50) NOT NULL,
`mobile_no` varchar(10) NOT NULL,
`company_id` int(3) unsigned,
`vehicle_id` varchar(10),
`date_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`date_updated` datetime NOT NULL,
`created_by` int(3) unsigned,
`status` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`user_details_id`),
UNIQUE KEY `email_id` (`email_id`),
FOREIGN KEY (`user_group_id`) REFERENCES `usergroups` (`user_group_id`),
FOREIGN KEY (`company_id`) REFERENCES `companies` (`company_id`),
FOREIGN KEY (`created_by`) REFERENCES `userdetails` (`user_details_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Allowing created_by to accept NULL values seems to be a quick fix to this problem as that can imply user is self-created.

MySQL "Foreign key constraint is incorrectly formed"

I have the follwing SQL commands:
CREATE TABLE IF NOT EXISTS `users`
(
`id` INTEGER NOT NULL auto_increment,
`username` VARCHAR(255) NOT NULL UNIQUE,
`password` VARCHAR(255) NOT NULL,
`root` TINYINT(1) DEFAULT 0,
`createdat` DATETIME NOT NULL,
`updatedat` DATETIME NOT NULL,
UNIQUE `username_unique` (`username`),
PRIMARY KEY (`id`)
)
engine=innodb;
CREATE TABLE IF NOT EXISTS `domains`
(
`id` INTEGER NOT NULL auto_increment,
`domain` VARCHAR(255) NOT NULL UNIQUE,
`createdat` DATETIME NOT NULL,
`updatedat` DATETIME NOT NULL,
`userid` INTEGER,
UNIQUE `domain_unique` (`domain`),
PRIMARY KEY (`id`),
FOREIGN KEY (`userid`) REFERENCES `users` (`id`) ON DELETE SET NULL ON
UPDATE CASCADE
)
engine=innodb;
CREATE TABLE IF NOT EXISTS `aliases`
(
`id` INTEGER NOT NULL auto_increment,
`source_username` VARCHAR(255) NOT NULL,
`source_domain` VARCHAR(255) NOT NULL,
`destination_username` VARCHAR(255) NOT NULL,
`destination_domain` VARCHAR(255) NOT NULL,
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`createdat` DATETIME NOT NULL,
`updatedat` DATETIME NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`source_domain`) REFERENCES `domains` (`domain`)
)
engine=innodb;
CREATE TABLE IF NOT EXISTS `accounts`
(
`id` INTEGER NOT NULL auto_increment,
`username` VARCHAR(255) NOT NULL,
`domain` VARCHAR(255) NOT NULL,
`password` VARCHAR(255) NOT NULL,
`quota` INTEGER NOT NULL DEFAULT 500,
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`sendonly` TINYINT(1) NOT NULL DEFAULT 0,
`createdat` DATETIME NOT NULL,
`updatedat` DATETIME NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`domain`) REFERENCES `domains` (`domain`)
)
engine=innodb;
if i try to run these i get the message:
"Foreign key constraint is incorrectly formed"
for the tables Alias and Accounts.
Its not possible to use primary keys in alias and accounts
Im using MariaDB 10.2
I hope somebody can tell me what is wrong with these statements.
You need to add a key/index to the domain field of the domains table, in order for it to be used as Foreign Key by another table.
If the table is already created and you want to add an index, use this.
CREATE INDEX domain ON domains(domain);
OR add the index while creating the table -
CREATE TABLE IF NOT EXISTS `domains`
(
`id` INTEGER NOT NULL auto_increment,
`domain` VARCHAR(255) NOT NULL UNIQUE,
`createdat` DATETIME NOT NULL,
`updatedat` DATETIME NOT NULL,
`userid` INTEGER,
UNIQUE `domain_unique` (`domain`),
PRIMARY KEY (`id`),
INDEX domain (domain),
FOREIGN KEY (`userid`) REFERENCES `users` (`id`) ON DELETE SET NULL ON
UPDATE CASCADE
)
engine=innodb;
For further reading (official documentation) regarding Foreign Key Contraint Errors on MariaDB this URL
You define an integer primary key. Use it:
CREATE TABLE IF NOT EXISTS `aliases`
(
`id` INTEGER NOT NULL auto_increment,
`source_username` VARCHAR(255) NOT NULL,
`source_domain_id` INTEGER NOT NULL,
`destination_username` VARCHAR(255) NOT NULL,
`destination_domain` VARCHAR(255) NOT NULL,
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`createdat` DATETIME NOT NULL,
`updatedat` DATETIME NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`source_domain_id`) REFERENCES `domains` (`id`)
)
engine=innodb;

MySQL Foreign key error 1215, even though both colums are of the same type and are NOT NULL

Parent table team_entrant:
CREATE TABLE IF NOT EXISTS `team_entrant` (
`entrant_number` tinyint(4) NOT NULL,
`qualifying_position` tinyint(4) NOT NULL,
`qualifying_time` time(3) NOT NULL,
`grid_position` tinyint(4) DEFAULT NULL,
`best_race_time` datetime DEFAULT NULL,
`final_position` tinyint(4) DEFAULT NULL,
`dnf_reason` varchar(45) DEFAULT NULL,
`team_id` int(11) NOT NULL,
`competition_year` date NOT NULL,
PRIMARY KEY (`entrant_number`),
KEY `fk_team_entrant_team1_idx` (`team_id`),
CONSTRAINT `fk_team_entrant_team1` FOREIGN KEY (`team_id`) REFERENCES `team` (`team_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Child table/Associative table entrant_drivers:
CREATE TABLE IF NOT EXISTS `entrant_drivers` (
`entrant_number` tinyint(4) NOT NULL,
`competition_year` date NOT NULL,
`driver_id` int(11) NOT NULL,
PRIMARY KEY (`entrant_number`,`competition_year`,`driver_id`),
CONSTRAINT `ed_entrant_fk` FOREIGN KEY (`entrant_number`) REFERENCES `team_entrant` (`entrant_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
At the time the team_entrant column competition_year did not exist.
HeidiSQL refuses to execute the following code:
ALTER table entrant_drivers ADD CONSTRAINT ed_comp_year_fk FOREIGN KEY (competition_year) REFERENCES team_entrant(competition_year);
SQL Error (1215): Cannot add foreign key constraint
Extraneous table, driver involved with the associative table:
-- Dumping structure for table 99_lemans_db1.driver
CREATE TABLE IF NOT EXISTS `driver` (
`driver_id` int(11) NOT NULL,
`driver_name` varchar(64) NOT NULL,
`driver_nationality` varchar(32) NOT NULL,
`driver_birth_day` date NOT NULL,
`driver_best_previous_finish_class` varchar(8) DEFAULT NULL,
`driver_best_previous_finish_position` tinyint(4) DEFAULT NULL,
`team_entrant_id` int(11) NOT NULL,
PRIMARY KEY (`driver_id`,`team_entrant_id`),
KEY `fk_driver_team_entrant1_idx` (`team_entrant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Any assistance would be appreciated.
The parent column must be designated as an index/primary key.
team_entrant is supposed to be made up of the composite primary keys (entrant number, competition year).