How to update a jsonb column and put text array - arrays

I have jsonb column like so:
{name: "Toby", occupation: "Software Engineer", interests: ""}
Now, I need to update the row and put a text array like ['Volleyball', 'Football', 'Swim'] into interests field.
What I've tried so far:
UPDATE users SET data = jsonb_set(data, '{interests}', ARRAY['Volleyball', 'Football', 'Swim'], true) WHERE id=84;
data is the jsonb column
But it returns an error:
ERROR: function jsonb_set(jsonb, unknown, integer[], boolean) does not
exist
Hint: No function matches the given name and argument types. You
might need to add explicit type casts.
P.S:
I'm using PostgreSQL 10

The third argument needs to be of JSONB type too.
UPDATE users SET data = jsonb_set(data, '{interests}', '["Volleyball", "Football", "Swim"]'::jsonb, true) WHERE id=84;
This will also work, which is a little closer to your example using ARRAY:
UPDATE users SET data = jsonb_set(data, '{interests}', to_jsonb(array['Volleyball', 'Football', 'Swim']), true) WHERE id=84

Related

SQL Searching Query inside JSON object array

Consider the below JSON object
[
{
"startdt": "10/13/2021",
"enddt": "10/13/2022",
"customerName1": "John",
"customerName2": "CA"
},
{
"startdt": "10/14/2021",
"enddt": "10/14/2022",
"customerName1": "Jacob",
"customerName2": "NJ"
}
]
This is the value present in a table "CustInfo" in the column "custjson" in Postgress DB. I want to search the data for the field customerName1. I have created the below query but it is searching in the whole object in such a way that if I give customerName1 as "Jacob" it gives the whole array. I want to search only for a particular array and return the same.
SELECT DISTINCT ON(e.id) e.*,
(jsonb_array_elements(e.custjson)->>'customerName1') AS name1
FROM CustInfo e
CROSS JOIN jsonb_array_elements(e.custjson) ej
WHERE value ->> 'customerName1' LIKE '%Jacob%'
Is there a way in which we can only search the "Jacob" customerName1's array instead of whole json?
For eg: if i search for Jacob i should get the following istead of searching the whole JSON
{
"startdt": "10/14/2021",
"enddt": "10/14/2022",
"customerName1": "Jacob",
"customerName2": "NJ"
}
Any help would be greatly helpful
You can use a JSON path expression to find the array element with a matching customer name:
select e.id,
jsonb_path_query_array(e.custjson, '$[*] ? (#.customerName1 like_regex "Jacob")')
from custinfo e
Based on your sample data, this returns:
id | jsonb_path_query_array
---+----------------------------------------------------------------------------------------------------
1 | [{"enddt": "10/14/2022", "startdt": "10/14/2021", "customerName1": "Jacob", "customerName2": "NJ"}]
If you are using an older Postgres version, that doesn't support JSON path queries, you need to unnest and aggregate manually:
select e.id,
(select jsonb_agg(element)
from jsonb_array_elements(e.custjson) as x(element)
where x.element ->> 'customerName1' like '%Jacob%')
from custinfo e
This assumes that custjson is defined with the data type jsonb (which it should be). If not, you need to cast it: custjson::jsonb

SQL column type

I am trying to take whereTerm which currently has no type listed in the view in SQL management when i hover over it and pass it into a stored procedure. well here is the issue it says that Cannot convert value of type array to integer.
I cannot change the SQL view and was wondering what the proper type is for a column when you hover over it, all it says is COLUMN: whereTerm and that is it. above that is another column named COLUMN: schoolYear - varchar(9). ok so that one has varchar as a type great so what is the type of whereTerm......is there a way to further look the type up or does that column just not have one any help would be appreciated.
#whereTerm=:whereTerm,
',
[
'whereTerm' => ['whereTerm'],
],
[
'whereTerm' => 'integer',
]
)

jsonb_set pass variable value instead of static in procedure

Need help to get jsob_set working under PostgreSQL procedure,
Fetching records from child table and updating parent table's json fields value.
Assigning selected value to the variable and adding it to jsonb_set under value,
e.g
jsonb_set(jsonFieldOfDb,'{json_Column}',jsonVariable,true);
Where jsonVariable is my selected value from second table.
For more detail please look at screenshot attached.
You might need to cast the path & jsonVariable to text[] and jsonb
jsonb_set(jsonFieldOfDb,'{json_Column}'::text[],jsonVariable::jsonb,true)
if your jsonVariable is just a plain string, you might need to quote them as well
jsonb_set(jsonFieldOfDb,'{json_Column}'::text[],('"' || jsonVariable || '"')::jsonb, true)
Adding to Yurui's answer, if you want to set a dynamic value other than string, you can convert the dynamic variable to jsonb by using to_jsonb function like this:
UPDATE event AS e
SET source_json = jsonb_set(source_json, '{consumerId}'::text[], to_jsonb(p.promoter_id))
FROM promoter AS p
WHERE e.id = p.event_id and p.app_id in ('123');

Dynamic variables within SQL

Good morning guys,
I'm having a slight issue with a SQL stored procedure. I am posting these variables to the procedure via. a HTML form:
Post Params:
key: 'DocID_1' value: '18743921-3810-4516-AA6B-566DF1045BDE'
key: 'status_1' value: 'Ignore'
key: 'DocID_2' value: '228C53F6-FE71-4816-8865-B52C02114D54'
key: 'status_2' value: 'Ignore'
key: 'DocID_3' value: 'ABCFCD74-56A3-4B11-B2C4-8D5B827E5648'
key: 'status_3' value: 'Ignore'
key: 'DocID_4' value: 'CD3F7440-BC71-48D0-B358-9EA5366ACCDE'
key: 'status_4' value: 'Ignore'
key: 'rowCount' value: '4'
Which are basically a list of documents which need to be approved, ignored etc. In my stored procedure I've got a function which iterates up to the rowCount variables value. What I am trying to do is use a select statement to select each DocID_ passed to the procedure.
My select statement so far:
DECLARE #rowCount int = 4
DECLARE #DocID_1 nvarchar(80) = '18743921-3810-4516-AA6B-566DF1045BDE'
SELECT
num,
#DocID_ + num
FROM
dbo.ufn_getcount(1, #rowCount)
As you can see I am trying to concatenate #DocID_ and num, which is the number returned by my function. This returns an error which to be honest I expected:
Must declare the scalar variable "#DocID_"
After reviewing the above, is there any way to dynamically create variable names on the fly?
I'm not quite sure what the advantage of selecting #DocID_ + num (were that a valid operation) would be - from the code sample you've listed you'd seem likely to know which variable was being selected anyway?
This could be done with dynamic SQL but it wouldn't be simple and the possibility for SQL Injection if it wasn't properly constructed is significant. Instead I'd look at the underlying requirement and work out how better to implement it. Possible options -
Table valued parameters
Table variables / temporary tables
Amending your getcount function to return the value you're specifically looking for - we'd need to see it's code to be certain but I suspect it'd be possible.

How to create a table in Hive with a column of data type array<map<string, string>>

I am trying to create a table which has a complex data type. And the data types are listed below.
array
map
array< map < String,String> >
I am trying to create a data structure of 3 type . Is it ever possible to create in Hive? My table DDL looks like below.
create table complexTest(names array<String>,infoMap map<String,String>, deatils array<map<String,String>>)
row format delimited
fields terminated by '/'
collection items terminated by '|'
map keys terminated by '='
lines terminated by '\n';
And my sample data looks like below.
Abhieet|Test|Complex/Name=abhi|age=31|Sex=male/Name=Test,age=30,Sex=male|Name=Complex,age=30,Sex=female
Whever i am querying the data from the table i am getting the below values
["Abhieet"," Test"," Complex"] {"Name":"abhi","age":"31","Sex":"male"} [{"Name":null,"Test,age":null,"31,Sex":null,"male":null},{"Name":null,"Complex,age":null,"30,Sex":null,"female":null}]
Which is not i am expecting. Could you please help me to find out what should be the DDL if it ever possible for data type array< map < String,String>>
I don't think this is possible using the inbuilt serde. If you know in advance what the values in your maps are going to be, then I think a better way of approaching this would be to convert your input data to JSON, and then use the Hive json serde:
Sample data:
{'Name': ['Abhieet', 'Test', 'Complex'],
'infoMap': {'Sex': 'male', 'Name': 'abhi', 'age': '31'},
'details': [{'Sex': 'male', 'Name': 'Test', 'age': '30'}, {'Sex': 'female', 'Name': 'Complex', 'age': '30'}]
}
Table definition code:
create table complexTest
(
names array<string>,
infomap struct<Name:string,
age:string,
Sex:string>,
details array<struct<Name:string,
age:string,
Sex:string>>
)
row format serde 'org.openx.data.jsonserde.JsonSerDe'
This can be handled with array of structs using the following query.
create table complexStructArray(custID String,nameValuePairs array<struct< key:String, value:String>>) row format delimited fields terminated by '/' collection items terminated by '|' map keys terminated by '=' lines terminated by '\n';
Sample data:
101/Name=Madhavan|age=30
102/Name=Ramkumar|age=31
Though struct allows duplicate key values unlike Map, above query should handle the ask if the data is having unique key values.
select query would give the output as follows.
hive> select * from complexStructArray;
101 [{"key":"Name","value":"Madhavan"},{"key":"age","value":"30"}]
102 [{"key":"Name","value":"Ramkumar"},{"key":"age","value":"31"}]
Sample data: {"Name": ["Abhieet", "Test", "Complex"],"infoMap": {"Sex":"male", "Name":"abhi", "age":31},"details": [{"Sex":"male", "Name":"Test", "age":30}, {"Sex":"female", "Name":"Complex", "age":30}]}
Table definition code:
#hive>
create table complexTest
(names array<string>,infomap struct<Name:string,
age:string,
Sex:string>,details array<struct<Name:string,
age:string,
Sex:string>>)
row format serde 'org.apache.hive.hcatalog.data.JsonSerDe'

Resources