I am using Postgres 9.6 and I have a JSONB column in which some rows have NULL value and some have dict values like {"notify": false}.
I want to update the column values with more dictionary key/value pairs.
UPDATE accounts SET notifications = jsonb_set(notifications, '{"alerts"}', 'false');
Does work for the cases where I already have values like {"notify": false}. The end result becomes as expected {"alerts": false, "notifications": false}.
But the value I'm trying to update us NULL, nothing is updated in the db.
Can you give me any ideas how I can update the NULL values as well, so the end result for them will be values like {"notify": false}. The end result becomes as expected {"alerts": false}
Use coalesce():
UPDATE accounts
SET notifications = jsonb_set(coalesce(notifications, '{}'), '{"alerts"}', 'false')
or even simpler:
UPDATE accounts
SET notifications = coalesce(notifications, '{}') || '{"alerts": false}'
Note that some versions of Postgres have coalesce() functions that don't support jsonb, and will give an error like this when trying to use the accepted answer:
ERROR: function coalsece(jsonb, unknown) does not exist
You can work around that by using a case statement instead. Ugly, but it works.
UPDATE accounts
SET notifications =
jsonb_set(
case
when notifications is null then '{}'
else notifications
end,
'{"alerts"}','false')
Related
I created a field name is result and type is text. I just want to update 'lat' in column. When I use this query I get syntax error. How can I do?
The column data is
"{"lat":"48.00855","lng":"58.97342","referer":"https:\/\/abc.com\/index.php"}"
Query is
update public.log set (result::json)->>'lat'=123 where id=6848202
Syntax error is
ERROR: syntax error at or near "::"
Use the jsonb concatenation operator (Postgres 9.5+):
update log
set result = result::jsonb || '{"lat":"123"}'
where id = 6848202
In Postgres 9.4 use json_each() and json_object_agg() (because jsonb_object_agg() does not exists in 9.4).
update log
set result = (
select json_object_agg(key, case key when 'lat' then '123' else value end)
from json_each(result)
)
where id = 6848202
Both solutions assume that the json column is not null. If it does not contain the lat key, the first query will create it but the second will not.
In PostgreSQL 13, You can:
update public.log set result = jsonb_set(result,'{lat}','"123"') where id=6848202;
In case the column is still null, you can use coalesce. The answer is provided here: PostgreSQL 9.5 - update doesn't work when merging NULL with JSON
I also tried to update json value in json type field, but couldn't find appropriate example. So I've connected to postgres DB using PgAdmin4, opened desired table and changed desired field's value, then looked at Query History to see what command it uses to change it.
So, finally, I've got the next simple python code for own purposes to update json field in postgres db:
import psycopg2
conn = psycopg2.connect(host='localhost', dbname='mydbname', user='myusername', password='mypass', port='5432')
cur = conn.cursor()
cur.execute("UPDATE public.mytable SET options = '{\"credentials\": \"required\", \"users\": [{\"name\": \"user1\", \"type\": \"string\"}]}'::json WHERE id = 8;")
cur.execute("COMMIT")
Address Table with 50 records. Has a bool field called "primary_address_indicator".
I want to update a selected record to true and automatically set all other 49 records to false.
I know I can do this with 2 sql statements
First (update all records to false)
UPDATE address SET address.primary_address_indicator=0
Then (update specific record to true)
UPDATE address SET address.primary_address_indicator=1 WHERE address.record_id=31
Is there a way to do this in a single sql statement? Something like #Rank?
Keeping it simple... no Unions or some weird self table join.
Maybe what I am looking for does not exist...and that is fine too. just curious.
Update with Case
UPDATE tableName
SET Pin = CASE
WHEN 1=1 --'your condition'
THEN True
ELSE False
END
PC : #keWalker
The simplest way is simply to treat the boolean result as a number:
UPDATE address a
SET a.primary_address_indicator = (a.record_id = 31);
CASE is the formal way to do it. This short-hand is specific to MySQL but it is one of the database-specific features that I like.
To summarize, I have an update query that will tack on a string of data (e.g. SAVE15) to an existing field. Currently, I anticipate this field to already have some information in it so my values are appending as ", SAVE15" which is a comma and space separator. This works for now but soon I anticipate the need to insert a comma and space only if the field is NOT NULL. If it is null, I need it to insert "SAVE15". Here is my current query:
UPDATE sales_flat_order sfo
INNER JOIN sales_flat_order_grid sfog
ON sfog.entity_id = sfo.entity_id
SET sfo.coupon_code = concat(IFNULL(sfo.coupon_code, ""),", SAVE15")
WHERE sfog.increment_id = "12345678";
Here is my attempt to use CONCAT_WS to add a separator ony when necessary:
UPDATE sales_flat_order sfo
INNER JOIN sales_flat_order_grid sfog
ON sfog.entity_id = sfo.entity_id
SET sfo.coupon_code = CONCAT_WS(',',IFNULL(sfo.coupon_code, ""),"SAVE15")
WHERE sfog.increment_id = "12345678";
I thought it was working at first but then it inserted ",SAVE15" onto a null field. I believe the second query is the correct method but I seem to be using it incorrectly.
The documentation for Concat_WS tell us that it will skip any Null field but not an empty string. You must therefore remove the call to IfNull(sfo.coupon_code, "") that convert the Null value into an empty string.
I am using an UPDATE query to update multiple rows which is something like the following
UPDATE TBLNAME SET NEWCOLUMN =
CASE
WHEN TYPE='ACCOUNT' THEN 'FINANCE'
WHEN CODE='DATA' AND CLASS='FIRST' THEN 'LEGAL'
END
The above query works fine for single conditions and for certain conditions something like
NEWCOLUMN = Audit when Type = file, fax, documents, I was using something like
UPDATE TBLNAME SET NEWCOLUMN =
CASE
WHEN TYPE='ACCOUNT' THEN 'FINANCE'
WHEN CODE='DATA' AND CLASS='FIRST' THEN 'LEGAL'
WHEN TYPE='FILE' AND 'FAX' AND 'DOCUMENTS' THEN 'AUDIT'
END
The above query works fine for the first two conditions but the third condition AUDIT is not updated.
Could somebody help?
Thanks
Use
WHEN TYPE IN ('FILE','FAX','DOCUMENTS') THEN 'AUDIT' END
I'm writing stored procedure that should search for records base on few procedure arguments.
The problem is that not always all arguments have to be passed, sometimes they may be set to NULL.
Is there a way to write sth that would work like that?
CREATE PROCEDURE testProc(IN p_idWorker INTEGER, IN p_idEffect INTEGER)
BEGIN
SELECT
*
FROM
CallHistory
WHERE
idWorker = IFNULL(p_idWorker, ANYTHING)
AND
idEffect = IFNULL(p_idEffect, ANYTHING);
END$$
Like so:
...
WHERE (p_idWorker IS NULL OR idWorkder = p_idWorker)
AND (p_idEffect IS NULL OR idEffect = p_idEffect);
Or, like the way you did, but instead of Anything use the column name instead like so:
...
WHERE
idWorker = IFNULL(p_idWorker, idWorker )
AND
idEffect = IFNULL(p_idEffect, idEffect );
You can use for example:
idWorker = IFNULL(p_idWorker, idWorker)
IF p_idWorker is null then this condition is always TRUE for all rows. If not then it is true only if idWorker = p_idWorker
First of all thank you Mahmoud and valex for your time but both answers are not totally good. They will not work if for example the field idWorker is nullable - it will not see the rows where field idWorker IS NULL.
The ultimate solution to this looks weird but it works:
...
WHERE
idWorker = IFNULL(p_idWorker, idWorker)
AND
IFNULL(ch.idProjTime, -1) = IFNULL(p_idProjTime, IFNULL(ch.idProjTime, -1))
Now it'll see NULL fields too.
If it is bad idea to sth like that (I can see probable performance impact - 3 times a row it does the IFNULL condition) - please correct me.