Frage

I have two tables :

CREATE TABLE `Users` (
  `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) NOT NULL DEFAULT '',
  `last_name` varchar(50) NOT NULL DEFAULT '',
  `login` varchar(50) NOT NULL DEFAULT '',
  `password` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

AND

CREATE TABLE `Books` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(50) NOT NULL DEFAULT '',
  `author` varchar(50) NOT NULL DEFAULT '',
  `year` int(4) NOT NULL,
  `available` int(3) NOT NULL DEFAULT '0',
  `availabledate` date NOT NULL,
  `user_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

I am trying to create a relationship between those two, so that one user may have multiple books (user_id) but whatever I'm doing I'm getting errors. Either

Cannot add or update a child row: a foreign key constraint fails (bookstore., CONSTRAINT books_fk FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE)

or before I didn't use unsigned int in the Books table and I said that default value is 0 (which I would prefere but I don't think I can do that?) In that case I got error 150.

War es hilfreich?

Lösung

I'd recommend, to change your database schema. Why?

  1. Can a book exist without having a user? If yes, you shouldn't have a foreign key from books referencing users. Can a user exist without having a book? If yes, you shouldn't have a foreign key from users referencing books.

  2. Can a user have multiple books? And a book multiple users? If yes, you have a m:n relationship. This means you need a bridge table.

In your tables you don't need foreign keys:

CREATE TABLE `Users` (
  `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) NOT NULL DEFAULT '',
  `last_name` varchar(50) NOT NULL DEFAULT '',
  `login` varchar(50) NOT NULL DEFAULT '',
  `password` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

CREATE TABLE `Books` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(50) NOT NULL DEFAULT '',
  `author` varchar(50) NOT NULL DEFAULT '',
  `year` int(4) NOT NULL,
  `available` int(3) NOT NULL DEFAULT '0',
  `availabledate` date NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

And a bridge table would look like this:

CREATE TABLE books_users (
book_id int(11) unsigned NOT NULL,
user_id int(11) unsigned NOT NULL,
PRIMARY KEY (book_id, user_id),
KEY idx_user_id (user_id),
FOREIGN KEY fk_books (book_id) REFERENCES Books(id),
FOREIGN KEY fk_users (user_id) REFERENCES Users(user_id)
) ENGINE=InnoDB;

This solves both problems and is common practice.

To query both users and books in one query, you join them like this:

SELECT
whatever
FROM
Books b
INNER JOIN books_users bu ON b.id = bu.book_id
INNER JOIN users u ON bu.user_id = u.user_id
WHERE user_id = 1 /*for example*/
;

If you want to insert something in the tables, just do the insert and get the id which was generated for the row with SELECT LAST_INSERT_ID();, then insert this id in the books_users bridge table.

Updates don't affect anything, you can simply perform them on users or books. If you really really have to update the auto_increment column (which usually isn't needed and not recommended) you can add ON UPDATE CASCADE after the foreign keys in the books_users table.

Andere Tipps

Change these lines and try again

change user_id int(11) unsigned NOT NULL AUTO_INCREMENT to user_id int(11) NOT NULL AUTO_INCREMENT

and

id int(11) unsigned NOT NULL AUTO_INCREMENT, to id int(11) NOT NULL AUTO_INCREMENT,

and

user_id int(11) unsigned NOT NULL, to user_id int(11) NOT NULL,

Finally try

CREATE TABLE `Users` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) NOT NULL DEFAULT '',
  `last_name` varchar(50) NOT NULL DEFAULT '',
  `login` varchar(50) NOT NULL DEFAULT '',
  `password` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

and

CREATE TABLE `Books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(50) NOT NULL DEFAULT '',
  `author` varchar(50) NOT NULL DEFAULT '',
  `year` int(4) NOT NULL,
  `available` int(3) NOT NULL DEFAULT '0',
  `availabledate` date NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

If you are using Mysql then you must use InnoDB database engine to enable relationship between two tables MyISAM will not allow this relationship

alter table `users` add constraint `FK_users` FOREIGN KEY (`user_id`) REFERENCES `books` (`user_id`) ON DELETE NO ACTION  ON UPDATE NO ACTION 

or you can use this query for cascade edit delete

alter table `users` add constraint `FK_users` FOREIGN KEY (`user_id`) REFERENCES `books` (`user_id`) ON DELETE CASCADE  ON UPDATE CASCADE 

This is your new DDL for two tables try this

CREATE TABLE IF NOT EXISTS `books` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(50) NOT NULL DEFAULT '',
  `author` varchar(50) NOT NULL DEFAULT '',
  `year` int(4) NOT NULL,
  `available` int(3) NOT NULL DEFAULT '0',
  `availabledate` date NOT NULL,
  `user_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

-- --------------------------------------------------------

--
-- Table structure for table `users`
--

CREATE TABLE IF NOT EXISTS `users` (
  `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) NOT NULL DEFAULT '',
  `last_name` varchar(50) NOT NULL DEFAULT '',
  `login` varchar(50) NOT NULL DEFAULT '',
  `password` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=15 ;

--
-- Constraints for dumped tables
--

--
-- Constraints for table `users`
--
ALTER TABLE `users`
  ADD CONSTRAINT `FK_users` FOREIGN KEY (`user_id`) REFERENCES `books` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top