SQL is a vibrant and versatile declarative database and programming language. Development of the language started in 1972, first as SQUARE, and from 1973 on as SEQUEL (Structured English Query Language). In 1977, SEQUEL became SQL because of a trademark dispute.
Why do we need SQL?
A single-line answer to this question is “Moving Computation Close to the Data”.
- Let the database system operate over (high-volume) data in native DBMS format
- Fetch the—typically few or even single—result row(s) into the Programming Language heap, perform lightweight in-heap postprocessing (only if needed)
Introduction to JSONB and JSON data types.
In 2016 Postgres introduced JSON-SQL interoperability. JSON values may be constructed/traversed and held in table cells thereby justifying 1NF to be intact.
There are 2 types of JSON data types supported by Postgres.
- Jsonb - The binary format of JSON
- Json - JavaScript Object Notation
This is what official docs say:
'There are two JSON data types: json and jsonb. They accept almost identical sets of values as input. The major practical difference is one of efficiency. The json data type stores an exact copy of the input text, which processing functions must reparse on each execution; while jsonb data is stored in a decomposed binary format that makes it slightly slower to input due to added conversion overhead, but significantly faster to process, since no reparsing is needed. jsonb also supports indexing, which can be a significant advantage.'
Let us see the difference between JSONB and JSON data types by looking at an example
JSONB
VALUES ( 1, '{ "b":1, "a":2 }' ::jsonb),
(2, '{ "a":1, "b":2, "a":3 }' ),
(3, '[ 0, false,null ]' );
Output -
Let us understand the jsonb data type by analyzing the following the Output
- The data stored is ordered: In the first row, the JSON value present in the query is '{ "b":1, "a":2 }' but the data stored in the cell is {"a": 2, "b": 1}.
- Duplicate keys are not retained: In the second row, the JSON value present in the query is { "a" :1, "b" :2, "a" :3 } but the data stored in the cell {"a": 3, "b" : 2}.
- The extra spaces or paddings in the strings are stripped off: In the third row, the JSON value present in the query is '[ 0,false,null ]'' but the data stored in the cell [0, false, null].
JSON
Output -
Let us understand the json data type by analyzing the following the Output
- The data stored is not ordered: The values in the query and output are the same '{"b": 1, "a": 2}'.
- Duplicate keys are retained: The values in the query and output are the same '{"a": 1, "b": 2, “a”:3}'
- The extra spaces or paddings in the strings are not stripped off: In The values in the query and output are the same '[ 0, false, null ]'
NOTE: jsonb is widely and globally used. This article will mainly concentrate on jsonb, hereby just referred to as json
Navigating the JSON.
There are 2 ways to navigate the JSON values
- Using subscripting
- Using path syntax
- Via -> and ->>
1. Navigation using subscripting
SELECT ('{ "a":0, "b": { "b1":[1,2], "b2":3 } }' :: jsonb)['b']['b1'][1] :: int + 40;
OUTPUT - 42
WORKING -
The input json value is { "a": 0, "b": { "b1": [ 1, 2 ], "b2": 3 } }
Accessing the element b1 - json['b']['b1']
2. Navigation using path syntax
SELECT j
FROM jsonb_path_query('{ "a":0, "b": { "c":[1,2], "d":3 } }' :: jsonb,
'$') AS j;
Output - "{"a": 0, "b": {"c": [1, 2], "d": 3}}"
Consider the json value
3. Navigation using -> and ->>
-> yields back a jsonb value, permits further navigation using -> or ->> ->> yields a text value (cast to atomic type for further computation)
SELECT ('{ "a":0, "b": { "b1":[1,2], "b2":3 } }' :: jsonb -> 'b' ->> 'b2') :: int + 40;
{ "a":0, "b": { "b1":[1,2], "b2":3 } } -> 'b' // yields { "b1":[1,2], "b2":3 } of type jsonb
{ "a":0, "b": { "b1":[1,2], "b2":3 } } -> 'b' ->> 'b3' // yields atomic value - 3
Bridge between JSON and SQL
JSON to Table Turn the fields and/or nested values inside JSON object into tables which we can query
- jsonb_each(o) - separate key and values
- jsonb_array_elements(a) - get array elements into a table
SELECT jsonb_each('{ "a":0, "b":2, "c":3 }' :: jsonb)
OUTPUT
(a, 0)
(b, 2)
(c, 3)
SELECT jsonb_array_elements('[ 0, false,null ]' :: jsonb)
OUTPUT
Table to JSON Convert single SQL row into SQL object
- row_to_json(・)::jsonb - Convert a single table row to a json value
- array_to_json(array_agg(・))::jsonb
SELECT row_to_json(t):: jsonb
FROM (VALUES (false, 0),
(true, 1),
(true, 2)) AS t(a, b)
OUTPUT
SELECT array_to_json(array_agg(t.a))
FROM (VALUES ('{ "b":1}' ::jsonb),
('{ "a":2}' )) AS t(a)
OUTPUT
[{“b” : 1}, {“a”, 2} ]
Conclusion
It's really exciting to learn about the increasing support of JSON in Postgres. It will definitely make developers more familiar with the benefits of storing data as JSON and consequently make Document Databases also more popular. Many tools and frameworks in the market already offer support for JSON data, and as the adoption of Postgres JSONB increases, it should become a standard feature The Evolution of JSONB has just started. The sky's the limit