$sql = "INSERT IGNORE INTO product (reference, description, price, created_at, updated_at)
VALUES ('{$sku}', '{$description}', '{$price}', '{$created_at}', '{$updated_at}')";
.. keeps on creating new rows because of the incrementing id column, how do I make SKU unique so it checks if SKU value exists, then UPDATE instead of INSERT.
Add a unique key on the column you don't want to allow duplicates of:
ALTER TABLE product ADD UNIQUE KEY (reference);
Once you've done this, you can use the ON DUPLICATE KEY UPDATE clause to update the row instead of ignoring the INSERT.
INSERT INTO product (reference, description, price, created_at, updated_at)
VALUES ('{$sku}', '{$description}', '{$price}', '{$created_at}', '{$updated_at}')
ON DUPLICATE KEY UPDATE
description = VALUES(description),
price = VALUES(price),
created_at = VALUES(created_at),
updated_at = VALUES(updated_at)
Using VALUES in the ON DUPLICATE KEY clause picks up the values that would have been assigned during an INSERT of a new row.
Related
INSERT INTO policy_consent_status (patien_ID,policy_ID,PS_ID)
VALUES
((SELECT patient_ID FROM patient WHERE first_name="Christine"),(SELECT policy_ID
FROM policy WHERE policy_name="PI"),6)
ON DUPLICATE KEY
UPDATE
patien_ID = VALUES((SELECT patient_ID FROM patient WHERE first_name="Christine")),
policy_ID = VALUES((SELECT policy_ID FROM policy WHERE policy_name="PI"))
PS_ID = 6
I have to insert on new and update on existing
In ON DUPLICATE KEY UPDATE, the argument to VALUES has to be the name of a column; it returns the value that would have been inserted into the new row. If you want to use some other value, just put the expression there, without VALUES.
But you don't need multiple subqueries. Use a SELECT query as the source of the values to insert.
Also, you don't need to assign the values of the columns that are part of the unique key, only the columns that you want to update. I assume in your table the unique key is the combination of patient_id and policy_id.
INSERT INTO policy_consent_status (patient_ID,policy_ID,PS_ID)
SELECT patient_id, policy_id, 6
FROM patient
CROSS JOIN policy
WHERE first_name="Christine"
AND policy_name="PI"
ON DUPLICATE KEY UPDATE PS_ID = VALUES(PS_ID)
Executing the query for the first time is working fine for inserting multiple column records but ON DUPLICATE KEY UPDATE is not working for the same records if that query is executed again. It inserts the same value again.
** First value '2' is the primary key auto-incremental **
INSERT INTO info(id, docid, deptid, catid, name)
VALUES (2,5,2,2,'John Adison')
ON DUPLICATE KEY UPDATE docid = concat(docid,',',5), deptid = concat(deptid,',',2), catid = concat(catid,',',2);
the output should be unchanged if it gets same records from all column.
if your intention is to ignore insert (dont make update) when duplicate key found then you can use IGNORE
INSERT IGNORE INTO my_table
( unique_index_column, other_column ) VALUES( 1, 'other value' );
but this has downside that ignores all insert errors. Alternatively you can use
INSERT INTO table_tags (id, docid, deptid, catid, name) VALUES (2,5,2,2,'John Adison')
ON DUPLICATE KEY UPDATE name=name;
I'm reading about conditional updates on duplicate key based on IF statements - e.g., MySQL Conditional Insert on Duplicate.
I'm trying to do something similar, but within an insert from a select:
INSERT IGNORE INTO data1 (id, date, quantity)
SELECT id, date, quantity
FROM other_table
WHERE date = '2015-03-01'
AND id=123
ON DUPLICATE KEY UPDATE
quantity = IF(quantity IS NULL, VALUES(quantity), quantity)
However, this generates an error:
#1052 - Column 'quantity' in field list is ambiguous
I can't quite figure out how to tell MySQL which 'quantity' field is which in order to resolve the ambiguity problem. Adding aliases to each table doesn't seem to help (calling data1 'd' throws a different error).
Anyone have experience with this?
You should qualify the references to the quantity field that belongs to table data1 in the ON DUPLICATE KEY UPDATE part of the query:
INSERT INTO data1 (id, date, quantity)
SELECT id, date, quantity
FROM other_table
WHERE date = '2015-03-01'
AND id=123
ON DUPLICATE KEY UPDATE
quantity = IF(data1.quantity IS NULL, VALUES(quantity), data1.quantity)
A shorter way to write this IF() expression is to use function IFNULL() or COALESCE():
ON DUPLICATE KEY UPDATE
quantity = IFNULL(data1.quantity, VALUES(quantity))
or
ON DUPLICATE KEY UPDATE
quantity = COALESCE(data1.quantity, VALUES(quantity))
Also, there is no need to use IGNORE. The errors that IGNORE converts to warnings does not happen any more because of the ON DUPLICATE KEY UPDATE clause.
mySQL doesn't know to which quantity collumn you are referring since it is present in both data1 and other_table tables.
You have to use it like this: other_table.quantity
Your query will change like this
INSERT IGNORE INTO data1 (id, date, quantity)
SELECT id, date, quantity
FROM other_table
WHERE date = '2015-03-01'
AND id=123
ON DUPLICATE KEY UPDATE
data1.quantity = IF(other_table.quantity IS NULL,
VALUES(other_table.quantity), other_table.quantity)
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"
INSERT INTO options (owner, name, value, modified)
SELECT owner, name, value, modified, #draft:=draft FROM
(
...
) `options`
ON DUPLICATE KEY UPDATE value=VALUES(value), modified=#draft
Above will error with column count doesn't match row count.
Is there a way I can SELECT a column into #draft without it being included as part of the inserts values but so it's usable in the DUPLICATE KEY UPDATE?
As stated in the manual:
In the values part of ON DUPLICATE KEY UPDATE, you can refer to columns in other tables, as long as you do not use GROUP BY in the SELECT part. One side effect is that you must qualify nonunique column names in the values part.
Therefore, you could do:
INSERT INTO options (owner, name, value, modified)
SELECT owner, name, value, modified FROM ( ... ) options2
ON DUPLICATE KEY UPDATE value=VALUES(value), modified=options2.draft
See it on sqlfiddle.