PostgreSQL - Set JSONB property from column value - postgresql

I have a numeric column total_price and I want to move it to a jsonb property named price_detail. For example, if the total_price value is 1000, the expected price_detail value is {"totalPrice": 1000}
I've tried using jsonb_set but the result is empty object {}
UPDATE public.orders SET price_detail =
jsonb_set('{}'
, '{}'
, jsonb_build_object('totalPrice', total_price::numeric))
If I set the path,
UPDATE public.orders SET price_detail =
jsonb_set('{}'
, '{totalPrice}'
, jsonb_build_object('totalPrice', total_price::numeric))
The result is {"totalPrice":{"totalPrice":1000}} which is unexpected
How can I set the totalPrice property correctly?

You don't need the JSONB_SET, just use JSONB_BUILD_OBJECT:
UPDATE orders
SET price_detail = JSONB_BUILD_OBJECT('totalPrice', total_price::numeric)
Demo on dbfiddle

Related

Divide a value in JSON using postgreSQL

Im relatively new and would like to redenominate some values in my current database. This means going into my jasonb column in my database, selecting a key value and dividing it by a 1000. I know how to select values but update after I have performed a calculation has failed me. My table name is property_calculation and has two columns as follows: * dynamic_fields is my jasonb column
ID
dynamic_fields
1
{"totalBaseValue": 4198571.230720645844841865113039602874778211116790771484375,"surfaceAreaValue": 18.108285497586717127660449477843940258026123046875,"assessedAnnualValue": 1801819.534798908603936834409607936611000776616631213755681528709828853607177734375}
2
{"totalBaseValue": 7406547.28939837918763178237213651300407946109771728515625,"surfaceAreaValue": 31.94416993248973568597648409195244312286376953125,"assessedAnnualValue": 9121964.022681592442116216621222042691512210677018401838722638785839080810546875}
I would like to update the dynamic_fields.totalBaseValue by dividing it by 1000 and committing it back as the new value. I have tried the following with no success:
update property_calculation
set dynamic_fields = (
select jsonb_agg(case
when jsonb_typeof(elem -> 'totalBaseValue') = 'number'
then jsonb_set(elem, array['totalBaseValue'], to_jsonb((elem ->> 'totalBaseValue')::numeric / 1000))
else elem
end)
from jsonb_array_elements(dynamic_fields::jsonb) elem)::json;
I get the following error:
ERROR: cannot extract elements from an object
SQL state: 22023
My json column has no zero string or null values.
Move the jsonb_typeof() check into the where clause:
update property_calculation
set dynamic_fields =
jsonb_set(
dynamic_fields,
'{totalBaseValue}',
to_jsonb((dynamic_fields->>'totalBaseValue')::numeric / 1000)
)
where jsonb_typeof(dynamic_fields->'totalBaseValue') = 'number';
db<>fiddle here

Build jsonb array from jsonb field

I have column options with type jsonb , in format {"names": ["name1", "name2"]} which was created with
UPDATE table1 t1 SET options = (SELECT jsonb_build_object('names', names) FROM table2 t2 WHERE t2.id= t1.id)
and where names have type jsonb array.
SELECT jsonb_typeof(names) FROM table2 give array
Now I want to extract value of names as jsonb array. But query
SELECT jsonb_build_array(options->>'names') FROM table
gave me ["[\"name1\", \"name2\"]"], while I expect ["name1", "name2"]
How can I get value in right format?
The ->> operator will return the value of the field (in your case, a JSON array) as a properly escaped text. What you are looking for is the -> operator instead.
However, note that using the jsonb_build_array on that will return an array containing your original array, which is probably not what you want either; simply using options->'names' should get you what you want.
Actually, you don't need to use jsonb_build_array() function.
Use select options -> 'names' from table; This will fix your issue.
jsonb_build_array() is for generating the array from jsonb object. You are following wrong way. That's why you are getting string like this ["[\"name1\", \"name2\"]"].
Try to execute this sample SQL script:
select j->'names'
from (
select '{"names": ["name1", "name2"]}'::JSONB as j
) as a;

How to update an empty jsonb column using jsonb_set in postgresql?

My purpose is to update a jsonb column using jsonb_set, which is currently null, with an object having more than one key-value pairs. The update command executes successfully but it is not updating anything, the column is still coming up empty. I am trying the following query.
UPDATE tab
set value = jsonb_set(value, '{}', '{"a" : 100, "b" : [100, 200]}'::jsonb)
where id = 100;
Any solutions ?
From what I've understood, it appears you don't need jsonb_set for this case. Simply cast the string to jsonb for updating
UPDATE tab
set value = '{"a" : 100, "b" : [100, 200]}'::jsonb
where id = 100
--and value is null; --additional check if you need.
Demo

Update column with multiple values Postgres

Sample data:
I am trying update a column with values from multiple columns in another table if two columns match.
Consider the following query:
UPDATE application_table
SET asset_list = asset_table.asset_name
FROM asset_table
WHERE application_table.application_name = asset_table.applications;
My table structure is:
application_table:
"asset_list"; "text[]"
"application_name"; "character varying"
asset_table:
"asset_name"; "character varying"
"applications"; "character varying"
I get the following error:
ERROR: column "asset_list" is of type text[] but expression is of type character varying
Line 12 SET asset_list = asset_table.asset_name
What you need to do is aggregate the asset_name per applications value and set asset_list to that aggregated value.
Problem is you can't do something like
UPDATE ..
SET asset_list = ARRAY_AGG(asset_name)
FROM ...
because aggregate functions are not allowed in updates like that.
So here's two other ways to do it:
UPDATE app_table
SET asset_list = _asset_list
FROM (
SELECT applications, ARRAY_AGG(asset_name ORDER BY asset_name) AS _asset_list
FROM asset_table
GROUP BY applications
) AS a
WHERE app_name = applications;
https://www.db-fiddle.com/f/pKB5k6Lexwzqv6ZbCCdJay/0
This first builds a result set of distinct application names and an array of all the asset_names for each of the app names. Then it updates the table as usual with that array value.
Another way is:
UPDATE app_table
SET asset_list = (SELECT ARRAY_AGG(asset_name ORDER BY asset_name)
FROM asset_table
WHERE applications = app_name)
;
https://www.db-fiddle.com/f/8oVWsubXW93n142gtZYLXB/0
This will update every record in app_table, and calculates the array value on the fly for every record.

How to set an object to null

How to set an object to null.
Ex:
my object samp contains three fileds
samp.field1,samp.field2.sampfield3
If i set samp:= null;
im getting errors is there a way to set the object value to null.
An sql database does not know about objects, it deals with rows in table.
To remove a row use DELETE :
e.g. :
DELETE FROM samp WHERE id = 12345;
DELETE FROM samp WHERE field1 = 'Delete Me';
The first example is typical to remove individual rows uing their primary key (id in this case)
The second example will remove a group of rows which have a speciic value for a field.