Let's say I have a users table:
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`city_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `users_city_id_foreign` (`city_id`),
CONSTRAINT `users_city_id_foreign` FOREIGN KEY (`city_id`) REFERENCES `cities` (`id`)
);
That is linked to a cities table:
CREATE TABLE `cities` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`country_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `cities_country_id_foreign` (`country_id`),
CONSTRAINT `cities_country_id_foreign` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`)
);
and that is linked to a countries table:
CREATE TABLE `countries` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
I'll often need the user's country name. I already have access to the country name via user->city->country
:
SELECT `users`.`name`, `countries`.`name`
FROM `users` JOIN
(`cities` JOIN `countries` ON `cities`.`country_id` = `countries`.`id`)
ON `users`.`city_id` = `cities`.`id`;
but I would like to have direct access like:
SELECT `users`.`name`, `countries`.`name`
FROM `users` JOIN `countries` ON `users`.`country_id` = `countries`.`id
Is it ok to add a foreign key linking directly the user table to the country table like this or should i avoid it?
ALTER TABLE `users`
ADD COLUMN `country_id` BIGINT(20) UNSIGNED NOT NULL AFTER `city_id`,
ADD INDEX `users_country_id_foreign_idx` (`country_id` ASC);
ALTER TABLE `users`
ADD CONSTRAINT `users_country_id_foreign`
FOREIGN KEY (`country_id`)
REFERENCES `countries` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
You create a risk of a data anomaly by adding the country_id to the users table. How would you explain this data:
countries:
1, UK
2, US
cities:
1, Little Whinging, 1
2, New York, 2
users:
1, Harry Potter, 1, 2
How can Harry Potter live in a city in the UK, but be assigned a country_id corresponding to the US? That's an anomaly that is possible if you store the redundant country_id in the users table. You can make data that disagrees with itself.
You could solve this by making the pair of city_id and country_id in users reference the pair of city_id and country_id in the cities table. At least that would prevent the anomaly, because it would have to reference a key in that table in which that pair of values exists (you'd have to create a two-column key in cities first). But it's still redundant.
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`city_id` bigint(20) unsigned NOT NULL,
`country_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `users_city_country_foreign` FOREIGN KEY (`city_id`, `country_id`)
REFERENCES `cities` (`id`, `country_id`)
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.