MySQL: Increment value if exists, create if not (multiple criteria) - mysql

I have a table with three columns ('xCoord', 'yCoord' and 'Total'). I want to increment the Total value if the x,y coordinate pair already exists, else I want to create a new row with the new x and y values with Total = 1.
Below is my best attempt so far - running the query for the first time adds a new line (as expected), running it a second time adds a new line instead of incrementing the previously created line though? Is there a way to perform this with action with a single query?
INSERT
INTO tbl_DATA_HeatmapValues (xCoord, yCoord, Total)
VALUES (11, 22, 1)
ON DUPLICATE KEY
UPDATE Total = Total + 1

Your query should work, but you need to have a unique index. The check, if a row already exists is based on the index, not the actual data in the row. No index, no checking if it exists, therefore inserting no matter what.

INSERT ... ON DUPLICATE KEY UPDATE performs an update only where the insert would cause a duplicate value(s) in a UNIQUE index or PRIMARY KEY, see this link for details: http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html
Consider creating an unique index on xCoord, yCoord columns:
CREATE UNIQUE INDEX ON tbl_DATA_HeatmapValues (xCoord, yCoord)

Related

Get the last primary key from table with no auto increment

I have a table that has a primary key and for some reason i was advised not to use the AUTO_INCREMENT flag.
So every time i have to insert a new entry i search for the last value inserted (highest value) of the primary key.
Then i increment it by 1 to get a new ID.
Now the problem i face is, when inserting the first entry, there is no data in the table.
Can anyone suggest the optimal way to check
if data exists in table,
if not set id as 1 and insert new row,
else get the last id from table, increment it by 1 and then insert new row.
PS: New to mysql so having difficulty with its syntax.
Based on your statement 'i search for the last value inserted (highest value) of the primary key', I presume that you're currently doing something like this to get the maximum existing ID:
SELECT MAX(id_column) + 1 FROM my_table
If you have an empty table, this will of course return NULL. In that case, just handle the NULL using IFNULL to return 0 if there is no maximum value:
SELECT IFNULL(MAX(id_column), 0) + 1 FROM my_table
This will output 1 as the next identifier if the table has no rows.
I've given this more thought, and it turns out there is a way to generate a unique primary key without using Auto Increment or worrying about race conditions, so long as you are willing and able to use a 36 byte primary key (or, alternatively, a 128 bit binary).
The solution (at least as of MySQL 5.5) is the UUID, which stands for Universal Unique Identifier.
You would use it thus:
CREATE TABLE uu_table (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(50),
{other interesting columns}
)
Then insert new rows thus:
INSERT INTO uu_table VALUES (UUID(), 'Name of this Row', {other interesting values});
The UUID() function is guaranteed to generate a unique key 99.99{bunch more 9's}% of the time, even if generated on independent systems. That's its whole purpose, to be as unique as snowflake patterns, no matter where it is created.
There are pros and cons to this method. Best to read up on it here: https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_uuid
It is basically a 128 bit number, which you can save as a binary value after conversion from the 36 characters. I believe some versions of MySQL come with functions for that purpose. That would use less space in your database than 36 bytes, but I'll leave that as an exercise for the reader.

id not auto incremented and duplicate records

This is my table tb_currency_minimum_amount
When I am inserting a record using
INSERT IGNORE INTO tb_currency_minimum_amount ( id, currency_id, payment_method, minimum_amount) VALUES (NULL, 1, 16, 0.02)
again and again it creates a new entry
rows with id 32,33,34 are same
It i assigning it id 32 not 27 and ignoring duplicates
2:
The purpose of an AUTO_INCREMENT column is to ensure unique identifiers for the rows in the table.
It is just an implementation detail that it uses consecutive integer values. It is not a requirement for these values to be consecutive. Your code must not rely on the values being consecutive.
The value of the AUTO_INCREMENT is increased by each INSERT statement when a value for that column is not provided, no matter if the updated value is used (the query creates a new row) or not (it fails because of a duplicate key constraint or it updates an existing row because of ON DUPLICATE KEY).
Auto increment is count every record with +1. But it does not check of other columns are unique or duplicates.
In your id column which is auto increment I do not see any duplicates.
Could you elaborate your purpose what you trying to archive.
It is adding assigning it id 32 not 27 and ignoring duplicates
If i understand your question correctly, you should use the SQL SELECT DISTINCT Statement.
The SELECT DISTINCT statement is used to return only distinct (different) values.
Inside a table, a column often contains many duplicate values; and sometimes you only want to list the different (distinct) values.
The SELECT DISTINCT statement is used to return only distinct (different) values.

INSERT or UPDATE if condition over two columns (regardless of order) is met

I want to do the following:
INSERT INTO table1 (term1, term2, number) values ('A','B',10);
however if values A and B are already present in table1 regardless of their order, ie. the predicate
(term1='A' && term2='B') OR (`term1='B' && term2='A')
holds true, then I just want to update column number. Is there any way of doing that?
A (perhaps the) clean way to handle this situation is to use INSERT ... ON DUPLICATE KEY UPDATE, read the documentation.
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, MySQL
performs an UPDATE of the old row
The important part is would cause a duplicate value in a UNIQUE index. Therefore you need to create an multicolumn unique index.
Now I'm not sure if you can manage the order that way, therefore I'd create an extra field with the concatenation of the sorted values of your fields, and have that field uniquely indexed.
EDIT: Instead of storing the concatenation your fields, you could also just store the hash and index it.
Thanks #okiharaherbst,
This is what I did: I added new column "uniqueKey" as primary key and insert goes as follows:
INSERT INTO table1(term1,term2,num,uniquekey) VALUES ( "a","b",10,
concat(greatest(term1,term2),least(term1,term2))) on duplicate key update num=10;

Insert missing data only in MySQL

I have two tables, the first table has 400 rows. The second table holds the same records with the same count. Now the first table row count increases to 450. I want to insert only those 50 new rows into the second table. I don't need to update the first 400 records.
I am setting the unique index for the particular field (like empid). Now when I insert the first table data it returns the following error:
Duplicate entry 'xxxx' for key 'idx_confirm'
Please help me to fix this error.
Am using the below code to insert the record. But it allows duplicate entry..
insert ignore into tbl_emp_confirmation (fldemp_id,fldempname,fldjoindatefldstatus)
select fldempid, fldempname,DATE_FORMAT (fldjoindate,'%Y-%m-%d') as fldjoindate,fldstatus from tblempgeneral as n;
Modify your INSERT ... statement to INSERT IGNORE ....
See for example this post for an explanation.
You need to make sure that you have a unique index that prevents any duplicates, such as on the primary key.

Which is a faster way for checking for duplicate entries, then creating a new entry?

I want to check if an entry exist, if it does I'll increment it's count field by 1, if it doesn't I'll create a new entry and have it's count initialize to 1. Simple enough, right? It seems so, however, I've stumbled upon a lot of ways to do this and I'm not sure which way is the fastest.
1) I could use this to check for an existing entry, then depending, either update or create:
if(mysql_num_rows(mysql_query("SELECT userid FROM plus_signup WHERE userid = '$userid'")))
2) Or should I use WHERE_EXISTS?
SELECT DISTINCT store_type FROM stores
WHERE EXISTS (SELECT * FROM cities_stores
WHERE cities_stores.store_type = stores.store_type);
3) Or use this to insert an entry, then if it exists, update it:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
4) Or perhaps I can set the id column as a unique key then just wait to see if there's a duplicate error on entry? Then I could update that entry instead.
I'll have around 1 million entries to search through, the primary key is currently a bigint. All I want to match when searching through the entries is just the bigint id field, no two entries have the same id at the moment and I'd like to keep it that way.
Edit: Oh shoot, I created this in the wrong section. I meant to put it into serverfault.
I believe it's 3.
Set an INDEX or a UNIQUE constraint and then use the syntax of number 3.
It depends which case will happen more often.
If it is more likely that the record does not exists I'd go for an INSERT IGNORE INTO, checking affected rows afterwards; if this is 0 the record already exists, so an UPDATE is issued.
Otherwise I'd go for INSERT INTO ... ON DUPLICATE KEY UPDATE.