Insert query for Many to Many relationship - mysql

I am creating a many to many python web app for a class. I have a users table joined to trips table with a joiner table called user_trips:
USERS
`id` INT NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(256) NULL,
`username` VARCHAR(256) NULL,
`password` VARCHAR(256) NULL,
`email` VARCHAR(256) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
TRIPS
`id` INT NOT NULL AUTO_INCREMENT,
`destination` VARCHAR(256) NULL,
`start_date` DATETIME NULL,
`end_date` DATETIME NULL,
`plan` TEXT(256) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
JOINER TABLE
CREATE TABLE IF NOT EXISTS `travel_test`.`user_trips` (
`trips_id` INT NOT NULL,
`users_id` INT NOT NULL,
PRIMARY KEY (`trips_id`, `users_id`),
I feel comfortable with all other entity relationships, but cannot seem to get how to create an insert statement to insert a new trip for a given user in the users table.
Does anyone have any pointers?

Related

Create two tables customer_data and order_data in SQL in a single execution via PHP

CREATE TABLE IF NOT EXISTS customers_data (
id int(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
INVOICE_ID varchar(50) NOT NULL,
_NAME varchar(255) NOT NULL,
MOBILE bigint(12) NOT NULL,
GSTIN varchar(20) NOT NULL,
_ADDRESS varchar(255) NOT NULL,
EMAIL varchar(255) NOT NULL,
_STATE varchar(50) NOT NULL,
MODE varchar(10) NOT NULL,
_DATE date NOT NULL DEFAULT current_timestamp(),
total_qty int(11) NOT NULL,
total_amount decimal(40,2) NOT NULL,
total_sc_gst decimal(30,2) NOT NULL,
Round_Off float(2,2) NOT NULL,
grand_total decimal(50,0) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
customer_data created sucessfully.
But there is an error in order_data regarding foreign key. Remember I want to create these two table in a same time.
CREATE TABLE IF NOT EXISTS order_data (
id int(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
cus_id int(20) NOT NULL,
ITEM varchar(255) NOT NULL,
HSN varchar(50) NOT NULL,
QTY int(15) NOT NULL,
RATE decimal(40,2) NOT NULL,
S_C_GST decimal(30,2) NOT NULL,
TOTAL decimal(50,2) NOT NULL,
_DATE timestamp NOT NULL DEFAULT current_timestamp(),
FOREIGN KEY(cus_id) REFERENCES customers_data(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
I got this error.
#1005 - Can't create table test. (errno: 150 "Foreign
key constraint is incorrectly formed")
I think you are using MySQL. You have not used Constraint with Foreign Key. Try the below query.
CREATE TABLE IF NOT EXISTS order_data (
id int(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
cus_id int(20) NOT NULL,
ITEM varchar(255) NOT NULL,
HSN varchar(50) NOT NULL,
QTY int(15) NOT NULL,
RATE decimal(40,2) NOT NULL,
S_C_GST decimal(30,2) NOT NULL,
TOTAL decimal(50,2) NOT NULL,
_DATE timestamp NOT NULL DEFAULT current_timestamp(),
**CONSTRAINT <FK_NAME>** FOREIGN KEY(cus_id) REFERENCES customers_data(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Making the table "at the same time" is not the problem you need to solve, (it's not possible anyway).
You can't make a foreign key if the data type is different from the data type of the referenced column.
order_data.cus_id is an INT column.
customers_data.id is an INT UNSIGNED column.
Change either one or the other data type, so they are the same.

Creating a MySQL Table but get error

I get
errnno 150: InnoDB Documentation
Supports transactions, row-level locking, and foreign keys
Here is the SQL:
-- Table structure for table `Serving_Info`
--
CREATE TABLE IF NOT EXISTS `Serving_Info` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`Food_Value` varchar(40) NOT NULL,
`Food_name` varchar(40) NOT NULL,
`Served_On` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`Oncall` varchar(128) NOT NULL,
Foreign key(`Oncall`) REFERENCES `employees`(`name`),
Foreign key(`Food_name`) REFERENCES `Foods`(`Food_name`),
PRIMARY KEY (`Oncall`,`Food_name`, `Served_On`)
);
Any idea what is causing the error? I have tried making id part of the primary key but that isn't solving the problem either.
Here are the statements for the tables I am referencing:
CREATE TABLE IF NOT EXISTS `employees` (
`id_user` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`email` varchar(64) NOT NULL,
`phone_number` varchar(16) NOT NULL,
`username` varchar(16) NOT NULL,
`password` varchar(32) NOT NULL,
`confirmcode` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id_user`)
);
--
-- Table structure for table `Foods`
--
CREATE TABLE IF NOT EXISTS `Foods` (
`Food_name` varchar(40) NOT NULL,
`CostPerRefill` double NOT NULL,
PRIMARY KEY (`Food_name`)
);
I just tried the below but I get the same error:
--
-- Table structure for table `Serving_Info`
--
CREATE TABLE IF NOT EXISTS `Serving_Info` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`Food_Value` varchar(40) NOT NULL,
`Food_name` varchar(40) NOT NULL,
`Served_On` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`Oncall` varchar(128),
Foreign key(`Oncall`) REFERENCES `employees`(`name`),
Foreign key(`Food_name`) REFERENCES `Foods`(`Food_name`),
PRIMARY KEY (`id`),
UNIQUE (`Oncall`,`Food_name`, `Served_On`)
);
Your problem is that the reference is to employees.name rather than employees.id_user. Try this:
CREATE TABLE IF NOT EXISTS `Serving_Info` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`Food_Value` varchar(40) NOT NULL,
`Food_name` varchar(40) NOT NULL,
`Served_On` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`Oncall` int,
PRIMARY KEY (`id`),
Foreign key(`Oncall`) REFERENCES `employees`(`id_user`),
Foreign key(`Food_name`) REFERENCES `Foods`(`Food_name`),
UNIQUE (`Oncall`,`Food_name`, `Served_On`)
);
Otherwise, change the employees table so name has an index:
CREATE TABLE IF NOT EXISTS `employees` (
`id_user` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL ,
`email` varchar(64) NOT NULL,
`phone_number` varchar(16) NOT NULL,
`username` varchar(16) NOT NULL,
`password` varchar(32) NOT NULL,
`confirmcode` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id_user`),
KEY (name)
);
In practice, if you are going to use name this way, you should probably make that unique rather than just key.

Mapping Composite primary keys of one table with that of the other table in ManyToMany Relationship

I have a situation where I have an Entity named User and another Entity UserHasFriends and there is a many-to-many relationship between the two. For Instance, a user can be friends with many other users and vice versa. I have 2 Primary Keys in the User table, userId and another is uniqueNo, that is associated with the User. In the table UserHasFriends, I have composite primary key(userId, uniqueNo),which are also foreign keys to the User table, that indicates that the user is friends with other users. The table UserHasFriends also contains some other attributes.
The problem is: When i am trying to create this schema, it shows me an error: "Cannot add Foreign Key".
CREATE TABLE IF NOT EXISTS `mydb`.`User` (
`userId` INT NOT NULL,
`uniqueNo` VARCHAR(45) NOT NULL,
`username` VARCHAR(45) NOT NULL,
`password` VARCHAR(45) NOT NULL,
`email` VARCHAR(45) NOT NULL,
`firstName` VARCHAR(45) NOT NULL,
`lastName` VARCHAR(45) NOT NULL,
`phoneNo` VARCHAR(45) NULL,
`address` VARCHAR(45) NULL,
PRIMARY KEY (`userId`, `uniqueNo`))
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS `mydb`.`UserHasFriends` (
`userId` INT NOT NULL,
`uniqueNo` VARCHAR(45) NOT NULL,
`requestStatus` VARCHAR(45) NULL,
PRIMARY KEY (`userId`, `uniqueNo`))
ENGINE = InnoDB

Split non-relational table into multiple relational tables

I have the following table of 60000 rows, in a MySQL 5 database, which is derived from a CSV file:
CREATE TABLE `smts_import` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`AscCode` varchar(5) NOT NULL,
`AscName` varchar(50) NOT NULL,
`RgnCode` varchar(5) NOT NULL,
`RgnName` varchar(100) NOT NULL,
`SCode` varchar(30) NOT NULL,
`SName` varchar(100) NOT NULL,
`AM` int(11) NOT NULL,
`AF` int(11) NOT NULL,
`LG` decimal(10,4) NOT NULL,
`LT` decimal(10,4) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ars_codes` (`AscCode`,`RgnCode`,`SCode`),
KEY `s_code` (`SCode`)
);
and which contains much repeated data. SCodes are unique, and the relationship between the RgnCode and SCode fields is many-to-one, as is that between the AscCode and RgnCode fields.
I want to split up (normalize) the data into three separate tables in a relational manner, such that no data are repeated:
CREATE TABLE `ascs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a_code` varchar(6) NOT NULL,
`a_name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `a_code` (`a_code`)
);
CREATE TABLE `rgns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a_id` int(11) NOT NULL,
`r_code` varchar(6) NOT NULL,
`r_name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `a_id`+`r_code` (`a_id`, `r_code`),
KEY `r_code` (`r_code`)
);
CREATE TABLE `sms` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`r_id` int(11) NOT NULL,
`s_code` varchar(16) NOT NULL,
`s_name` varchar(100) NOT NULL,
`a_m` int(11) NOT NULL,
`a_f` int(11) NOT NULL,
`lg` decimal(10,4) NOT NULL,
`lt` decimal(10,4) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `r_id+s_code` (`r_id`,`s_code`),
KEY `s_code` (`s_code`)
);
where rgns.a_id is a foreign key on ascs.id, and sms.r_id is a foreign key on rgns.id.
I've created the three tables and successfully populated the first two, ascs and rgns, with unique data from the smts_import table. My problem comes when I try to populate the third table sms with just the SCode, SName, AM, AF, LG and LT fields from the smts_import table, PLUS the appropriate id from the rgns table. And here I just get lost, I've tried many variations on the following:
INSERT INTO sms (r_id, s_code, s_name, a_m, a_f, lg, lt)
SELECT DISTINCT sr.id, SCode, SName, AM, AF, LG, LT
FROM sms_import AS si, rgns AS sr, ascs AS sa
WHERE (sr.r_code = si.RgnCode)
AND (sr.a_id = sa.id)
AND (sa.a_code = si.AscCode)
ORDER BY SCode
but I just end up with too many records. How do I write this insert statement to get the appropriate fields from all records from the sms_import table, plus the correct values in the sms.r_id field from the rgns.id field?
Thanks for your help
"the relationship between the RgnCode and SCode fields is many-to-one"
So you also get many rgns.id per SCode.
If you select distinct rgns.id, SCode, etc. you will get each SCode more than once depending on how many RgnCode you have for it.
I would suggest adding a id column to the sms table and create a separate table sms2rgns which contains the one-to-many relations sms.id -> rgns.id

Data Structure causing impossible joins

Tables:
nodes
data_texts
data_profiles
data_locations
data_profiles
data_media
data_products
data_metas
categories
tags
categories_nodes
tags_nodes
This question is a generalized question and is on the back of another question
Explanation:
Each of the "data" tables has a node_id that refers back to the id of the nodes table (hasMany/belongsTo association).
A "Node" can be anything - a TV Show, a Movie, a Person, an Article...etc (all generated via a CMS, so the user can control what type of "Nodes" they want).
When pulling data, I want to be able to query against certain fields. For example if they do a search, I want to be able to pull nodes that have data_texts.title = '%george%' or order by the datetime field in data_locations.
The problem is, when I do a join on all seven data tables (or more), the query has to hit so many combined rows that it just times out (even with a nearly empty database.... total 200 rows across the entire database).
I realize I can determine IF I need a join depending on what I'm doing - but even with five or six joins (once the database gets to 10k+ records), it's going to be horribly slow, if it works at all. Per this question, the query I'm using just doing a join on these tables times out completely.
Each node can have multiple rows of each data type (for multi-language reasons among others).
I'm completely defeated - I'm at the point where I think I need to restructure the entire thing, but don't have the time for that. I've thought about combining all into one table, but aren't sure how....etc
nodes
CREATE TABLE `nodes` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`slug` VARCHAR(100) NOT NULL,
`node_type_id` CHAR(36) NOT NULL,
`site_id` CHAR(36) NOT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `nodeTypeId` (`node_type_id`),
INDEX `slug` (`slug`),
INDEX `nodeId` (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM;
data_texts:
CREATE TABLE `data_texts` (
`id` CHAR(36) NOT NULL,
`title` VARCHAR(250) NULL DEFAULT NULL,
`subtitle` VARCHAR(500) NULL DEFAULT NULL,
`content` LONGTEXT NULL,
`byline` VARCHAR(250) NULL DEFAULT NULL,
`language_id` CHAR(36) NULL DEFAULT NULL,
`foreign_key` CHAR(36) NULL DEFAULT NULL,
`model` VARCHAR(40) NULL DEFAULT NULL,
`node_id` CHAR(36) NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `nodeId` (`node_id`),
INDEX `languageId_nodeId` (`language_id`, `node_id`),
INDEX `foreignKey_model` (`foreign_key`, `model`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
data_profiles
CREATE TABLE `data_profiles` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(80) NULL DEFAULT NULL,
`email_personal` VARCHAR(100) NULL DEFAULT NULL,
`email_business` VARCHAR(100) NULL DEFAULT NULL,
`email_other` VARCHAR(100) NULL DEFAULT NULL,
`title` VARCHAR(100) NULL DEFAULT NULL,
`description` LONGTEXT NULL,
`prefix` VARCHAR(40) NULL DEFAULT NULL,
`phone_home` VARCHAR(40) NULL DEFAULT NULL,
`phone_business` VARCHAR(40) NULL DEFAULT NULL,
`phone_mobile` VARCHAR(40) NULL DEFAULT NULL,
`phone_other` VARCHAR(40) NULL DEFAULT NULL,
`foreign_key` CHAR(36) NULL DEFAULT NULL,
`model` VARCHAR(40) NULL DEFAULT NULL,
`node_id` CHAR(36) NULL DEFAULT NULL,
`language_id` CHAR(36) NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
`user_id` CHAR(36) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `nodeId` (`node_id`),
INDEX `languageId_nodeId` (`node_id`, `language_id`),
INDEX `foreignKey_model` (`foreign_key`, `model`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM;
categories
CREATE TABLE `categories` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`node_type_id` CHAR(36) NOT NULL,
`site_id` CHAR(36) NOT NULL,
`slug` VARCHAR(100) NOT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `nodeTypeId` (`node_type_id`),
INDEX `slug` (`slug`)
)
COMMENT='Used to categorize nodes'
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
categories_nodes
CREATE TABLE `categories_nodes` (
`id` CHAR(36) NOT NULL,
`category_id` CHAR(36) NOT NULL,
`node_id` CHAR(36) NOT NULL,
PRIMARY KEY (`id`),
INDEX `categoryId_nodeId` (`category_id`, `node_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
node_tags
CREATE TABLE `node_tags` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(40) NOT NULL,
`site_id` CHAR(36) NOT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `siteId` (`site_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
nodes_node_tags
CREATE TABLE `nodes_node_tags` (
`id` CHAR(36) NOT NULL,
`node_id` CHAR(36) NOT NULL,
`node_tag_id` CHAR(36) NOT NULL,
PRIMARY KEY (`id`),
INDEX `node_id_node_tag_id` (`node_id`, `node_tag_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
MySQL:
SELECT `Node`.`id`, `Node`.`name`, `Node`.`slug`, `Node`.`node_type_id`, `Node`.`site_id`, `Node`.`created`, `Node`.`modified`
FROM `mysite`.`nodes` AS `Node`
LEFT JOIN `mysite`.`data_date_times` AS `DataDateTime` ON (`DataDateTime`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_locations` AS `DataLocation` ON (`DataLocation`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_media` AS `DataMedia` ON (`DataMedia`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_metas` AS `DataMeta` ON (`DataMeta`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_profiles` AS `DataProfile` ON (`DataProfile`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_products` AS `DataProduct` ON (`DataProduct`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_texts` AS `DataText` ON (`DataText`.`node_id` = `Node`.`id`)
WHERE 1=1
GROUP BY `Node`.`id`
Firstly, try InnoDB, not MyISAM.
Secondly, remove the group by, see how well it runs then, and how many rows are involved. Shouldn't be that many, but it's interesting.
You don't need the 'nodeId' index on node (as you already have it as a primary key). Again, shouldn't make any difference.
The where clause is irrelevant. You can remove it with no effect one way or another.
Thirdly, well, something is seriously broken.
Have a quick look on how to start profiling (e.g. http://dev.mysql.com/doc/refman/5.0/en/show-profile.html) , and run a profile command to see where all the time is going. Post it here if it doesn't immediately show that something is broken.
I'm unfortunately not in a position where I can do any tests right now. I'll just throw out some ideas. I might be able to do some tests later.
Be suspicious of different collations.
Some of your ids are useless. For example, you should drop the column categories_nodes.id, and put a primary key constraint on {category_id, node_id} instead.
Be suspicious of any design that requires joining all the tables at run time. There are better ways.
Use innodb and foreign key constraints.