MySQL Update set Value only if flag = 0 - mysql

I have this Query:
INSERT INTO `items` (`id`,`image`)
VALUES(112,'asdf.jpg'),(113,'foobar.png')
ON DUPLICATE KEY UPDATE
`id`VALUES(`id`),
`image` = IF(image_uploaded = 0, VALUES(`image`),image);
The worse: its properly working but not as i want.
What i want: The images should only be updated if the field "image_uploaded" is set to 0.
Any ideas?
The Background: I have a DB-Table with data. Now each night a cronjob calls an API-Fn to get new Data from another DB and write it down to my table. This function is getting all items from the second DB so its currently just overwriting my existing data. Now my Application allows changes on data i got from the 2nd DB and overwrites the changes in my own Table. So the Problem is: I need the ability to edit Data via my App AND update Data via API without colliding. The User may change the "image" but all other things should be updated from the 2nd DB. The Image should only be overwritten if it wasn't uploaded manually.

Without playing around with ON DUPLICATE KEY... I'm not sure, if it can handle this situation. I'd work around it by using another (temporary) table.
It's the same structure as your target_table plus a column (in the example sid) to indicate if the entry exists in your target_table or not.
CREATE TEMPORARY TABLE tmp_whatever (
sid int,
id int, image varchar(50)
);
Now we insert the data you want to insert into your target_table into the newly created table first and check with coalesce() and left joining, if the entry already exists. I'm assuming here, that id is your primary key.
INSERT INTO tmp_whatever (sid, id, image)
SELECT
COALESCE(t.id, 0),
id, image
FROM (
SELECT 112 AS id,'asdf.jpg' AS image
UNION ALL
SELECT 113,'foobar.png'
) your_values v
LEFT JOIN your_target_table t ON v.id = t.id;
Then we update the target_table...
UPDATE your_target_table t INNER JOIN tmp_whatever w ON t.id = w.id AND w.sid <> 0
SET t.image = w.image
WHERE t.image_uploaded = 0;
And finally we insert the rows not already existing...
INSERT INTO your_target_table (id, image)
SELECT
id, image
FROM tmp_whatever
WHERE sid = 0;
While I was writing this down, it came to my mind, that I might have had wrong assumptions on what your problem is. This
The worse: its properly working but not as i want.
is definitely not the way to ask a question or describe a problem. I answered because I have a good day :) (and it's the reason why you get downvotes, btw)
Anyway, another cause of "not as i want" could be, that you're missing a unique index in your table. Though a primary key is a unique key, afaik/iirc ON DUPLICATE KEY relies on a unique index on another column to work correctly.

Related

insert into select with external key reference

INSERT INTO trees (preview)
select galleries.preview
from galleries,trees
where trees.id=galleries.idTree;
I am trying to move a column from a table to another, I have set an empty column with the same data type as the original.
Where idTree is equal to id to the destination table (in the source table idTree is foreign key reference to id on trees that is the destination).
The "select" works and give me back the right set of values (at least ordered by id and all) but the insert into part, do nothings and the field on trees is still empty. what am I doing wrong ?
INSERT INTO.. will create a new row; but you are looking to update the existing rows in trees table which has id. Try with UPDATE query instead:
UPDATE trees
JOIN galleries ON galleries.idTree = trees.id
SET trees.preview = galleries.preview

Mysql, Insert new record into table B if foreign key exists in table A

There are a few similar questions on here. None provide a solution. I would like to INSERT a NEW record into table B, but only if a foreign key exists in table A. To be clear, I do not wish to insert the result of a select. I just need to know that the foreign key exists.
INSERT INTO tableB (tableA_ID,code,notes,created) VALUES ('24','1','test',NOW())
SELECT tableA_ID FROM tableA WHERE tableA_ID='24' AND owner_ID='9'
Clearly, the above does not work. But is this even possible? I want to insert the NEW data into tableB, only if the record for the row in tableA exists and belongs to owner_ID.
The queries I have seen so far relate to INSERTING the results from the SELECT query - I do not wish to do that.
Try this:
INSERT INTO tableB (tableA_ID,code,notes,created)
SELECT id, code, notes, created
FROM ( SELECT '24' as id, '1' as code, 'test' as notes, NOW() as created) t
WHERE EXISTS
(
SELECT tableA_ID
FROM tableA
WHERE tableA_ID='24' AND owner_ID='9'
)
I know it's a pretty much old answered question but it's highly ranked now in google search results and I think some addition may help someone in the future.
In some DB configuration, you may want to insert a row in a table that have two or more foreign keys. Let's say we have four tables in a chat application :
Users, Threads, Thread_Users and Messages
If we want a User to join a Thread we'll want to insert a row in Thread_Users in wich have two foreign keys : user_id, thread_id.
Then, we can use a query like this, to insert if both foreign keys exists, and silently fail otherwise :
INSERT INTO `thread_users` (thread_id,user_id,status,creation_date)
SELECT 2,3,'pending',1601465161690 FROM (SELECT 1 as nb_threads, 1 as nb_users) as tmp
WHERE tmp.nb_threads = (SELECT count(*) FROM `threads` WHERE threads.id = 2)
AND tmp.nb_users = (SELECT count(*) FROM `users` WHERE users.id = 3)
It's a little verbose but it does the job pretty well.
Application-side, we just have to raise an error if affectedRows = 0 and maybe trying to see which of the keys doesn'nt exists. IMHO, it's a better way to do the job than to execute two SELECT queries and THEN execute the INSERT especially when an inexistent foreign key probability is very low.

Issues with MySQL inserting columns below desired location

I have been having some frustration attempting to add data values to this table students. I have all the other data values and have dropped and created the column student_id. However, when trying to add the data with this query:
insert into students(student_id) values('1'),('2'),('3'),('4'),('5');
The data does not insert correctly, as it creates new columns below the first 5 which contain data.
It must be because of my not null values, but I can't not have the not null identifier.
Is there a query command that allows me to change data within already existing value-filled columns? I have been unsuccessful in finding this so far.
Here are some images to explain the problem further.
The query I have made to add my values to the table:
The data was inserted but as it is underneath the columns I need to map with a foreign key, I cannot use the column as the top 5 values are still my not null default, which is required to let me create the foreign key
Looks like you already have your records initially created without the student_id field, you want to UPDATE the current records but you're actually INSERTING new records.
You're meant to update your students with update statements such as "UPDATE students SET student_id = X where condition = Y"
Then it looks like your student_id is your primary key which you should set to AUTO_INCREMENT value.
Regards
INSERT is the wrong command since you want to update existing rows. The problem here lies within the fact that the order of the rows is nondeterministic and I think you cannot update them in one statement. One solution would be as follows:
UPDATE students SET student_id = 1 WHERE first_name = 'Berry';
UPDATE students SET student_id = 2 WHERE first_name = 'Darren';
I hope you really do have only 5 columns to update :-)

Change tracking in sql server 2008, senseless delete operations

I am currently testing change tracking mechanism in sql server 2008 and noticed something:
When to the base table (change tracked) I insert a new record and delete it using the same
key, select with the changes returns to me the information that it should be deleted in the remote table however that record doesn't exist at all in that table ..
Why is it functioning that way?
SAMPLE CODE:
CREATE TABLE TEST (
ID UNIQUEIDENTIFIER primary key,
value int
)
ALTER TABLE [dbo].Test
ENABLE CHANGE_TRACKING
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SELECT CT.SYS_CHANGE_OPERATION, CT.ID, IV.value
FROM CHANGETABLE(CHANGES TEST, 51374) CT
LEFT JOIN TEST IV ON IV.ID = CT.ID
--zero changes now for: 51374
insert into Test VALUES ('54C1D80E-ACB0-433F-94DF-7D06FE809E22', 1)
delete from Test where id = '54C1D80E-ACB0-433F-94DF-7D06FE809E22'
select * from Test -- table is empty (insert and delete)
SELECT CT.SYS_CHANGE_OPERATION, CT.ID, IV.value
FROM CHANGETABLE(CHANGES TEST, 51374) CT
LEFT JOIN TEST IV ON IV.ID = CT.ID
--however for Anchor: 51374 it claims I should delete the record ...
My base and the remote table were in sync at 51374 anchor.
Adding and deleting the record shouldn't give me the info for deleting
of something I don't have in my remote table ...
I think Damien's answer is right. Not sure why he answered in a comment.
It's all there in the documentation, really "Only the fact that a row
has changed is required, not how many times the row has changed or the
values of any intermediate changes.", "If an application requires
information about all the changes that were made and the intermediate
values of the changed data, using change data capture, instead of
change tracking."
Imagine if there's a row with ID 1 that you know about. Then in some
period, someone goes in and deletes that row, and then adds a new row
with the same ID. Change tracking will give you an insert, even though
you already knew about a row with ID 1 and haven't seen a delete. It's
the nature of the beast - you only get the last change, and you have
to reconcile that with your version of reality. If you see a Delete
for a row you don't know about, ignore it.

MySQL - Taking DISTINCT values from table A and turning into PRIMARY KEY on table B

Basically trying to fill a table with product codes from another table. The codes can be repeated in the Products table, as it has data about product sizes, however this value needs to be unique in ProductDescriptions.
I need there to be a new entry into the ProductDescriptions table every time there is a new DISTINCT product code in the Products table.
I've tried all sorts of things with no success, doesn't seem to that complex however its baffled me.
I have tried this:
INSERT INTO ProductDescriptionsbackup(ProductID) SELECT DISTINCT `PRODUCT CODE` FROM Products
However it doesn't run as it can't just take the DISTINCT values, and in the long run it doesn't update automatically, however that would be a secondary issue.
The main issue is getting the DISTINCT values into the ProductDescriptions table.
I've had a look around for answers but theres been nothing that stood out and made sense to me. Thanks in advance for any help received.
If you are only trying to insert new values, this should work. You could make a left join to the target table and only include records that don't exist (WHERE pbu.ProductID IS NULL).
INSERT INTO ProductDescriptionsbackup(ProductID)
SELECT DISTINCT p.`PRODUCT CODE`
FROM Products as p
LEFT JOIN ProductDescriptionsbackup as pbu
ON p.`PRODUCT CODE` = pbu.ProductID
WHERE pbu.ProductID IS NULL;
Lets break your question is two parts. First is to garanteee that ProductDescriptions is always updated when you insert a new row in the products, the second is how to insert the new values.
For the first part there are two option, you're responsible in the code to explicit insert the productdescription every time and everywhere you do a insert into the product table or you can create a trigger after insert to do that
create trigger ai_eav
after insert on eav
for each row
(...)
I recommend this second option so you won't forget to insert, but there are some folks that don't like triggers since they can become "invisible" to the programmer as they are usually forgotten.
For the second part, you can do a insert if not exists, which could be achieved by doing a insert with a left join
insert into ProductDescriptions(ProductID)
select distinct p.`PRODUCT CODE`
from Products
left join join ProductDescriptions on `PRODUCT CODE` = ProductID
where ProductID is null
if you opt for the trigger you can even take advantage of the pseudo row new and make the insert even faster since you'll be working with a single row, instead of working with the whole products table.