syntax error when trying to query json documents in postgresql - json

on my postgresql 9.6, I ran into an error with a table created like
create table jsonTest (id integer, data jsonb);
The table has the following data:
select * from jsonTest;
id | data
----+----------------------------------
1 | {"tags": ["AA", "BB", "CC"]}
2 | {"tags": ["BB", "DD"]}
2 | {"tags": ["CC"]}
4 | {"city": "austin", "tags": "EE"}
(4 rows)
But when I tried to select, got syntax error:
template1=# select * from jsonTest where data->>city = 'austin';
ERROR: column "city" does not exist
LINE 1: select * from jsonTest where data->>city = 'austin';
Any ideas? Thanks a lot!

The right operand of ->> operator for JSON object is text. Use the apostrophes for the key, because without them Postgres interprets the name as an identifier (a column name):
data->>'city'

Related

Can't get through mysql JSON_CONTAINS to show the correcct data. Getting null everytime i try

The data in the table events with column attributes is in json and looks like this -
{"event_volunteer_requests":{"1":{"volunteertypeid":250,"volunteer_needed_count":50,"cc_email":""},"2":{"volunteertypeid":249,"volunteer_needed_count":30,"cc_email":""}}}
So the context is that i want to show the events with volunteertypeid present in the attributes. There are many volunteers., this is just sample data.
I've been using the query below
SELECT
*
FROM `events`
WHERE `zoneid` = 27
AND `isactive` = 1
AND JSON_CONTAINS(`attributes` -> '$.event_volunteer_requests[*].volunteertypeid', '249');
I just can't make this work and i've scorched the internet for hours. Any guidance would be appreciated.
Your JSON structure uses object syntax ({"key": "value"}), but you seem to want to use it as a JSON array (["value", "value", ...]).
The [*] syntax in JSON paths works for JSON arrays, not for JSON objects.
If your JSON document must be nested object syntax:
{
"event_volunteer_requests": {
"1": {
"cc_email": "",
"volunteertypeid": 250,
"volunteer_needed_count": 50
},
"2": {
"cc_email": "",
"volunteertypeid": 249,
"volunteer_needed_count": 30
}
}
}
Then you can do what you want this way:
SELECT t.id, t.volunteertypeid
FROM (
SELECT j.id, JSON_EXTRACT(a.attributes, CONCAT('$.event_volunteer_requests."', j.id, '".volunteertypeid')) AS volunteertypeid
FROM (SELECT '{"event_volunteer_requests":{"1":{"volunteertypeid":250,"volunteer_needed_count":50,"cc_email":""},"2":{"volunteertypeid":249,"volunteer_needed_count":30,"cc_email":""}}}' as attributes) AS a
CROSS JOIN JSON_TABLE(JSON_KEYS(a.attributes, '$.event_volunteer_requests'), '$[*]' COLUMNS (id INT PATH '$')) AS j
) AS t
WHERE t.volunteertypeid = 249;
Result:
+------+-----------------+
| id | volunteertypeid |
+------+-----------------+
| 2 | 249 |
+------+-----------------+
The JSON_TABLE() function requires MySQL 8.0. If you use MySQL 5.7, you must upgrade.

Update JSONB with UUID value

I have a table with a column of jsonb type, the JSON object is of key:value pairs, the problem is, I need to update one of the keys to contain a UUID instead of the original value.
The update statement I'm using:
UPDATE
public.applications a
SET
data = jsonb_set(data, '{id}', (SELECT b.uuid FROM public.devices b WHERE b.id = (a.data ->> 'id')::integer)::text)
Postgres returns the following error:
ERROR: function jsonb_set(jsonb, unknown, text) does not exist
I've tried to cast the value to different data types, but with same result.
Sample data
id | data
---------
1 | {"id": 1}
2 | {"id": 2}
Expected output
id | data
---------
1 | {"id": device_uuid_here}
2 | {"id": device_uuid_here}
DB_VERSION: PostgreSQL12.12
UPDATE public.applications a
SET data = jsonb_set(data, '{id}',
(SELECT '"'||b.uuid::text||'"' FROM public.devices b
WHERE b.id = (a.data ->> 'id')::integer)::jsonb);

MySQL Parse and Split JSON value

I have a column which contains a JSON value of different lengths
["The Cherries:2.50","Draw:3.25","Swansea Jacks:2.87"]
I want to split them and store into a JSON like so:
[
{
name: "The Cherries",
odds: 2.50
},
{
name: "Draw",
odds: 3.25
},
{
name: "Swansea",
odds: 2.87
},
]
What I did right now is looping and splitting them in the UI which to me is quite heavy for the client. I want to parse and split them all in a single query.
If you are running MySQL 8.0, you can use json_table() to split the original arrayto rows, and then build new objects and aggregate them with json_arrayagg().
We need a primary key column (or set of columns) so we can properly aggreate the generated rows, I assumed id:
select
t.id,
json_arrayagg(json_object(
'name', substring(j.val, 1, locate(':', j.val) - 1),
'odds', substring(j.val, locate(':', j.val) + 1)
)) new_js
from mytable t
cross join json_table(t.js, '$[*]' columns (val varchar(500) path '$')) as j
group by t.id
Demo on DB Fiddle
Sample data:
id | js
-: | :-------------------------------------------------------
1 | ["The Cherries:2.50", "Draw:3.25", "Swansea Jacks:2.87"]
Query results:
id | new_js
-: | :----------------------------------------------------------------------------------------------------------------------
1 | [{"name": "The Cherries", "odds": "2.50"}, {"name": "Draw", "odds": "3.25"}, {"name": "Swansea Jacks", "odds": "2.87"}]
You can use json_table to create rows from the json object.
Just replace table_name with your table name and json with the column that contains json
SELECT json_arrayagg(json_object('name',SUBSTRING_INDEX(person, ':', 1) ,'odds',SUBSTRING_INDEX(person, ':', -1) ))
FROM table_name,
JSON_TABLE(json, '$[*]' COLUMNS (person VARCHAR(40) PATH '$') people;
Here is a Db fiddle you can refer
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=801de9f067e89a48d45ef9a5bd2d094a

Error while setting up a golden gate replication process, for JSON document convert to rdbms table

I am trying to convert and replicate json document stored in oracle table (source) as clob value to target database (oracle) as rdbms table using oracle goldengate :
GGSCI (ggsrv2.localdomain) 39> view params RJSON3
Replicat rjson3
DiscardFile ./dirrpt/rjson3.dsc, Purge
USERID ogg, PASSWORD oracle
Map HR.JSON_TEST_SOURCE, Target HRTRG.JSON_TEST_TARGET,
SQLEXEC (id lookup, QUERY 'SELECT json_value(jsondoc, '$.IDNumber') AS J_ID, json_value(jsondoc, '$.Description') AS J_DESCRIPTION, json_value(jsondoc, '$.DecimalNumber') AS J_DECIMAL FROM
HRTRG.JSON_TEST_SOURCE
WHERE ID = :V_ID ',
PARAMS (V_ID = ID)),
J_ID = #GETVAL(lookup.J_ID)),
J_DESCRIPTION = #GETVAL(lookup.J_DESCRIPTION)),
J_DECIMAL = #GETVAL(lookup.J_DECIMAL))
);
Error message:
2019-01-06 07:56:54 WARNING OGG-10173 (rjson3.prm) line 4 column 317: Parsing error, value "'#'" syntax error.
2019-01-06 07:56:54 WARNING OGG-10173 (rjson3.prm) line 4: Parsing error, option [sqlexec] for parameter [map] has unrecognized value "=".
2019-01-06 07:56:54 WARNING OGG-10173 (rjson3.prm) line 4: Parsing error, option [sqlexec] for parameter [map] has unrecognized value "J_ID"."
Database version 12cR2,GoldenGate version 12.3
Source Table:
SQL> desc HR.JSON_TEST_SOURCE;
Name Null? Type
------- -------- ------------
ID NOT NULL NUMBER(10)
JSONDOC CLOB
Sample data on Source table:
SQL> col JSONDOC for a55
SQL> select * from HR.JSON_TEST_SOURCE;
ID JSONDOC
---------- -------------------------------------------------------
1600 { "IDNumber" : 01,
"Description" : "I am Shanoj",
"DecimalNumber" :
1601 { "IDNumber" : 02,
"Description" : "I am Joby",
"DecimalNumber" : 1
1602 { "IDNumber" : 03,
"Description" : "I am Siriram",
"DecimalNumber"
1603 { "IDNumber" : 04,
"Description" : "No idea who I am",
"DecimalNumb
Target Table:
SQL> desc HRTRG.JSON_TEST_TARGET
Name Null? Type
-------------- -------- --------------
J_ID NOT NULL VARCHAR2(4000)
J_DESCRIPTION VARCHAR2(4000)
J_DECIMAL VARCHAR2(4000)
Looks like you may to use some adapters. Another option is to use a materialized view from target to get the JSon values as records using json_values().

query to Extract from Json in Postgres

I've a json object in my postgres db, which looks like as given below
{"Actor":[{"personName":"Shashi Kapoor","characterName":"Prem"},{"personName":"Sharmila Tagore","characterName":"Preeti"},{"personName":"Shatrughan Sinha","characterName":"Dr. Amar"]}
Edited (from editor: left the original because it is an invalid json, in my edit I fixed it)
{
"Actor":[
{
"personName":"Shashi Kapoor",
"characterName":"Prem"
},
{
"personName":"Sharmila Tagore",
"characterName":"Preeti"
},
{
"personName":"Shatrughan Sinha",
"characterName":"Dr. Amar"
}
]
}
the name of the column be xyz and I've a corresponding content_id.
I need to retrieve content_ids that have Actor & personName = Sharmila Tagore.
I tried many queries, among those these two where very possible query to get but still i didn't get.
SELECT content_id
FROM content_table
WHERE cast_and_crew #>> '{Actor,personName}' = '"C. R. Simha"'
.
SELECT cast_and_crew ->> 'content_id' AS content_id
FROM content_table
WHERE cast_and_crew ->> 'Actor' -> 'personName' = 'C. R. Simha'
You should use jsonb_array_elements() to search in a nested jsonb array:
select content_id, value
from content_table,
lateral jsonb_array_elements(cast_and_crew->'Actor');
content_id | value
------------+-----------------------------------------------------------------
1 | {"personName": "Shashi Kapoor", "characterName": "Prem"}
1 | {"personName": "Sharmila Tagore", "characterName": "Preeti"}
1 | {"personName": "Shatrughan Sinha", "characterName": "Dr. Amar"}
(3 rows)
Column value is of the type jsonb so you can use ->> operator for it:
select content_id, value
from content_table,
lateral jsonb_array_elements(cast_and_crew->'Actor')
where value->>'personName' = 'Sharmila Tagore';
content_id | value
------------+--------------------------------------------------------------
1 | {"personName": "Sharmila Tagore", "characterName": "Preeti"}
(1 row)
Note, if you are using json (not jsonb) use json_array_elements() of course.