문제

Description:

I am trying to insert user's preferences into a database. If the user hasn't yet placed any, I want a insert, otherwise, I want an update. I know I can insert default values in the creation of the user and than exclusively use update, but that adds another query (I think)

Problem:

I have read up on ON DUPLICATE KEY UPDATE but I don't understand it. This is almost the exact question I have but without the answer. The answer says:

It does sound like it will work for what you want to do as long as you hav the proper column(s) defined as UNIQUE KEY or PRIMARY KEY.

If I do a simple insert like so:

INSERT INTO table (color, size) VALUES ('blue', '18') ... 

How will that ever produce at DUPLICATE KEY? As far as mysql knows it's just another insert and the id is auto-incremented. I have the primary key in the table set to unique, but the insert isn't going to check against that, right?

Table:

CREATE TABLE `firm_pref` (
    `id` int(9) NOT NULL AUTO_INCREMENT,
    `firm_id` int(9) NOT NULL, //user_id in this case
    `header_title` varchar(99) NOT NULL,
    `statement` varchar(99) NOT NULL,
    `footer_content` varchar(99) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
도움이 되었습니까?

해결책

Well, unless you want your application to be used by a single person only, you would have to specify someone's user_id in that INSERT - when this 'someone' guy or girl updates his/her preferences, right?

This field (user_id) is exactly what would be checked by ON DUPLICATE KEY UPDATE clause.

And if you want to insert a new record, just send NULL instead:

INSERT INTO table (user_id, color, size) VALUES (NULL, 'blue', 18);

... so auto-increment will have a chance to move on and save the day. )

UPDATE: Take note that to understand that some field should be considered a unique identifier, you should mark it as such. Usually it's done naturally, as this field is used as a PRIMARY KEY. But sometimes it's not enough; it means some work for UNIQUE constraint. For example, in your table it can be used like this:

CREATE TABLE `prefs` (
    `id` int(9) NOT NULL AUTO_INCREMENT,
    `firm_id` int(9) NOT NULL,
     ...
     PRIMARY KEY (`id`),
     UNIQUE KEY (`firm_id`)
);

(or you can add this constraint to the existing table with ALTER TABLE prefs ADD UNIQUE (firm_id) command)

Then insert/update query will look like...

INSERT INTO prefs(firm_id, header_title, statement, footer_content) 
           VALUES(17, 'blue', '18', 'some_footer')
 ON DUPLICATE KEY UPDATE 
           header_title = 'blue', 
           statement = '18', 
           footer_content = 'some_footer';

I've built a sort of demo in SQL Fiddle. You can play with it some more to better understand that concept. )

다른 팁

For options, you would normally have an options table that has a list of available options (like color, size etc), and then a table that spans both your options table and users table with the users' values.

For example, your options table:

id | name
=========
1  | color
2  | size

Your users table:

id | name
================
1  | Martin Bean

And an options_users join table:

option_id | user_id | value
===========================
1         | 1       | Blue
2         | 1       | Large

With the correct foreign keys set up in your options_users table, you can have redundant values removed when an option or user is removed from your system. Also, when saving a user's preferences, you can first delete their previous answers and insert the new ones.

DELETE FROM `options_users`
WHERE `user_id` = @user_id;

INSERT INTO `options_users` (`option_id`, `user_id`, `value`)
VALUES (1, @user_id, 'Blue'), (2, @user_id, 'Large');

Hope that helps.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top