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

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.

Related

MySQL check 2 values already exists before insert

My columns are like this. column "a" is primary and auto incremantal.
a | b | x | y
When inserting new data, i need to check x and y columns shouldn't be exist together.
To clarify, imagine this row is at database with these values
(2, "example.com" , "admin", "123456")
I should able to insert both of these columns
(3, "example.com" , "user", "123456")
(4, "example2.com" , "admin", "123456")
But i shouldn't able to insert this column
(5, "example.com" , "admin", "5555555")
Because "example.com" and "admin" values already in database on a row. It doesn't matter column "y" is same or not.
How can i do this?
Create a composite unique index. This will allow any number of duplicates in the individual fields, but the combination needs to be unique.
CREATE UNIQUE INDEX ix_uq ON tablename (b, x);
...and use INSERT IGNORE to insert if the unique index is not violated. If it is, just ignore the insert.
INSERT IGNORE INTO test (a,b,x,y) VALUES (5, "example.com" , "admin", "5555555");
If you want to insert unless there's a duplicate, and update if there is, you can also use INSERT INTO ... ON DUPLICATE KEY UPDATE;
Ref: MySQL only insert new row if combination of columns (which allow duplicates) is unique
You want to let the database do the work. Although you can set up a condition within a query, that condition may not be universally true or someone might use another query.
The database can check this with a unique constraint or index. Actually, the unique constraint is implementing using a unique index:
create unique index unq_t_b_x on t(b, x);
(The columns can be in either order.)
The insert would then look like:
insert into t(b, x, y)
values ('example.com', 'admin', '5555555')
on duplicate key update b = values(b);
Note that the auto-incremented value is not included in the update.
The on duplicate key update just prevents the insert from generating an error. It is better than insert ignore because the latter will ignore all errors, and you just want to ignore the one caused by the duplicate key.

MySQL on duplicate key... get existing ID?

I'm using ON DUPLICATE KEY UPDATE to handle duplicate inserts on a table, in order that they are discarded.
In my case it's a simple table storing tags:
id (int, PK, AI, unsigned, not null)
tag (varchar 25, not null, unique)
This is working fine, but I need to retrieve the ID - either the insert ID, on successful insert, or the existing ID, if it's a duplicate.
I'm getting insert ID = 0 where ON DUPLICATE KEY UPDATE fires, which I guess is expected behaviour since no insert took place.
Is there anyway I can get the existing ID, or am I headed to a separate read query?
You could add a third column ModifiedDate and use that:
insert into t(id, tag)
select id, tag
on duplicate key update ModifiedDate = now();
This will ensure that an update really occurs, and in turn, that LAST_INSERT_ID() returns a value.

MySQL - insert into statement requires me to enter primary key

I'm pretty much a complete newbie to SQL, I'm using MySQL with SQLyog. I have five fields, StudentForename, StudentSurname, StudentAge, StudentHouse and StudentID for the Primary Key. The StudentID field is set as a Primary Key and Not Null and AutoIncrement. I'm trying to use an INSERT INTO statement without having to entering the primary key - apparently I shouldn't need to, it should update itself. But it's not working, it's returning the error "Column count doesn't match value count at row 1". Here's the code I'm using. I've already set up the table, so I haven't got the code for the query that
INSERT INTO students VALUES('Harry', 'Potter', 'Slytherin', 30)
You will need to explicitly state which columns you will provide values for, otherwise it is assumed you will provide values for all columns. E.g.
INSERT INTO students (`first_name`, `last_name`, `house`, `age`) VALUES('Harry', 'Potter', 'Slytherin', 30)
(I made up column names, swap these with your columns)

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.

MySQL: INSERT IGNORE or ON DUPLICATE KEY UPDATE with checking multiple and not unique columns

i want to insert rows IF a row containing the specific values exists, and if not update it.
Concretely:
A column user_id=5, user_zip=12345, distance=600 exists on the database.
If i try to insert user_id=5, user_zip=12345, distance=700 it should just update the distance
but i try to insert user_id=5, user_zip=67890, distance=800 it should insert a new row.
I can't define the columns user_zip and distance unique, so that i can use the on duplicate key update.
I think you are misunderstanding how ON DUPLICATE KEY UPDATE works. With a unique constraint on (user_id, user_zip), this should work:
INSERT INTO yourTable (user_id, user_zip, distance) VALUES (5,12345,600)
ON DUPLICATE KEY UPDATE distance=600;
You don't have to define user_zip unique (that's how I understand your question), just the combination of user_id and user_zip. So you still can have 2 or more rows with the same user_id, just the user_zip can't match on those rows.