Insert If duplicate not found in table else update - mysql

I wanted to ignore or update duplicate when I am going to insert values. I know about on duplicate key but i can't figure out the solution with that. Here is sample table example.
| ID | roll | sub | mark |
| ---- |----------| ------|------|
| 1 | 100 | 11 | 15 |
| 2 | 101 | 11 | 16 |
| 3 | 102 | 11 | 17 |
| 4 | 100 | 12 | 10 |
| 5 | 101 | 12 | 11 |
| 6 | 102 | 12 | 12 |
Here the id is primary key but I wanted to insert to check if roll & sub already exist then update otherwise insert new row. I've tried with the following code but that's insert duplicate row but it should update row 6 in following table.
CREATE INDEX mycompo_index on student(roll,sub);
insert into student(roll, mark, sub)
values (102, 22, 12)
on duplicate key update mark = values(mark);

If the combination of roll and sub should be unique, you should define such a key in your table:
ALTER TABLE student ADD CONSTRAINT student_uq UNIQUE(roll, sub)
Note that if you do this, you don't have to explicitly create the index you're creating, the constraint will create on for you. Once you have this is place, you can use the on duplicate key syntax you were trying to use:
INSERT INTO student(roll, mark, sub)
VALUES (102, 22, 12)
ON DUPLICATE KEY UPDATE mark = VALUES(mark)

Related

Mysql insert multiple rows, if duplicate value column then update

I have a MySQL table that looks like this
id | customer_id | textkey | value |
---+-------------+---------+-------+
1 | 1 | text1 | value1|
2 | 1 | text2 | value2|
3 | 1 | text3 | value3|
4 | 1 | text4 | value4|
5 | 2 | text1 | value1|
...
I want to insert the following values to customer_id 1
(text1, valueX), (text3, valueY), (text5, value5), (text6, value6)
The end result should look like this
mysql> SELECT * from MyTable where customer_id=1;
id | customer_id | textkey | value |
---+-------------+---------+-------+
1 | 1 | text1 | valueX|
2 | 1 | text2 | value2|
3 | 1 | text3 | valueY|
4 | 1 | text4 | value4|
6 | 1 | text5 | value5|
7 | 1 | text6 | value6|
The value column should update whenever there is a duplicate in the textkey insert, and insert regularly if the textkey is not a duplicate. What query could I use to achieve this? I tried using IGNORE, LAST_INSERT_ID(), and ON DUPLICATE KEY UPDATE but I cant figure out what works for a "ON DUPLICATE COLUMN UPDATE" scenario. Thanks
You must create unique index which will detect the duplication:
CREATE UNIQUE INDEX idx ON test (customer_id, textkey);
Now you can use INSERT .. ODKU:
INSERT INTO test (customer_id, textkey, value) VALUES
(1, 'text1', 'valueX'),
(1, 'text3', 'valueY'),
(1, 'text5', 'value5'),
(1, 'text6', 'value6')
ON DUPLICATE KEY UPDATE
value = VALUES(value);
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=6dcc351706f574f4c9f13c1fc95b9225

Use ON DUPLICATE KEY UPDATE to update row with MySQL

I've the following table structure:
Table ___Availabilities :
|--------|------------|------------|------------|
| AVA_Id | AVA_RoomId | AVA_Date | AVA_Status |
|--------|------------|------------|------------|
| 1 | 47 | 2019-03-11 | NoData |
| 2 | 48 | 2019-03-22 | Book |
| 3 | 48 | 2019-03-23 | Book |
|--------|------------|------------|------------|
I want to UPDATE the AVA_Status only if AVA_RoomId and AVA_Date are know in a row of the table. If not, INSERT a new row.
So my query is this one:
INSERT INTO ___Availabilities
(AVA_Id, AVA_RoomId, AVA_Date, AVA_Status)
VALUES('', '103', '2019-04-04', 'Open')
ON DUPLICATE KEY UPDATE
`AVA_RoomId`='47',
`AVA_Date`='2019-03-11'
But it doesn't work as it added a new row whereas it should update the row where AVA_RoomId = 47 and AVA_Date = 2019-03-11.
Why my query is not working please ?
Thanks.
Assuming there is a UNIQUE INDEX(AVA_RoomId, AVA_Date)
You might want to update the AVA_Status when the combination of room and date already exists:
INSERT INTO ___Availabilities
(`AVA_RoomId`, `AVA_Date`, `AVA_Status`)
VALUES('103', '2019-04-04', 'Open')
ON DUPLICATE KEY UPDATE
`AVA_Status` = VALUES(`AVA_Status`),
As #Barmar already explained, if not already done, you can still add an index after table creation:
ALTER TABLE `___Availabilities`
ADD UNIQUE INDEX `uq_room_date` (`AVA_RoomId`, `AVA_Date`)
;

SQL ON DUPLICATE KEY with 2 unique keys?

I have a MySQL table that goes like so:
+----+--------+-------+-------------+
| id | userID | month | lastUpdated |
+----+--------+-------+-------------+
| 1 | 5 | 1 | 2017-03-27 |
| 2 | 5 | 2 | 2017-03-22 |
| 3 | 5 | 3 | 2017-03-21 |
| 4 | 9 | 1 | 2017-03-27 |
| 5 | 9 | 2 | 2017-03-22 |
| 6 | 9 | 3 | 2017-03-21 |
+----+--------+-------+-------------+
I want to make an INSERT statement to this table but use ON DUPLICATE KEY UPDATE like this:
INSERT INTO users_last_updated
(userID, month, lastUpdated)
VALUES
(:userID, :month, :lastUpdated)
ON DUPLICATE KEY UPDATE lastUpdated = :lastUpdated
The thing is, a userID can show up multiple times and a month value can show up multiple times BUT, the uniqueness of each row is a combination of userID & month (e.g: userID = 1 & month = 3 can only appear once).
Is there a way to make a combination of 2 columns to be unique?
Thanks :)
If the unique key is userid/month, then use both of those for a unique index or constraint:
create index unq_users_last_updated_2 on users_last_updated(userId, month);
I would add that it seems strange to have month without a year.
The on duplicate key uses any and all available unique indexes, including primary keys (but not limited only to primary keys).

MySQL - Increment Column Value or Insert Data if not Exists

I have users visiting the site. The user can do a bunch of different actions. I'd like a counter to count the amount of times the user does that action. The problem is, it's per day, it starts over each day.
So the model has, Id, User, Action, Times, Date
I'd like to use this, but I can't because Action is not a key, and cannot be. None of the other fields can be a key either.
insert into useractions (user, action, times) values (2, 3, 1)
on duplicate key update times = times + 1;
You left the data column out of your insert example, but you mentioned it several times so I'll assume that exists. Also, I'm assuming it's an actual date (not a timestamp or datetime).
If you add a unique index on (user,action,date) then your query will work.
Here's the DDL:
alter table useractions
add unique index unique_idx (user,action,date);
And your DML (adding the date column):
insert into useractions (user, action, times, date) values (2, 3, 1, current_date())
on duplicate key update times = times + 1;
Do you absolutely want to calculate the counter value at the time of inserting the action? It may be simpler to simply keep track of the users and actions with timestamps, like so:
+--------+----------+---------------------+
| UserID | ActionID | Time |
+--------+----------+---------------------+
| 1 | 1 | 2012-01-19 14:47:03 |
| 1 | 2 | 2012-01-19 14:48:12 |
| 1 | 3 | 2012-01-19 14:48:15 |
| 2 | 1 | 2012-01-19 14:49:33 |
| 2 | 1 | 2012-01-18 14:49:42 |
And then calculate the daily tallies with a query:
SELECT UserID,
ActionID,
DATE(Time) AS Date,
COUNT(*) AS n
FROM actions
GROUP BY UserID,ActionID,Date
ORDER BY Date,UserID,ActionID;
+--------+----------+------------+---+
| UserID | ActionID | Date | n |
+--------+----------+------------+---+
| 1 | 2 | 2012-01-17 | 2 |
| 1 | 3 | 2012-01-17 | 2 |
| 3 | 2 | 2012-01-17 | 6 |
| 1 | 1 | 2012-01-18 | 1 |
| 1 | 2 | 2012-01-18 | 1 |
| 1 | 3 | 2012-01-18 | 4 |
You can use a unique key on a combination of columns. That way you can make that combination (user, action, date) unique and your query should then work.
That really is the easiest solution. You do need rights to alter the table though.

ON DUPLICATE KEY: multi-column unique constraint

Right now I have:
INSERT INTO mytable (a,b,c,d) VALUES(1,2,3,4)
ON DUPLICATE KEY UPDATE c=VALUES(c),d=VALUES(d)
which works if a or b are UNIQUE keys...
But now I want to UPDATE only when another row with the pair (a,b) doesn't exist in the table (otherwise skip insertion).
Basically (a,b) shoud be UNIQUE, not (a) or (b), but both connected.
For example these rows would be valid
ID (auto-inc) | a | b | c | d
0 | 5 | 1 | 343 |466
1 | 5 | 2 | 363 |466
2 | 5 | 3 | 343 |496
3 | 7 | 1 | 343 |496
Because there's 5,1, 5,2, 5.3, 7.1 etc.
But row #2 here should be considered duplicate of row #1, so row #1 should be updated:
ID (auto-inc) | a | b | c | d
0 | 5 | 1 | 343 |466
1 | 5 | 1 | 363 |466
2 | 5 | 3 | 343 |496
3 | 7 | 1 | 343 |496
Is this possible?
make UNIQUE KEY to (a,b) not to b
ALTER TABLE tblname ADD UNIQUE (a,b)
CREATE UNIQUE INDEX index_unique_on_a_and_b ON mytable (a,b)
It's worth noting that if you try to add the ADD UNIQUE(a,b) while there is data in the table, you'll likely get a duplicate key error. Empty the table, add the unique index, and it'll work.