ON DUPLICATE KEY UPDATE not updating only insert - mysql

I am trying to check if a session exists for a customer so that I can either update the session with new session details or insert a session for a customer. I am using the statement below:
INSERT INTO sessions (customerid, productlist, date)
VALUES('33', '{"68":1,"72":1}', '2016-03-03 13:54:56')
ON DUPLICATE KEY UPDATE customerid=VALUES(customerid)
When I run this, the statement inserts a session for customer even if a session already exists.

ON DUPLICATE KEY UPDATE requires an UNIQUE INDEX on the table. It allows updating the already existing row when the INSERT will fail because of the UNIQUE INDEX.
The candidate for UNIQUE INDEX in your sessions table is customerid. Do you have such an index?
Anyway, the query you posted doesn't make any sense. ON DUPLICATE KEY UPDATE kicks in when you want to insert a new row and the value you want to put in customerid already exists in the table. The UNIQUE INDEX prevents the insertion and ON DUPLICATE KEY UPDATE allows the updating of some of the other columns of the existing row.
When customerid is the UNIQUE INDEX, customerid=VALUES(customerid) is a no-op.
What you probably want is:
INSERT INTO sessions (customerid, productlist, date)
VALUES('33', '{"68":1,"72":1}', '2016-03-03 13:54:56')
ON DUPLICATE KEY UPDATE productlist=VALUES(productlist), date=VALUES(date)
The SQL statement to make customerid an UNIQUE INDEX of table sessions is:
ALTER TABLE `sessions`
ADD UNIQUE INDEX `customerid` (`customerid`)
Or, even better, make is the PRIMARY KEY of the table (if the table doesn't already have one:
ALTER TABLE `sessions`
ADD PRIMARY KEY (`customerid`)

Make sure you create an UNIQUE key by using: customerid and pdoructlist columns.

Related

Sql Statement: Insert On Key Update is not working as expected when primary key is not specified in the fields to insert

Hello I am using the "INSERT ON DUPLICATE KEY UPDATE" sql statement to update my database.
All was working fine since I always inserted an unique id like this:
INSERT INTO devices(uniqueId,name)
VALUES (4,'Printer')
ON DUPLICATE KEY UPDATE name = 'Central Printer';
But for now, I need to insert elements but I don't insert a unique id, I only insert or update the values like this:
INSERT INTO table (a,b,c,d,e,f,g)
VALUES (2,3,4,5,6,7,8)
ON DUPLICATE KEY
UPDATE a=a, b=b, c=c, d=d, e=e, f=f, g=g;
Have to say that an autoincrement primary key is generated always that I insert a row.
My problem is that now the inserted rows are duplicated since I don't insert the primary key or unique id explicitly within the sql statement.
What I am supposed to do?
For example, maybe I need to insert the primary key explicitly? I would like to work with this primary autoincremented key.
For recommendation from Gordon I am adding a sample case the you can see in the next image
Rows Output
In this case I add the first three rows, and then I try to update the three first rows again with different information.... Ok I am seeing the error... There is no key to compare to...... :$
Thanks for your answers,
If you want to prevent columns from being duplicated, then create a unique index or constraint on them. For instance:
create unique index unq_table_7 on table(a, b, c, d, e, f, g);
This will guarantee that the 7 columns -- in combination -- are unique.

INSERT if exists UPDATE

I've been looking at other resources and am just getting a bit confused. I'd like to relate an example to my problem.
I have a game server which stores a unique id from steam in a database, and along with this has a column for specific permissions to that user. E.g id: 712309123810 permission: default
What I want to achieve is sending data from a form; $Id and $permission are posted. Insert this data into the database under columns for example sake; 'Id' and 'permission'. I can do this, what I am having issues is understanding how to UPDATE only the $permission column if the $id already exists in the db.
I have read about ON DUPLICATE KEY UPDATE , but am confused about how to correctly utilize it. I am fairly new to mysql.
Thanks for your time.
The on duplicate key fires when the insert part of the statement violates a unique constraint (in your case - the primary key on id). So, to put it all together:
INSERT INTO mytbale (id, permissions)
VALUES (:id, :permissions)
ON DUPLICATE KEY UPDATE permissions = :permissions
It's explained rather well by the manual:
http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
Your query might be something like:
INSERT INTO myTable (id, permissions) VALUES (712309123810, "default")
ON DUPLICATE KEY UPDATE permissions = "default";
This requires that the table contains a unique or primary key on the id column.
Normally, if you attempt to insert a new row that would create a duplicate value for a unique or primary key, it is an error. Using ON DUPLICATE KEY UPDATE changes that: instead, your insert transforms into an update.
The example query I gave will insert a new record if none with that id exists, or it will update the permissions of the existing one.
Typically, an id can have multiple permissions. If so, you don't want to overwrite the permissions; you want to accumulate them. If this is the case, you might need junction table to handle this:
create table UserPermissions (
UserPermissionsId int auto_increment primary key,
UserId int not null,
PermissionId int not null,
constraint fk_UserPermissions_UserId foreign key UserId references Users(UserId),
constraints fk_UserPermissions_PermissionId foreign key Permissions references Permissions (PermissionId)
);
If a user has only one permission that gets overwritten, then on duplicate key update is appropriate.

On duplicate key issue

I have a table for updating times for a game, in which columns are unique to avoid duplicates.
My problem is the following: how to update a particular column only and avoid inserting a new row if they are the same?
Here is the query.
I did this code and it still enters a new row instead of updating the Time Column only:
INSERT INTO `leaderboard` (`Persona`, `Level`, `Track`, `Car`, `Mode`, `Time`,
`Date`, `Timestamp`, `HMS`)
VALUES ('STIG', 80, 'SPA FRANCORCHAMPS',
'AUDI R8 LMS ULTRA', 'HD', '02:17.332',
'2014-12-06', '1417825487', '1:24:47')
ON DUPLICATE KEY UPDATE `Time` = '02:17.332';
You are actually creating a composite unique key in:
ALTER TABLE `leaderboard`
ADD UNIQUE KEY `Persona` (`Persona`,`Level`,`Track`,`Car`,`Mode`,`Time`,`Date`,`Timestamp`,`HMS`);
It means that the tuple (Persona, Level, Track, Car, Mode, Time, Date, Timestamp, HMS) will be unique. However, the time columns are to be updated, and it is very likely they won't be unique.
Maybe what you want to do is:
ALTER TABLE `leaderboard`
ADD UNIQUE KEY `Persona` (`Persona`,`Level`,`Track`,`Mode`);

MySQL "Insert ... On Duplicate Key" with more than one unique key

I've been reading up on how to use MySQL insert on duplicate key to see if it will allow me to avoid Selecting a row, checking if it exists, and then either inserting or updating. As I've read the documentation however, there is one area that confuses me. This is what the documentation says:
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, an UPDATE of the old row is performed
The thing is, I don't want to know if this will work for my problem, because the 'condition' I have for not inserting a new one is the existence of a row that has two columns equal to a certain value, not necessarily that the primary key is the same. Right now the syntax I'm imagining is this, but I don't know if it will always insert instead of replace:
INSERT INTO attendance (event_id, user_id, status) VALUES(some_event_number, some_user_id, some_status) ON DUPLICATE KEY UPDATE status=1
The thing is, event_id and user_id aren't primary keys, but if a row in the table 'attendance' already has those columns with those values, I just want to update it. Otherwise I would like to insert it. Is this even possible with ON DUPLICATE? If not, what other method might I use?
The quote includes "a duplicate value in a UNIQUE index". So, your values do not need to be the primary key:
create unique index attendance_eventid_userid on attendance(event_id, user_id);
Presumably, you want to update the existing record because you don't want duplicates. If you want duplicates sometimes, but not for this particular insert, then you will need another method.
If I were you, I would make a primary key out of event_id and user_id. That will make this extremely easy with ON DUPLICATE.
SQLFiddle
create table attendance (
event_id int,
user_id int,
status varchar(100),
primary key(event_id, user_id)
);
Then with ease:
insert into attendance (event_id, user_id, status) values(some_event_number, some_user_id, some_status)
on duplicate key
update status = values(status);
Maybe you can try to write a trigger that checks if the pair (event_id, user_id) exists in the table before inserting, and if it exists just update it.
To the broader question of "Will INSERT ... ON DUPLICATE respect a UK even if the PK changes", the answer is yes: SQLFiddle
In this SQLFiddle I insert a new record, with a new PK id, but its values would violate the UK. It performs the ON DUPLICATE and the original PK id is preserved, but the non-UK ON DUPLICATE KEY UPDATE value changes.

Can I re-insert a row with a newly created auto_increment primary key

EDIT:
I want to update the id to a newly created auto increment id, the rest of the row's columns will not change.
ORIGINAL:
I've got a table in mysql looking like:
id userId productId
all columns are UBIGINT, and id is the PRIMARY KEY, set to AUTO INCREMENT.
So now I want to re-insert a row into the same table, but with a newly created id. And the old row should be deleted!
I'm using the id for order (higher == newer).
Is this possible, because the other option is adding a timestamp column and updating this column, but I won't use the timestamp. So I want to prevent this at all costs.
Let's say we have following table
create table so (
`id` int(11) not null auto_increment,
`num` varchar(20) not null, primary key (`id`),
unique (`num`)
) engine=InnoDB default charset=utf8;
Then we can use following query to insert new row
insert into so (num) values ("hi") on duplicate key update id=last_insert_id()+1;
If there is already "hi"-row this query will update it's id to be equal next after the last inserted
In your case
insert into table (userId, productId) values (someUserId, someProductId)
on duplicate key update id=last_insert_id()+1;
Also, there is replace MySQL extension.
replace into table (userId, productId) values (someUserId, someProductId);
As an on duplicate key update it will only work if your table has unique or primary key constraint.
Unlike on duplicate key update replace will first delete existing row and then insert new, while on duplicate key update will just update it.
INSERT INTO table (userId, productId) VALUES
(SELECT userId, productId FROM table WHERE id=[id of row]);
DELETE FROM table WHERE id=[id of row];
Yes it is possible. You just have to delete the old record and add an other one. But you have to know that the auto_increment will always grow.