🧚 Hör mal! Beekeeper Studio ist eine schnelle, moderne Open-Source-Datenbank-GUI Download
23. März 2025 Von Matthew Rathbone

PostgreSQL bietet mit den Datentypen json und jsonb starke Unterstützung zum Speichern und Abfragen von JSON-Daten. Besonders nützlich ist der Typ jsonb, da er die Daten in einem Binärformat speichert und so effizienteres Indexieren und Abfragen ermöglicht als der textbasierte Typ json.

In diesem Tutorial sehen wir uns die gängigsten JSON-Operationen in PostgreSQL an – mit praktischen Beispielen, die du direkt in deinen Anwendungen nutzen kannst.

JSON-Daten anlegen

Legen wir zuerst eine Tabelle mit einer jsonb-Spalte an und fügen ein paar Beispieldaten ein:

CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    info JSONB
);

-- Insert a customer with basic information
INSERT INTO customers (info) VALUES (
    '{"name": "Alice Smith", "email": "alice@example.com", "age": 32, "addresses": [
        {"type": "home", "city": "San Francisco", "state": "CA"}, 
        {"type": "work", "city": "Oakland", "state": "CA"}
     ]}'
);

-- Insert another customer
INSERT INTO customers (info) VALUES (
    '{"name": "Bob Johnson", "email": "bob@example.com", "age": 45, "addresses": [
        {"type": "home", "city": "Seattle", "state": "WA"}
     ], "orders": [101, 102, 103]}'
);

Grundlegende JSON-Operationen

Das gesamte JSON-Dokument abrufen

SELECT info FROM customers WHERE id = 1;

Ergebnis:

{
  "age": 32,
  "name": "Alice Smith",
  "email": "alice@example.com",
  "addresses": [
    {"city": "San Francisco", "type": "home", "state": "CA"},
    {"city": "Oakland", "type": "work", "state": "CA"}
  ]
}

Werte aus JSON extrahieren

PostgreSQL bietet mehrere Operatoren, um Werte aus JSON zu extrahieren:

Ein bestimmtes Feld mit dem Operator -> extrahieren (liefert JSON)

-- Get the name field as JSON
SELECT info -> 'name' FROM customers;

Ergebnis:

"Alice Smith"
"Bob Johnson"

Ein bestimmtes Feld mit dem Operator -» extrahieren (liefert Text)

-- Get the name field as text
SELECT info ->> 'name' AS customer_name FROM customers;

Ergebnis:

customer_name
----------------
Alice Smith
Bob Johnson

Auf verschachtelte Objekte zugreifen

-- Getting the first address (array element 0) city
SELECT info -> 'addresses' -> 0 ->> 'city' AS home_city FROM customers;

Ergebnis:

home_city
------------
San Francisco
Seattle

Den Operator #> für Pfadzugriffe nutzen

-- Using the path syntax to get the same value
SELECT info #> '{addresses,0,city}' FROM customers;

Ergebnis:

"San Francisco"
"Seattle"

Den Operator #» für Pfadzugriffe als Text nutzen

-- Using the path syntax to get the same value as text
SELECT info #>> '{addresses,0,city}' AS home_city FROM customers;

Ergebnis:

home_city
------------
San Francisco
Seattle

JSON-Daten ändern

PostgreSQL bietet mehrere Funktionen zum Ändern von JSON-Daten:

Ein Feld mit jsonb_set hinzufügen

-- Add a new field 'premium_customer' to a customer
UPDATE customers
SET info = jsonb_set(info, '{premium_customer}', 'true')
WHERE id = 1;

Ein Feld mit dem Operator - entfernen

-- Remove the premium_customer field
UPDATE customers
SET info = info - 'premium_customer'
WHERE id = 1;

JSON-Objekte mit || zusammenführen

-- Add multiple fields by merging objects
UPDATE customers
SET info = info || '{"status": "active", "last_login": "2025-03-23"}'::jsonb
WHERE id = 1;

Ein verschachteltes Feld aktualisieren

-- Update a nested field (home address state)
UPDATE customers
SET info = jsonb_set(
    info, 
    '{addresses,0,state}', 
    '"NY"'::jsonb
)
WHERE id = 1;

JSON-Arrays abfragen

Die Arbeit mit JSON-Arrays ist eine häufige Aufgabe:

Array-Länge ermitteln

-- Get the number of addresses for each customer
SELECT 
    info ->> 'name' AS customer_name,
    jsonb_array_length(info -> 'addresses') AS address_count
FROM customers;

Ergebnis:

customer_name  | address_count
---------------+--------------
Alice Smith    | 2
Bob Johnson    | 1

Bestimmte Array-Elemente extrahieren

-- Get the second address (index 1) for Alice
SELECT info -> 'addresses' -> 1 FROM customers WHERE id = 1;

Ergebnis:

{"city": "Oakland", "type": "work", "state": "CA"}

Arrays entpacken, um einzelne Elemente abzufragen

-- Unnest the addresses array to query individual addresses
SELECT 
    c.id,
    c.info ->> 'name' AS customer_name,
    jsonb_array_elements(c.info -> 'addresses') AS address
FROM customers c;

Ergebnis:

id | customer_name | address
---+---------------+------------------------------------------------------
1  | Alice Smith   | {"city": "San Francisco", "type": "home", "state": "NY"}
1  | Alice Smith   | {"city": "Oakland", "type": "work", "state": "CA"}
2  | Bob Johnson   | {"city": "Seattle", "type": "home", "state": "WA"}

Mit entpackten Arrays filtern

-- Find customers with addresses in CA
SELECT DISTINCT
    c.id,
    c.info ->> 'name' AS customer_name
FROM customers c,
     jsonb_array_elements(c.info -> 'addresses') AS addr
WHERE addr ->> 'state' = 'CA';

Ergebnis:

id | customer_name
---+--------------
1  | Alice Smith

Auf Schlüssel und Werte prüfen

Prüfen, ob ein Schlüssel existiert

-- Find customers who have the 'orders' key
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info ? 'orders';

Ergebnis:

id | customer_name
---+--------------
2  | Bob Johnson

Auf Werte in Arrays prüfen

-- Find customers with a specific order number
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info -> 'orders' ? '101';

Ergebnis:

id | customer_name
---+--------------
2  | Bob Johnson

Prüfen, ob ein Array-Element passt

-- Find customers who have an address in Oakland (using path operators)
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info @> '{"addresses": [{"city": "Oakland"}]}';

Ergebnis:

id | customer_name
---+--------------
1  | Alice Smith

JSON-Daten indexieren

Für Produktivdatenbanken mit großen JSON-Datenmengen ist eine passende Indexierung unverzichtbar:

Einen GIN-Index für Containment-Abfragen anlegen

-- Create a GIN index for faster containment operations
CREATE INDEX idx_customers_info ON customers USING GIN (info);

Einen gezielten Index für ein JSON-Feld anlegen

-- Create an index on the 'email' field for fast lookups
CREATE INDEX idx_customers_email ON customers ((info ->> 'email'));

Indexierte Felder in Abfragen nutzen

-- This query can use the index we created above
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info ->> 'email' = 'alice@example.com';

Zwischen JSON und Tabellen konvertieren

JSON in Zeilen umwandeln (jsonb_to_record)

-- Extract JSON fields into a tabular structure
SELECT 
    id,
    rec.name,
    rec.email,
    rec.age
FROM 
    customers,
    jsonb_to_record(info) AS rec(
        name text,
        email text,
        age int
    );

Ergebnis:

id | name         | email             | age
---+--------------+-------------------+-----
1  | Alice Smith  | alice@example.com | 32
2  | Bob Johnson  | bob@example.com   | 45

Verschachtelte Arrays in Tabellen umwandeln (jsonb_to_recordset)

-- Extract addresses from all customers into a table
SELECT 
    c.id,
    c.info ->> 'name' AS customer_name,
    addr.type AS address_type,
    addr.city,
    addr.state
FROM 
    customers c,
    jsonb_to_recordset(c.info -> 'addresses') AS addr(
        type text,
        city text,
        state text
    );

Ergebnis:

id | customer_name | address_type | city          | state
---+---------------+--------------+---------------+------
1  | Alice Smith   | home         | San Francisco | NY
1  | Alice Smith   | work         | Oakland       | CA
2  | Bob Johnson   | home         | Seattle       | WA

Abfrageergebnisse in JSON umwandeln

-- Aggregate customer orders into a JSON array
SELECT
    c.id,
    c.info ->> 'name' AS customer_name,
    json_agg(o.order_id) AS orders
FROM 
    customers c
    CROSS JOIN LATERAL (
        SELECT jsonb_array_elements_text(c.info -> 'orders') AS order_id
    ) o
GROUP BY c.id, c.info ->> 'name';

Ergebnis:

id | customer_name | orders
---+---------------+----------
2  | Bob Johnson   | ["101", "102", "103"]

Hinweise zur Performance

Wenn du mit JSON in PostgreSQL arbeitest, solltest du diese Performance-Aspekte im Blick behalten:

  1. Nutze jsonb statt json: Der Typ jsonb bietet bei den meisten Operationen eine bessere Performance.

  2. Gezielt indexieren: Nutze GIN-Indizes für Containment-Abfragen, lege aber für häufig abgefragte Felder eigene Indizes an.

  3. Denormalisierung gut abwägen: JSON erlaubt dir zwar, dein Datenmodell zu denormalisieren, doch zu tiefe Verschachtelung kann die Abfrage-Performance beeinträchtigen.

  4. Abfragemuster im Blick behalten: Komplexe JSON-Pfadausdrücke oder häufiges Entpacken großer Arrays können teure Operationen sein.

  5. Array-Größe begrenzen: Sehr große JSON-Arrays können beim Entpacken zu Performance-Problemen führen.

  6. Projektion nutzen: Extrahiere nur die Felder, die du brauchst, statt das gesamte JSON-Dokument zurückzugeben.

Fazit

Dank seiner JSON-Funktionen ist PostgreSQL eine hervorragende Wahl für Anwendungen, die halbstrukturierte Daten speichern und abfragen müssen. Mit den Operatoren und Funktionen aus diesem Tutorial kannst du effektiv mit JSON-Daten arbeiten und gleichzeitig die Leistung und Zuverlässigkeit einer ausgereiften relationalen Datenbank nutzen.

Für komplexe Datenmodelle lohnt sich ein hybrider Ansatz: Nutze strukturierte Tabellen für feste Schemas und häufig abgefragte Daten und JSON für flexible, schemalose Daten oder verschachtelte Strukturen, die sich relational nur umständlich modellieren lassen.

Willst du die Beispiele selbst ausprobieren? Öffne Beekeeper Studio und entdecke noch heute die JSON-Funktionen von PostgreSQL.

Beekeeper Studio ist eine kostenlose & quelloffene Datenbank-GUI

Das beste SQL-Abfrage- & Editor-Tool, das ich je benutzt habe. Es bietet alles, was ich zum Verwalten meiner Datenbank brauche. - ⭐⭐⭐⭐⭐ Mit

Beekeeper Studio ist schnell, intuitiv und einfach zu bedienen. Beekeeper unterstützt jede Menge Datenbanken und läuft hervorragend auf Windows, Mac und Linux.

Die Linux-Version von Beekeeper hat 100% des Funktionsumfangs, ohne Abstriche und ohne Kompromisse.

Was Nutzer über Beekeeper Studio sagen

★★★★★
„Beekeeper Studio hat meinen alten SQL-Workflow komplett ersetzt. Es ist schnell, intuitiv und macht die Arbeit mit Datenbanken wieder zum Vergnügen.“
— Alex K., Datenbankentwickler
★★★★★
„Ich habe viele Datenbank-GUIs ausprobiert, aber Beekeeper trifft die perfekte Balance zwischen Funktionsumfang und Einfachheit. Es funktioniert einfach.“
— Sarah M., Full-Stack-Entwicklerin

Bereit, deinen SQL-Workflow zu verbessern?

download Kostenlos herunterladen