Changing first boolen that is false to true in postgreSQL table - postgresql

I have a table where all values of the column requested are false. I perform an action in python and want to update the first row where requested is false to true. So, after the first execution in python, the first row is set to true. After the second execution - since requested in the first row is now true - the second row is set to true and so on. My sql statement looks like this:
UPDATE timeframes SET requested = TRUE
WHERE requested = (
SELECT requested FROM timeframes
WHERE requested = FALSE
ORDER BY id
LIMIT 1);
This statement sets ALL the values in requested to true. I don't know why. If I execute the subquery as its own query, it only returns the first row. So in my opinion the update statement should therefore only set that specific row to true. Any idea as to why my statement doesn't work and how to improve it?
EDIT: Changing WHERE requested IN to WHERE id IN worked. The statement should look like this:
UPDATE timeframes SET requested = TRUE
WHERE id = (
SELECT id FROM timeframes
WHERE requested = FALSE
ORDER BY id
LIMIT 1);

your update executes ...
where requestet = false
to update only the first row with a unique id change your update statement to
UPDATE timeframes SET requested = TRUE
WHERE id = (
SELECT id FROM timeframes
WHERE requested = FALSE
ORDER BY id
LIMIT 1);
as written in the comments, by amadan, you can either use where id in, or better in this situation where id =

Related

Postresql update limited rows and return old values

I have table with logs and when they requested -> they change seen status to true. Problem is that i don't need to update rows that seen is already true, only return them. Is there a way to do it?
logs
id | seen
1 | false
2 | true
UPDATE logs as new
SET seen=true
FROM (SELECT * FROM logs WHERE seen is not null LIMIT 5) as old
WHERE new.id = old.id //if i add here "AND old.seen=false" then nothing will return
RETURNING old.seen
Your sub-query should be filtered for "unseen" records and there is no need to return all columns either:
(SELECT id FROM logs WHERE NOT seen LIMIT 5)
This will return the ids for up to 5 records in the log table that have seen equal to false.
The updated solution would look like this:
UPDATE logs
SET seen = true
FROM (SELECT id FROM logs WHERE NOT seen LIMIT 5) AS unseen
WHERE logs.id = unseen.id
RETURNING id; -- Returning `seen` would only return false. `id` is more useful, no?

SQL update statements updates wrong fields

I have the following code in Postgres
select op.url from identity.legal_entity le
join identity.profile op on le.legal_entity_id =op.legal_entity_id
where op.global_id = '8wyvr9wkd7kpg1n0q4klhkc4g'
which returns 1 row.
Then I try to update the url field with the following:
update identity.profile
set url = 'htpp:sam'
where identity.profile.url in (
select op.url from identity.legal_entity le
join identity.profile op on le.legal_entity_id =op.legal_entity_id
where global_id = '8wyvr9wkd7kpg1n0q4klhkc4g'
);
But the above ends up updating more than 1 row, actually all of the rows of the identity table.
I would assume since the first postgres statement returns one row, only one row at most can be updated, but I am getting the wrong effect where all of the rows are being updated. Why ?? Please help a nubie fix the above update statement.
Instead of using profile.url to identify the row you want to update, use the primary key. That is what it is there for.
So if the primary key column is called id, the statement could be modified to:
UPDATE identity.profile
SET ...
WHERE identity.profile.id IN (SELECT op.id FROM ...);
But you can do this much simpler in PostgreSQL with
UPDATE identity.profile op
SET url = 'htpp:sam'
FROM identity.legal_entity le
WHERE le.legal_entity_id = op.legal_entity_id
AND le.global_id = '8wyvr9wkd7kpg1n0q4klhkc4g';

Update columns based on subquery containing "select unnest" clause

I am attempting to update a boolean column in one table based upon the values in a second.
UPDATE channels
SET contains_photos = TRUE
WHERE id IN (SELECT unnest(ancestors)
FROM channel_tree WHERE id = 11329);
The channel_tree.ancestors column contains an array of channel IDs. The above is failing with the following error:
ERROR: cannot TRUNCATE "channel_tree" because it is being used by active queries in this session
The overriding goal is to set the contains_photos column to true for all ancestors of a given channel. Any one know how best to alleviate this error, or even an alternative solution?
No idea why your error says TRUNCATE. It sounds like you have a trigger or rule that is doing a truncate that we can't see.
Here's some alternative ways of doing that same query:
UPDATE channels
SET contains_photos = TRUE
WHERE id = ANY (SELECT ancestors
FROM channel_tree WHERE id = 11329);
Or with a join:
UPDATE channels
SET contains_photos = TRUE
FROM channel_tree
WHERE channels.id = ANY (channel_tree.ancestors)
AND channel_tree.id = 11329;

PostgreSQL: check if attribute is in table

I'm writing some triggers to check if an arrtibute of a newly create tuple is present in another table. What is the best way to check this?
IF (SELECT * FROM TABLEB where NEW.Attribute = Attribute) = NULL THEN
return NULL
END IF
Is there a better way? And does a Select that returns nothing = NULL or empty set?
Use IF EXISTS (SELECT * FROM TABLEB where NEW.Attribute = Attribute).
An empty rowset isn't the same as NULL, which represents an empty cell of a row. Your syntax would only be valid if the query only selected one row, in which case PostgreSQL will allow use of comparison operators against the top cell returned, which counts as NULL if none are returned.

SELECT and SET with ROWCOUNT

I have a SP with which I fetch a defined amount of rows. How can I change the value of a column in the fetched rows? Such as 'has been fetched' = 1.
Any advice?
EDIT:
The SP looks something like this
SET ROWCOUNT #numberOfRows
SELECT * FROM tableA where notSent = 1
I would like to change the 'notSent' colum for all the rows that i fetch. Is this possible?
1) Don't use Select * in a stored procedure - always specifically list the fields required as shown below - replace field1,2,3 etc with the actual fields you want returned.
OK - Modified answer:
2) Set a flag on the columns you want to select and update with a value that will not be otherwise programmatically set - e.g. -1 - Then select these records, then update them to set the final value required. Doing it this way will avoid the possibility that you will update a different set of records to those selected, due to inserts occurring half-way through the stored procedure's execution. You could also avoid this by use of locks, but the way below is going to be far healthier.
UPDATE Table set notSent = -1 WHERE notSent = 0
SELECT ... from Table where notSent = -1
UPDATE Table set notSent = 1 where notSent = -1