What is the difference between `->>` and `->` in Postgres SQL?

SqlJsonPostgresql

Sql Problem Overview


What is the difference between ->> and -> in SQL?

In this thread (https://stackoverflow.com/questions/19422233/check-if-field-exists-in-json-type-column-postgresql), the answerer basically recommends using,

json->'attribute' is not null

instead of,

json->>'attribute' is not null

Why use a single arrow instead of a double arrow? In my limited experience, both do the same thing.

Sql Solutions


Solution 1 - Sql

-> returns json (or jsonb) and ->> returns text:

with t (jo, ja) as (values
    ('{"a":"b"}'::jsonb,('[1,2]')::jsonb)
)
select
    pg_typeof(jo -> 'a'), pg_typeof(jo ->> 'a'),
    pg_typeof(ja -> 1), pg_typeof(ja ->> 1)
from t
;
 pg_typeof | pg_typeof | pg_typeof | pg_typeof 
-----------+-----------+-----------+-----------
 jsonb     | text      | jsonb     | text

Solution 2 - Sql

PostgreSQL provides two native operators -> and ->> to help you query JSON data.

The operator -> returns JSON object field as JSON. The operator ->> returns JSON object field as text.

The following query uses operator -> to get all customers in form of JSON:

SELECT
 info -> 'customer' AS customer
FROM
 orders;
customer
--------
"John Doe"
"Lily Bush"
"Josh William"
"Mary Clark"

And the following query uses operator ->> to get all customers in form of text:

SELECT
 info ->> 'customer' AS customer
FROM
 orders;
customer
--------
John Doe
Lily Bush
Josh William
Mary Clark

You can see more details in the link below http://www.postgresqltutorial.com/postgresql-json/

Solution 3 - Sql

Postgres offers 2 operators to get a JSON member:

  • the arrow operator: -> returns type JSON or JSONB
  • the double arrow operator: ->> returns type text

We must also understand that we now have 2 different kinds of null:

  • (null) postgres null type
  • null json/b null type

I created an example on jsfiddle

Let's create a simple table with a JSONB field:

create table json_test (
  id integer,
  val JSONB
);

and insert some test-data:

INSERT INTO json_test (id, val) values
(1, jsonb_build_object('member', null)),
(2, jsonb_build_object('member', 12)),
(3, null);

Output as we see it in sqlfiddle:

id	| val
----+-----------------
 1  | {"member": null}
 2  | {"member": 12}
 3  | (null)

Notes:

  1. contains a JSONB object and the only field member is null
  2. contains a JSONB object and the only field member has the numeric value 12
  3. is (null): i.e. the whole column is (null) and does not contain a JSONB object at all

To better understand the differences, let's look at the types and null-checks:

SELECT id,
  val -> 'member'  as arrow,
  pg_typeof(val -> 'member')  as arrow_pg_type,
  val -> 'member' IS NULL as arrow_is_null,
  val ->> 'member' as dbl_arrow,
  pg_typeof(val ->> 'member')  as dbl_arrow_pg_type,
  val ->> 'member' IS NULL as dbl_arrow_is_null,
  CASE WHEN jsonb_typeof(val -> 'member') = 'null' THEN true ELSE false END as is_json_null
from json_test;

Output:

id arrow arrow_pg_type arrow_is_null dbl_arrow dbl_arrow_pg_type dbl_arrow_is_null is_json_null
1 null jsonb false (null) text true true
2 12 jsonb false 12 text false false
3 (null) jsonb true (null) text true false

Notes:

  • for {"member": null}:

    • val -> 'member' IS NULL is false
    • val ->> 'member' IS NULL is true
  • is_json_null can be used to get only the json-null condition

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiontim_xyzView Question on Stackoverflow
Solution 1 - SqlClodoaldo NetoView Answer on Stackoverflow
Solution 2 - SqlEddy BayonneView Answer on Stackoverflow
Solution 3 - SqlTmTronView Answer on Stackoverflow