Setup: Contact database using 4 tables
Contacts
Cities
States
Zips
Structure:
CREATE TABLE `contacts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`first` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`prefix` varchar(50) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`suffix` varchar(50) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`address` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`address_1` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`city_id` int(100) DEFAULT NULL,
`state_id` int(20) DEFAULT NULL,
`alt_address_1` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_address_2` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_city` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_state` varchar(20) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_zip` varchar(15) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`publish_name` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`salutation` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`mail_label` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`solicitor` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`is_volunteer` tinyint(1) DEFAULT NULL,
`is_sponsor` tinyint(1) DEFAULT '0',
`is_company` tinyint(1) DEFAULT '0',
`is_foundation` tinyint(1) DEFAULT '0',
`status` varchar(15) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`created_on` datetime NOT NULL,
`created_by` varchar(30) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`modified_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified_by` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`agency_id` int(25) DEFAULT NULL,
`primary_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `primary_id` (`primary_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3008 DEFAULT CHARSET=utf8
CREATE TABLE `cities` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`city` varchar(50) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`stateid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `city` (`city`)
) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=utf8
CREATE TABLE `states` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`abbreviation` varchar(2) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`state` varchar(20) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `state` (`state`),
UNIQUE KEY `abbreviation` (`abbreviation`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=52 DEFAULT CHARSET=utf8
CREATE TABLE `zips` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`zip` varchar(10) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`cityid` int(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `zip` (`zip`)
) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=utf8
I have filled the contacts with 111 contacts, the states are simply all of the states, and cities have corresponding id keys that relate to the state id, zip codes have a key to match to a city.
The query is to generate a list of people to match up to the proper fields. Here is the query.
SELECT concat(contacts.last,' ', contacts.first) as name
, cities.city
, zips.zip
FROM contacts
JOIN cities
ON cities.id = contacts.city_id
JOIN states ON states.id = contacts.state_id
JOIN zips ON zips.cityid = cities.id
This query, return 338 rows, of a possible 11 contacts. There obvious duplicates. This happens when I join zip codes, which because they belong to more than 1 city, it gets matched for each city (I think thats what is happening). Anyone have an answer on how to properly join these tables?
Thank you.
Rich
I believe that you should re-think the surrogate key usage on a lot of these tables and use natural keys where possible. Taking the state table for an example, in most cases it will be acceptable to simply use the state short (ie. TX vs. Texas) for data and display purposes. This means that if you removed the incrementing ID on the states table and used a natural key for each state, you would reduce the necessecity of a join in 90% of cases.
Then use state.abbriviation as the FK in tables that need to store state values. Extending this to zipcodes and cities, you can FK the state abbr to the city table, and make a compound FK form the cities table to the contacts table giving you a key for both the city and the state at the same time.
Example schema (excluded zipcodes table and shortened contacts table):
CREATE TABLE IF NOT EXISTS `states` (
`state_id` CHAR(2) NOT NULL ,
`name` VARCHAR(45) NULL ,
PRIMARY KEY (`state_id`) ,
UNIQUE INDEX `state_name` (`name` ASC)
)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `cities` (
`state_id` CHAR(2) NOT NULL ,
`city_name` VARCHAR(255) NOT NULL ,
PRIMARY KEY (`state_id`, `city_name`) ,
INDEX `fk_city_state_id` (`state_id` ASC) ,
CONSTRAINT `fk_city_state_id`
FOREIGN KEY (`state_id` )
REFERENCES `states` (`state_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `contacts` (
`contacts_id` INT NOT NULL AUTO_INCREMENT ,
`state` CHAR(2) NULL ,
`city` VARCHAR(255) NULL ,
PRIMARY KEY (`contacts_id`) ,
INDEX `fk_contact_city` (`state` ASC, `city` ASC) ,
INDEX `fk_contact_state` (`state` ASC) ,
CONSTRAINT `fk_contact_city`
FOREIGN KEY (`state` , `city` )
REFERENCES `cities` (`state_id` , `city_name` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_contact_state`
FOREIGN KEY (`state` )
REFERENCES `states` (`state_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Data for table `states`
-- -----------------------------------------------------
SET AUTOCOMMIT=0;
INSERT INTO `states` (`state_id`, `name`) VALUES ('TX', 'Texas');
INSERT INTO `states` (`state_id`, `name`) VALUES ('CA', 'California');
INSERT INTO `states` (`state_id`, `name`) VALUES ('OR', 'Oregon');
COMMIT;
-- -----------------------------------------------------
-- Data for table `cities`
-- -----------------------------------------------------
SET AUTOCOMMIT=0;
INSERT INTO `cities` (`state_id`, `city_name`) VALUES ('CA', 'modesto');
INSERT INTO `cities` (`state_id`, `city_name`) VALUES ('OR', 'protland');
INSERT INTO `cities` (`state_id`, `city_name`) VALUES ('TX', 'Dallas');
COMMIT;
Now your query is simplified except in the extreme case where you'd need a full state nomenclature:
SELECT
concat(contacts.last,' ', contacts.first) as name,
city,
state,
zip
FROM contacts
WHERE {INSERTWHERE}
your tables a properly joined. i think the problem you have here is that you have normalized your data improperly and gone too far. just store the address as provided. don't try and split it in to table with numeric ID's.
for example, what possible benefit do you get by storing the state as a number in the contact table instead of just the state code? and the same question applies to city.
Related
For a back-end web project, we use PHP 7.4 and MySQL 8.X, here is the structure of a part of the DB
CREATE TABLE `availability ` (
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
`student_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`start` date DEFAULT NULL,
`end` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_2CBACE2FDDEAB1A3` (`student_id`),
CONSTRAINT `FK_2CBACE2FDDEAB1A3` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE `student` (
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`sex_id` int DEFAULT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`first_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`phone` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`picture` longtext COLLATE utf8mb4_unicode_ci,
`cv` longtext COLLATE utf8mb4_unicode_ci,
PRIMARY KEY (`id`),
KEY `IDX_717E22E3448F3B3C` (`sex_id`),
CONSTRAINT `FK_717E22E3448F3B3C` FOREIGN KEY (`sex_id`) REFERENCES `sex` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE `request` (
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`student_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`date` datetime NOT NULL,
`title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`content` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_2694D7A5DDEAB1A3` (`student_id`),
CONSTRAINT `FK_2694D7A5DDEAB1A3` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Here are the cardinalities:
a STUDENT can have several availabilities (no matter what the
category of the availability is) an AVAILABILITY can belong to one or
more STUDENTS
a student can have one or more APPLICATIONS
a REQUEST belongs to only one STUDENT
but when I try to retrieve all the REQUESTS according to a period, it retrieves the data twice:
SELECT DE.*, ET.picture AS picture_editor, CONCAT(ET.first_name, ' ', ET.name) AS name_editeur, DI.start, DI.end
FROM request DE
INNER JOIN student ET ON ET.id = DE.student_id
INNER JOIN availability DI ON DI.student_id = DE.student_id
WHERE DI.start< CAST('2022-12-31' AS DATETIME) AND DI.end> CAST('2022-09-11' AS DATETIME)
Can you help me as I want to retrieve the data according to the student's availability
i want to copy 1 row from this table:
tableold
-----------
oid (primary key, auto_incremment)
name
age
detail
to this table:
tablenew
------------
nid (primary key, auto_incremment)
fid (foreign key to another table)
name
age
detail
With this SQL-Command:
INSERT INTO tablenew (tablenew.name, tablenew.age, tablenew.detail)
SELECT tableold.name, tableold.age, tableold.detail
FROM tableold
WHERE tableold.oid = 123;
But i get the error:
ERROR 1364 (HY000): Field 'fid' doesn't have a default value
Is there any possibility to manually add the foreign key 'fid' to the SQL-Command?
*Edit, i have added the CREATE table statements:
CREATE TABLE `othertable` (
`fid` int NOT NULL AUTO_INCREMENT,
`value1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`value2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`value3` longtext CHARACTER SET utf8 COLLATE utf8_general_ci,
`value4` longtext CHARACTER SET utf8 COLLATE utf8_general_ci,
PRIMARY KEY (`fid`),
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8;
CREATE TABLE `tablenew` (
`nid` int NOT NULL AUTO_INCREMENT,
`fid` int NOT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`age` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`detail` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`sid`),
KEY `fid_fkey` (`fid`),
CONSTRAINT `fid_fkey` FOREIGN KEY (`fid`) REFERENCES `othertable` (`fid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
CREATE TABLE `tableold` (
`oid` int NOT NULL AUTO_INCREMENT,
`name` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`age` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`detail` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`oid`)
) ENGINE=InnoDB AUTO_INCREMENT=157 DEFAULT CHARSET=utf8;
I have solved it:
INSERT INTO tablenew (tablenew.fid, tablenew.name, tablenew.age, tablenew.detail)
SELECT 'value', tableold.name, tableold.age, tableold.detail
FROM tableold
WHERE tableold.oid = value;
I'm building a twitter-like app using node.js for fun and I have multiple tables :
users: to store users' data.
tweets: to store tweets.
likes: to store what users liked what tweet.
retweets: to store what users retweeted what tweet.
following: to store what user is following other users.
CREATE TABLE IF NOT EXISTS `following` (
`user_id` varchar(50) NOT NULL,
`followed_id` varchar(50) NOT NULL,
`date_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`,`followed_id`)
)
CREATE TABLE IF NOT EXISTS `likes` (
`user_id` varchar(50) NOT NULL,
`tweet_id` varchar(50) NOT NULL,
`date_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`,`tweet_id`)
)
CREATE TABLE IF NOT EXISTS `retweets` (
`user_id` varchar(50) NOT NULL,
`tweet_id` varchar(50) NOT NULL,
`date_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`,`tweet_id`)
)
CREATE TABLE IF NOT EXISTS `tweets` (
`tweet_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`reply_to_tweet_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`reply_to_user_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`truncated` tinyint(1) NOT NULL,
`author` varchar(30) NOT NULL,
`text` varchar(255) NOT NULL,
`media` varchar(255) NOT NULL,
`entities` json NOT NULL,
PRIMARY KEY (`tweet_id`)
)
CREATE TABLE IF NOT EXISTS `users` (
`user_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`email` varchar(30) NOT NULL,
`username` varchar(30) NOT NULL,
`password` varchar(255) NOT NULL,
`handelname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`account_url` varchar(255) NOT NULL,
`bio` varchar(255) NOT NULL,
`profile_pic` varchar(255) NOT NULL,
`cover_pic` varchar(255) NOT NULL,
`protected` tinyint(1) NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `username` (`username`)
)
and I want to create a new view for the users containing there information along with how many tweets
they did like, the number of users they follow, the number of users follow them and how many tweets they have created.
I want this information in one table but I tried many ways and none of them worked fine for me!
what is the proper solution for such a problem?
You may try below query -
SELECT `user_id`
,LI.LI_CNT no_of_tweets_liked
,FL.FL_CNT no_of_followers
,FL2.FL2_CNT no_of_followee
,RT.RT_CNT no_of_retweets
FROM `users` U
JOIN (SELECT `user_id`, COUNT(`tweet_id`) LI_CNT
FROM `likes`
GROUP BY `user_id`) LI ON U.`user_id` = LI.`user_id`
JOIN (SELECT `user_id`, COUNT(`followed_id`) FL_CNT
FROM `following`
GROUP BY `user_id`) FL ON U.`user_id` = FL.`user_id`
JOIN (SELECT `followed_id`, COUNT(`followed_id`) FL2_CNT
FROM `following`
GROUP BY `followed_id`) FL2 ON U.`user_id` = FL2.`followed_id`
JOIN (SELECT `user_id`, COUNT(`tweet_id`) RT_CNT
FROM `retweets`
GROUP BY `user_id`) RT ON U.`user_id` = RT.`user_id`;
I'm iterating over about 14,000 records which I get from csv file.
For each user I do this:
1) I create a user record in users table
2) I insert ~21 attributes for that user into users_attributes table
Initially each user takes ~2 seconds to be inserted, but after awhile insertion time grows to ~50 seconds... and so script takes forever....
Why is it so slow?
Example insert statement:
Executed once:
INSERT INTO users (uname, email, pass, passreminder, activated, approved_date, approved_by, user_regdate, lastlogin, theme, ublockon, ublock, tz, locale) VALUES ('someid_example.com', 'someid#example.com', 'test', 'User-generated', -32768, '2014-09-03 14:41:50', 2, '2014-09-03 14:41:50', '1970-01-01 00:00:00', '', 0, '', '', '');
Repeated 21 times:
INSERT INTO users_attributes (name, value, user_id) VALUES ('user_information_address', 'some address', 9862);
Schema:
CREATE TABLE `users` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`uname` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`pass` varchar(138) COLLATE utf8_unicode_ci NOT NULL,
`passreminder` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`activated` smallint(6) NOT NULL,
`approved_date` datetime NOT NULL,
`approved_by` int(11) NOT NULL,
`user_regdate` datetime NOT NULL,
`lastlogin` datetime NOT NULL,
`theme` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`ublockon` smallint(6) NOT NULL,
`ublock` longtext COLLATE utf8_unicode_ci NOT NULL,
`tz` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
`locale` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`uid`),user
KEY `uname` (`uname`),
KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `users_attributes` (
`user_id` INT(11) NOT NULL,
`name` VARCHAR(80) COLLATE utf8_unicode_ci NOT NULL,
`value` longtext COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`user_id`,`name`),
KEY `IDX_SOMENUM` (`user_id`),
CONSTRAINT `IDX_SOMENUM` FOREIGN KEY (`user_id`) REFERENCES `users` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
I am trying to insert values into my comments table and I am getting a error. Its saying that I can not add or update child row and I have no idea what that means.
My schema looks something like this:
--
-- Baza danych: `koxu1996_test`
--
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `user`
--
CREATE TABLE IF NOT EXISTS `user` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`username` varchar(32) COLLATE utf8_bin NOT NULL,
`password` varchar(64) COLLATE utf8_bin NOT NULL,
`password_real` char(32) COLLATE utf8_bin NOT NULL,
`email` varchar(32) COLLATE utf8_bin NOT NULL,
`code` char(8) COLLATE utf8_bin NOT NULL,
`activated` enum('0','1') COLLATE utf8_bin NOT NULL DEFAULT '0',
`activation_key` char(32) COLLATE utf8_bin NOT NULL,
`reset_key` varchar(32) COLLATE utf8_bin NOT NULL,
`name` varchar(32) COLLATE utf8_bin NOT NULL,
`street` varchar(32) COLLATE utf8_bin NOT NULL,
`house_number` varchar(32) COLLATE utf8_bin NOT NULL,
`apartment_number` varchar(32) COLLATE utf8_bin NOT NULL,
`city` varchar(32) COLLATE utf8_bin NOT NULL,
`zip_code` varchar(32) COLLATE utf8_bin NOT NULL,
`phone_number` varchar(16) COLLATE utf8_bin NOT NULL,
`country` int(8) NOT NULL,
`province` int(8) NOT NULL,
`pesel` varchar(32) COLLATE utf8_bin NOT NULL,
`register_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`authorised_time` datetime NOT NULL,
`edit_time` datetime NOT NULL,
`saldo` decimal(9,2) NOT NULL,
`referer_id` int(8) NOT NULL,
`level` int(8) NOT NULL,
PRIMARY KEY (`id`),
KEY `country` (`country`),
KEY `province` (`province`),
KEY `referer_id` (`referer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=83 ;
and the mysql statement I am trying to do looks something like this:
INSERT INTO `user` (`password`, `code`, `activation_key`, `reset_key`, `register_time`, `edit_time`, `saldo`, `referer_id`, `level`) VALUES (:yp0, :yp1, :yp2, :yp3, NOW(), NOW(), :yp4, :yp5, :yp6). Bound with :yp0='fa1269ea0d8c8723b5734305e48f7d46', :yp1='F154', :yp2='adc53c85bb2982e4b719470d3c247973', :yp3='', :yp4='0', :yp5=0, :yp6=1
the error I get looks like this:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(koxu1996_test.user, CONSTRAINT user_ibfk_1 FOREIGN KEY
(country) REFERENCES country_type (id) ON DELETE NO ACTION ON
UPDATE NO ACTION)
It just simply means that the value for column country on table comments you are inserting doesn't exist on table country_type or you are not inserting value for country on table user.
Bear in mind that the values of column country on table comments is dependent on the values of ID on table country_type.
You have foreign keys between this table and another table and that new row would violate that constraint.
You should be able to see the constraint if you run show create table user, it shows up as CONSTRAINT... and it shows what columns reference what tables/columns.
In this case country references country_type (id) and you are not specifying the value of country. You need to put a value that exists in country_type.
Just to throw in my own issue in case it can help someone else, I was copy/pasting entries in my migration files and messed up by putting quotes around an integer. Since the value I was trying to enter was considered a string going into an integer field that was referencing another integer, this error came up.
Another option could be thath your primary key in source table IS NOT unsigned, so I solved same insert with (notice id int(8) unsigned):
CREATE TABLE IF NOT EXISTS user ( id int(8) unsigned NOT NULL
AUTO_INCREMENT, username varchar(32) COLLATE utf8_bin NOT NULL,
password varchar(64) COLLATE utf8_bin NOT NULL, password_real
char(32) COLLATE utf8_bin NOT NULL, email varchar(32) COLLATE
utf8_bin NOT NULL, code char(8) COLLATE utf8_bin NOT NULL,
activated enum('0','1') COLLATE utf8_bin NOT NULL DEFAULT '0',
activation_key char(32) COLLATE utf8_bin NOT NULL, reset_key
varchar(32) COLLATE utf8_bin NOT NULL, name varchar(32) COLLATE
utf8_bin NOT NULL, street varchar(32) COLLATE utf8_bin NOT NULL,
house_number varchar(32) COLLATE utf8_bin NOT NULL,
apartment_number varchar(32) COLLATE utf8_bin NOT NULL, city
varchar(32) COLLATE utf8_bin NOT NULL, zip_code varchar(32)
COLLATE utf8_bin NOT NULL, phone_number varchar(16) COLLATE
utf8_bin NOT NULL, country int(8) NOT NULL, province int(8)
NOT NULL, pesel varchar(32) COLLATE utf8_bin NOT NULL,
register_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
authorised_time datetime NOT NULL, edit_time datetime NOT NULL,
saldo decimal(9,2) NOT NULL, referer_id int(8) NOT NULL,
level int(8) NOT NULL, PRIMARY KEY (id), KEY country
(country), KEY province (province), KEY referer_id
(referer_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
AUTO_INCREMENT=83 ;
In my case, the value was empty for target table column while the reference table column has it. hence was throwing this error.
In my case the references values does not corresponding on the related table. Just be sure the values exist on reference table and currents rows has corresponding valid values.
In my case , its no problem in SQL commands , but the inputs was not sending as $request , so in php.ini file :
max_input_vars was 1000 by default and I changed it to :
max_input_vars = 2000
then you have to restart web server .
You should pass NULL for empty values. Not empty string such as ''
in my case this was the error:
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'brand_name_ur' cannot be null (SQL: insert into brands (brand_name_en, brand_name_ur, brand_slug_en, brand_slug_ur, brand_image) values (SAMI, ?, sami, سامی, upload/brand/1742772943246486.png))
and fixed by
'brand_name_ur' => $request -> brand_image_ur,
< changing brand_image_ur to brand_name_ur. Noob mistak. took my hour.
thanks to #Tsimtsum
By running a request like :
SELECT user.id as user_id, country as user_country_type_id, country_type.id as country_type_id
FROM `user`
LEFT JOIN country_type ON country_type.id = user.country
WHERE country_type.id is null;
it probably returns some rows and it should not !
You can delete it (probably a bad idea if you are in production) using request like :
DELETE user
FROM `user`
LEFT JOIN country_type ON country_type.id = user.country
WHERE country_type.id is null;
and adding constraint should be done after !
add to your migrations
$this->addSql('SET foreign_key_checks = 0');
.....
$this->addSql('SET foreign_key_checks = 1');