ON DUPLICATE KEY UPDATE ... with WHERE or subselection? - mysql

i am a bit concerned about one of my mysql queries... The following query receives a variable $DB_id... if a row with that primary key already exists the query performs an update.
$this->db->query(" INSERT INTO modules_text
( module_id,
module_content,
module_index
)
VALUES ( '{$DB_id}',
'{$content['text']}',
'{$index}'
)
ON DUPLICATE KEY
UPDATE module_content = '{$content['text']}',
module_index = '{$index}'
");
NOW THE THING THAT CONCERNS ME... There is no relation if the affected rows actually belong to the user. I would like to add a where statement to the UPDATE part or first make a subselecion of the rows which are permitted to be affected. SOmething like:
[...]
ON DUPLICATE KEY
UPDATE module_content = '{$content['text']}',
module_index = '{$index}'
WHERE module_post_id = '{$post]}'
Is this somehow possible... Until now i didnt find a solution... Any help would be very appreciated... THANKS A LOT!!!!!
Saludos Sacha!

This isn't how ON DUPLICATE KEY works. The update portion of the INSERT will only occur if there's a match for the UNIQUE key(s) or PRIMARY key for the table. (i.e.: The UNIQUE/PRIMARY key(s) are effectively the WHERE clause.)
See the full MySQL docs for more information.

Related

mysql - INSERT... ON DUPLICATE KEY UPDATE, but not really...?

Hi I've been trying to get this to work, I thought I had it with mysql - INSERT... ON DUPLICATE KEY UPDATE, but no luck.
I have a table as such:
sessionID is unique,
productID references another table and is not unique, but not common, should be a max of 3 rows containing the same value,
sessionType is either 1, 2 or 3, and would link with productID,
I need to check if the table has a row where there is a matching pair of productID and sessionType, if there is then sessionDate & sessionCapacity in that row should be UPDATED, if there isn't then a new row inserted.
$vals = array($pID,$data['pSessionDate'],'1',$data['pQty'],$pID,$data['pSessionDate'],'1',$data['pQty']);
$db->Execute("INSERT INTO VividStoreSessions (pID,sDate,sType,sCapacity) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE pID=?,sDate=?,sType=?,sCapacity=?",$vals);
Hope that makes sense to someone and thanks in advance for any help!
Your insert looks valid. But, first you need a unique index/constraint:
create unique index unq_VividStoreSessions_productId_sessionType
on VividStoreSessions, productId, sessionType)
Then you can write the code to only use four parameters:
INSERT INTO VividStoreSessions (pID, sDate, sType, sCapacity)
VALUES (? ,?, ?, ?)
ON DUPLICATE KEY UPDATE sDate = VALUES(sDate), Capacity = VALUES(Capacity);
Finally, you need to ensure that sType only takes on the values of 1, 2, or 3. Perhaps you want to enforce this at the application layer. Otherwise, you need a trigger or foreign key constraint to ensure that there are only three rows.

Strategies for preventing the insertion of duplicate table rows

Scenario:
User A and B executes at the same time select id from Product where id = ?, if the there are no results, both create a new product with given ID.
Problem:
This could lead to the creation of duplicate rows.
Question:
What are the possibles strategies to prevent that? I know that I can use compound/unique keys, to guarantee this, but are there any other strategies? Is there any SQL statement to lock query with same parameters?
You can use unique constraints
ALTER TABLE Persons ADD UNIQUE (P_Id)
or
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
That way it would be impossible for a duplicate to be inserted.
Put a UNIQUE key on the field in question:
https://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html

Duplicate Key Entry on Update query MySQL

UPDATE Table1, Table2
SET Table1.Col1 = 1, Table1.Col2 = 2, Table2.Col1 = 3
WHERE Table1.PKey = Table2.PKey AND Table1.PKey = 199
results in duplicate key entry
#1062 - Duplicate entry '199-1' for key 'PRIMARY'
please help i've been scratching my head. I want this query to be optimal and fast since its used inside a loop that loops through a lot of rows and updates for each one. Dont want to split into 2 queries since then it will be 2 separate query calls per row.
Your query above should work -- reference:
https://stackoverflow.com/a/9417254/1073631
Guessing that you're trying to update a primary key (unique) column with a value that is already in another row in that same table --- hence the duplicate entry error.
I think the primary key for your Table1 is on PKey AND Col1, i.e.
CREATE TABLE `Table1`
...
PRIMARY KEY (`PKey`,`Col1`)
The error about the duplicate entry '199-1' points in that direction.

How to delete rows from table sql

I want to delete specific rows from 8 tables.
My problem is that the rows are connected with foreign key.
How can I delete all the data that connected to the specific rows that I want to delete?
My tables include definition tables (like id, name ,max value, min value...),
data tables (like id, user_id, definition_id,....) and history tables (save every change in data table).
I thought to use delete on cascade command but I could not find a way to use it.
DELETE CASCADE is an attribute of the foreign key constraint. Unfortunately it's not something you can use as an option with a DELETE statement (which would be really cool actually)
If your foreign keys have not been declared as cascading you need to "work your way up".
Unfortunately you did not show us your real table structure so let's assume something like this:
main_table (main_id)
child_one (id, main_id)
child_two (id, id_one)
child_three (id, id_two)
(I know you said 8 tables, but for the sake of the demonstration I shortened it a bit, but that doesn't change the underlying "strategy")
Assuming you want to delete the row with main_id = 42 from `main_table:
You first need to delete the rows from child_three using something like this:
delete from child_three
where id_two in (select id
from child_two
where id_one in (select id
from child_one
where main_id = 42);
Then delete the rows from child_two:
delete from child_two
where id_one in (select id
from child_one
where main_id = 42);
Then child_one:
delete from child_one
where main_id = 42;
And finally the main table:
delete from main_table
where id = 42;
Some SQL clients can actually generate those statements for you. I don't know if SQL Developer can though.
I assume that you use InnoDB Engine, since you are talking about foreign keys,
Easier will be to define properly the table so that a deletion will act as a cascade deletion.
CONSTRAINT `myForeignKey` FOREIGN KEY (`typeId`)
REFERENCES `types` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
Here is alink with a proper create table statement:
How do I use on delete cascade in mysql?

MySQL: Advanced insert if not exists

I have a table with with essentially three columns: user_id, setting, and value. I'm trying to use the following code:
INSERT INTO 'user_settings'(user_id, setting, value)
VALUES (1234, setting_1, 500)
ON DUPLICATE KEY UPDATE user_id = 1234, setting = setting_1'
This works great when creating a new setting, and it doen't generate duplicate records. The problem comes when I want to change the value- this won't work after the previous query has run:
INSERT INTO 'user_settings'(user_id, setting, value)
VALUES (1234, setting_1, 999)
ON DUPLICATE KEY UPDATE user_id = 1234, setting = setting_1'
No rows are affected. Clearly I'm missing something...
IMPORTANT: I am not able to alter the database (new primary keys or something).
UPDATE: It seems my understanding of ON DUPLICATE KEY is wrong. But the question remains- what is the most efficient way way to accomplish this?
Answered in a comment below: "If the Primary (or Unique) key is (user_id, setting), then use: ... ON DUPLICATE KEY UPDATE value=999".
Assuming you actually have a unique key on user_id, you are getting "no rows affected" because you aren't changing anything in the second query. I think what you want to do is update the value field as well:
INSERT INTO 'user_settings'(user_id, setting, value)
VALUES (1234, setting_1, 999)
ON DUPLICATE KEY UPDATE setting = setting_1,value=999
Without value in there, you're just setting the user_id and the setting field to the same values they were before, and MySQL doesn't need to update the record.
If you don't have a unique key on user_id, you'll have to find a different approach, as the ON DUPLICATE KEY UPDATE won't trigger.