where is the duplicate in ON DUPLICATE KEY query?
-
01-07-2021 - |
문제
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.