mysql Query Insert into or update when entry already exists - mysql

I have the following query (user_id isn't and can't be primary key as there are many entries from each user depending on another column of the table). I used duplicate key but doesnt work. It still adds a new row. Any thoughts?
INSERT INTO profile (user_id, correct) VALUES(". $user_id . ", correct + 1)
ON DUPLICATE KEY UPDATE correct=correct+1
EDIT
So if row exists for this user_id, I want to go update this entry and SET correct = correct+1 and not make a new entry with user_id and correct=1 again

Try this:
INSERT IGNORE INTO profile (user_id, correct)
VALUES ($user_id, 0);
UPDATE profile SET correct = correct + 1
WHERE user_id = $user_id; -- updates 0 to 1
Or:
UPDATE profile SET correct = correct + 1
WHERE user_id = $user_id;
If not found:
INSERT INTO profile (user_id, correct)
VALUES ($user_id, 1);
I prefer the second variant.
The first variant requires that the user_id has a UNIQUE constraint. (PRIMARY KEY counts.)

Related

Mysql trigger add number to new value on duplicate key

I'm trying to import data to a new table, but turns out some values from two different columns are duplicate, but it seems to not be working. This is what my trigger looks like:
DELIMITER //
CREATE TRIGGER insert_specificationattributeoption_child AFTER INSERT ON import_specificationattributeoption FOR EACH ROW
BEGIN
INSERT INTO t_virtuemart_customs (virtuemart_custom_id, custom_parent_id, custom_title, show_title, field_type, custom_params, created_on, created_by, ordering, modified_on, modified_by)
VALUES (NEW.option_id, NEW.specification_attribute_id, NEW.option_name, lower(NEW.option_name), 'S', 0, current_time(), 633, NEW.display_order, current_time(), 633)
ON DUPLICATE KEY UPDATE NEW.option_id = NEW.option_id + 5000;
END //
With the trigger I don't get the duplicate key error, but I don't see any key being over 5000. What am I doing wrong there? Would it be better to "find" the highest id and adding the new id to it instead?
Edit: Basically what I want to do is, if I'm inserting a primary key that already exists, change the value I want to insert.
I am not clear what you are trying to do. The trigger must be detecting the duplicate key because no duplicate error is being shown but UPDATE NEW.option_id = NEW.option_id + 5000 has no effect on the table. If you want to amend the table then the syntax would be UPDATE option_id = NEW.option_id + 5000 -note this also amends the next auto_increment value to NEW.option_id + 5000 + 1.

Using WHERE clause in ON DUPLICATE KEY UPDATE column

Here's the table design for a cartitems table
cartitems
cartitem_id PK AI
customer_id FK
item_id FK UNIQUE
item_quantity INT DEFAULT 1
What I need to accomplish
1.) if item_id exists in the table, increment the item_quantity by 1 everytime user clicks on "Add To Cart" button for the same item_id
2.) if item_id doesn't yet exist in the table, run an insert statement.
So what I did is this.
CREATE DEFINER=`root`#`localhost` PROCEDURE `addItemToCart`(aCustomerId int, aProductId int)
BEGIN
INSERT INTO cart_items(customer_id,product_id)
VALUES(aCustomerId,aProductId)
ON DUPLICATE KEY UPDATE
item_quantity = item_quantity + 1
WHERE customer_id = aCustomerId AND item_id = aProductId;
END
But when I inspected it, I get an error that says, missing semicolon at item_quantity = item_quantity + 1
I can't figure out what's causing the error. I don't know if it's a problem with the WHERE clause.
I'd appreciate any help.
Thanks.
The behavior of ON DUPLICATE KEY UPDATE is well explained in 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
Looking at your table, you want to increment the quantity of an item for a given customer's cart. I am assuming here that a customer may only have one shopping cart at a time. So the conditions under which you want MySQL to perform an UPDATE rather than an INSERT is when the customer and item already appear in the table.
Towards this end, you can create a unique index on these two columns via:
CREATE UNIQUE INDEX unq_item_index ON cart_items (customer_id, item_id);
Then, you can use the following INSERT query:
INSERT INTO cart_items (customer_id, item_id)
VALUES
(aCustomerId, anItemId)
ON DUPLICATE KEY UPDATE
item_quantity = item_quantity + 1
WHERE customer_id = aCustomerId AND
item_id = anItemId;
Now the behavior will be that if a new entry for customer/item comes in, the item_quantity will be set to the default value of 1, otherwise the item_quantity will be incremented by 1.
BEGIN
IF NOT EXISTS(SELECT 1 FROM cart_items WHERE item_id = aProductId)
BEGIN
INSERT INTO cart_items(customer_id,product_id)
VALUES(aCustomerId,aProductId)
END
ELSE
UPDATE cart_items SET item_quantity = item_quantity + 1 WHERE customer_id = aCustomerId AND item_id = aProductId;
END
Why are you trying to use that WHERE clause there? It doesn't make sense. If DUPLICATE KEY happens it will UPDATE whatever field you specified to the old record that has the same key. So, if you just remove WHERE clause it should work. Check this article. It states the following two:
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;
are the same.

Update if row > 0 OR INSERT on Mysql

How to I can create a query for update, if select result is bigger then 0, else execute insert?
I had try execute this code, but is not work
select
case
where count(id) > 0 (update product set description = 'blablabla' where id_fk1 = 3 AND id_fk2 = 4)
else (insert into product (description) values('blablabla')
end
I know this is a select code, it will not work, but I don't know how to use If in mysql
you can use this example foreign-keys
there is a way to compose single query which compose single query with 'update ...' and 'insert into...'
or, if i misunderstood you, you can use this one insert-on-duplucate
What you need is INSERT with ON DUPLICATE KEY UPDATE clause:
https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
This has been asked before:
Insert into a MySQL table or update if exists
Contains many interesting answers.
Presumably, you want to insert the paid id = 3, description = 'blablabla' into the table. If it exists, then update the description.
You can use insert . . . on duplicate key insert, assuming that id is declared as the primary key or as a unique key. You would do this as:
create unique key product_id on product(id);
Then the following statement does what you want:
insert into product(id, description)
select 3, 'blablabla'
on duplicate key insert description = values(description);
EDIT:
I think the same idea applies to two foreign keys:
create unique key product_fk1_fk2 on product(id_fk1, id_fk2);
insert into product(id_fk1, id_fk2, description)
select 3, 4, 'blablabla'
on duplicate key insert description = values(description);
It will be base on the number of your query result, right?
$result=mysqli_query($con,"SELECT * FROM product");
if(mysqli_num_rows($result)==0){
mysqli_query($con,"INSERT INTO product (description) VALUES ('blah')");
}
else {
mysqli_query($con,"UPDATE product SET description='blah'");
}
If you're trying to base it on your id field, try this:
$result=mysqli_query($con,"SELECT * FROM product");
if(mysqli_num_rows($result)==0){
mysqli_query($con,"INSERT INTO product (description) VALUES ('blah')");
}
else
while($row=mysqli_fetch_array($result)){
$id=$row['id'];
if($id>0){
mysqli_query($con,"UPDATE product SET description='blah' WHERE id='$id'");
}
} /* END OF WHILE LOOP */
} /* END OF ELSE */

How to make insert or delete?

Structure table:
id (int primary key)
name (varchar 100)
date(datetime)
For insert I use query:
INSERT INTO table (name, date) VALUES ('t1','$date');
For delete row I use query:
DELETE FROM table WHERE name = 't1';
I would like want how make 1 query: first insert, if row with it name already exist, than delete row, and insert again.
Tell me please how to make it?
Create a UNIQUE index over your name column:
ALTER TABLE `table` ADD UNIQUE (name);
If you genuinely want to "delete row and insert again", then you can use REPLACE instead of INSERT. As documented:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.
Therefore, in your case:
REPLACE INTO `table` (name, date) VALUES ('t1','$date');
However, if instead of deleting the existing record and then inserting a new one you merely want to update the existing record, you can use INSERT ... ON DUPLICATE KEY UPDATE:
INSERT INTO `table` (name, date) VALUES ('t1','$date')
ON DUPLICATE KEY UPDATE date = VALUES(date);
The most material difference is in the treatment of columns for which you do not provide explicit values (such as id in your example): REPLACE will result in the new record having the default value, whereas INSERT ... ON DUPLICATE KEY UPDATE will result in the old value being retained.
What you want to do is use MySQL's on duplicate update feature.
Can be used like this :
INSERT INTO table (name, date) VALUES ('t1','$date')
ON DUPLICATE KEY UPDATE name=VALUES(name),dateVALUES(date);
Of course for that to happen a dupliate violation must occur.
insert into table (name, date) values('t1','$date') on duplicate key update name=values(name), date=values(date)
Are you looking for an update query?
Update will set a value on an already existing row.
UPDATE table SET date = '$newdate' WHERE name = 't1';
The best way to do this is using the mysql methods together with your query.
If you make the 'name' field unique:
id (int primary key)
name (varchar 100) NOT NULL UNIQUE
date(datetime)
And alter the query to:
INSERT INTO table
(name, date) VALUES ('t1','$date')
ON DUPLICATE KEY UPDATE date = "$date"

Combine two queries to check for duplicates in MySQL?

I have a table that looks like this:
Number | Name
--------+--------
123 | Robert
This is what I want to do:
If the Number is already in the database, don't insert a new record.
If the Number is not in the databse, but the name is, create a new name and insert it. So for example, if I have a record that contains 123 for Number and Bob for Name, I don't want to insert it, but if I get a record that contains 456 for Number and Robert for name, I would insert 456 and Robert1. I was going to check for duplicates individually like:
SELECT * FROM Person where Number = 123;
//If number is not found
SELECT * FROM Person where Name = 'Robert';
//If name is found, add a number to it.
Is there a way I can combine the two statements?
There are actually two problems in your question. The first problem is to make Number column unique and the second one is to increment the column Name by appending a number if it already exists.
FIRST PART
Since the number is UNIQUE, enforce a UNIQUE constraint on the column. It could be a PRIMARY KEY or a UNIQUE KEY.
If the column has no KEY and you want to make it PRIMARY, here is the ALTER statement:
ALTER TABLE TableName ADD CONSTRAINT tb_pk PRIMARY KEY (Number)
SQLFiddle Demo
but if you only want it to be UNIQUE and not a primary key,
ALTER TABLE TableName ADD CONSTRAINT tb_uq UNIQUE (Number)
SQLFiddle Demo
SECOND PART
You can actually do it without using join.
INSERT INTO TableName(Number, Name)
SELECT 124 AS Number,
CONCAT('Robert', COALESCE(MAX(CAST(REPLACE(Name, 'Robert', '0') AS UNSIGNED)) + 1,'')) AS Name
FROM TableName
WHERE Name LIKE 'Robert%'
SQLFiddle Demo
SQLFiddle Demo (added more example)
SQLFiddle Demo (throws exception due to uniqueness)
Some details:
when the value supplied on column Number already exists, it will throw an error since the column is unique. I have read a comment from a deleted posts saying: "..Number is not unique, but if it does exist, I don't want to enter a record." -- it does not make any sense if you don't want to add uniqueness on the column. How will you know if the number already exists or not? Doing a little check for the existence of Number feels like a little overhead for me. So my best recommendation is to enforce uniqueness.
SELECT * FROM Person WHERE Number = 123 OR Name = 'Robert'
I haven't worked with SQL for some time, so this may be wrong ;)
Edit:
$number = 123;
$name = 'Robert';
$query = mysql_query("SELECT * FROM Person WHERE Number = $number OR Name = '$name' ");
if (mysql_num_rows($query) == 0 ) {
//-> Add your record, it's unused
} else if (mysql_result($query, 0, 'number') == $number && mysql_result($query, 0, 'name' == $name)) {
//combination of number and name already exists -> modify name and add record
} else {
echo "Number is used by another name";
}
Use this query, for insert the row [123, 'Robert']. if you want insert other values, change 123 & Robert values in below query:
insert into Person (Number,Name)
select 123, IF(mn.MaxNumber is NULL,'Robert',concat('Robert',mn.MaxNumber+1))
from (SELECT 'foo') foo
left JOIN (select max(CONVERT(SUBSTR(Name,LENGTH('Robert')+1),UNSIGNED)) `MaxNumber`
from person where name rlike '^Robert[0-9]*$') mn on 1=1
where Not Exists (select * from Person where Number=123)
NOTE: if Robert exists in the table, above query inserts Robert1. if Robert1 exists, it inserts Robert2, and so on .
make both number and name unique.
ALTER TABLE `person` ADD UNIQUE (`number` ,`name`);
You can now do a insert with ON DUPLICATE
INSERT INTO `person` (`number`, `name`, `id`) VALUES ('322', 'robert', 'NULL') ON DUPLICATE KEY UPDATE `id`='NULL';
For appending a number after name i would suggest using autoincrement column instead.
insert into Person (Number,Name)
select 123, IF(mn.MaxNumber is NULL,'Robert',concat('Robert',mn.MaxNumber+1))
from (SELECT 'foo') foo
left JOIN (select max(CONVERT(SUBSTR(Name,LENGTH('Robert')+1),UNSIGNED)) `MaxNumber`
from person where name rlike '^Robert[0-9]*$') mn on true
where Not Exists (select * from Person where Number=123)