JSON-Daten mit mssql-python verwenden

Microsoft SQL 2016 und spätere Versionen sowie Azure SQL bieten JSON-Unterstützung über Funktionen, die auf nvarchar Spalten arbeiten. Der mssql-python-Treiber sendet und empfängt JSON als reguläre Python-Strings. Sie haben folgende Möglichkeiten:

  • Speichere JSON als Strings in Spalten nvarchar .
  • Abfrage von JSON mit Pfadausdrücken mit JSON_VALUE, JSON_QUERY, und OPENJSON.
  • Relationale Daten mit FOR JSON in JSON umwandeln.
  • JSON mit OPENJSON in ein relationales Format analysieren.

Note

Microsoft SQL speichert JSON-Daten in Spalten, nicht in nvarchar einem speziellen JSON-Spaltentyp. Der mssql-python-Treiber sendet und empfängt JSON als reguläre Strings. Nutze das integrierte json Modul von Python, um auf der Client-Seite zu serialisieren und zu deserialisieren.

JSON-Daten speichern

Serialisieren Sie Python-Dictionaries in Strings json.dumps(), bevor Sie sie in nvarchar-Spalten einfügen.

JSON-String einfügen

Speichere ein Python-Wörterbuch als JSON-Text in einer Datenbanktabelle:

import json
import mssql_python

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDefault;"
    "Encrypt=yes"
)
cursor = conn.cursor()

# Create table with JSON column
cursor.execute("""
    CREATE TABLE #JsonProducts (
        ProductID INT IDENTITY PRIMARY KEY,
        Name NVARCHAR(100),
        JsonData NVARCHAR(MAX)
    )
""")

# Python dict to JSON string
product_data = {
    "name": "Widget Pro",
    "specs": {
        "weight": 2.5,
        "dimensions": {"width": 10, "height": 5, "depth": 3}
    },
    "tags": ["electronics", "gadgets", "bestseller"]
}

cursor.execute("""
    INSERT INTO #JsonProducts (Name, JsonData)
    VALUES (%(name)s, %(json)s)
""", {"name": "Widget Pro", "json": json.dumps(product_data)})
conn.commit()

JSON beim Einfügen validieren

Verwenden Sie die Funktion, ISJSON() um die JSON-Syntax zu validieren, bevor Sie einfügen:

data = {"name": "Widget", "specs": {"weight": 1.5}}

cursor.execute("""
    CREATE TABLE #JsonValidate (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonValidate (Name, JsonData)
    SELECT %(name)s, %(json)s
    WHERE ISJSON(%(json)s) = 1
""", {"name": "Widget", "json": json.dumps(data)})

if cursor.rowcount == 0:
    raise ValueError("Invalid JSON data")

Abfragen von JSON-Daten

Verwenden Sie Microsoft SQL JSON-Pfadfunktionen, um Werte auf dem Server zu extrahieren, bevor Sie sie an den Client zurückgeben.

Skalare Werte extrahieren

Verwendung JSON_VALUE zum Extrahieren einzelner Werte:

# Create table with sample JSON data
cursor.execute("""
    CREATE TABLE #JsonExtract (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonExtract (Name, JsonData) VALUES (
        'Widget Pro',
        '{"name":"Widget Pro","specs":{"weight":2.5,"dimensions":{"width":10,"height":5,"depth":3}},"tags":["electronics","gadgets"]}'
    )
""")

cursor.execute("""
    SELECT 
        Name,
        JSON_VALUE(JsonData, '$.specs.weight') AS Weight,
        JSON_VALUE(JsonData, '$.specs.dimensions.width') AS Width
    FROM #JsonExtract
    WHERE JSON_VALUE(JsonData, '$.name') = %(name)s
""", {"name": "Widget Pro"})

row = cursor.fetchone()
print(f"Weight: {row.Weight}, Width: {row.Width}")

Objekte oder Arrays extrahieren

Verwenden Sie JSON_QUERY für Objekte und Arrays.

cursor.execute("""
    CREATE TABLE #JsonQuery (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonQuery (Name, JsonData) VALUES (
        'Widget Pro',
        '{"specs":{"weight":2.5,"color":"blue"},"tags":["electronics","gadgets"]}'
    )
""")

cursor.execute("""
    SELECT 
        Name,
        JSON_QUERY(JsonData, '$.specs') AS Specs,
        JSON_QUERY(JsonData, '$.tags') AS Tags
    FROM #JsonQuery
""")

for row in cursor:
    specs = json.loads(row.Specs) if row.Specs else {}
    tags = json.loads(row.Tags) if row.Tags else []
    print(f"{row.Name}: {specs}, Tags: {tags}")

JSON-Array in Zeilen umwandeln

Erweitern Sie ein JSON-Array in Zeilen mit OPENJSON:

cursor.execute("""
    CREATE TABLE #JsonArray (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonArray (Name, JsonData) VALUES 
        ('Widget Pro', '{"tags":["electronics","gadgets","bestseller"]}'),
        ('Gadget X', '{"tags":["tools","gadgets"]}')
""")

cursor.execute("""
    SELECT p.Name, t.value AS Tag
    FROM #JsonArray p
    CROSS APPLY OPENJSON(p.JsonData, '$.tags') t
""")

for row in cursor:
    print(f"Product: {row.Name}, Tag: {row.Tag}")

JSON-Objekt in Spalten analysieren

Einzelne Felder aus JSON-Objekten mithilfe von JSON_VALUE() extrahieren und die Ergebnisse in geeignete SQL-Typen umwandeln.

cursor.execute("""
    CREATE TABLE #JsonCols (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonCols (Name, JsonData) VALUES (
        'Widget Pro',
        '{"name":"Widget Pro","specs":{"weight":2.5,"dimensions":{"width":10,"height":5}}}'
    )
""")

cursor.execute("""
    SELECT 
        p.ProductID,
        j.name AS ProductName,
        j.weight,
        j.width,
        j.height
    FROM #JsonCols p
    CROSS APPLY OPENJSON(p.JsonData)
    WITH (
        name NVARCHAR(100) '$.name',
        weight DECIMAL(5,2) '$.specs.weight',
        width INT '$.specs.dimensions.width',
        height INT '$.specs.dimensions.height'
    ) j
""")

JSON-Daten modifizieren

Verwenden Sie JSON_MODIFY , um einen bestimmten Pfad in einem JSON-Dokument zu aktualisieren, ohne den gesamten Wert neu zu schreiben.

JSON-Wert aktualisieren

Ändern Sie eine einzelne JSON-Eigenschaft mit JSON_MODIFY:

cursor.execute("""
    CREATE TABLE #JsonMod (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonMod (Name, JsonData) VALUES (
        'Widget Pro',
        '{"specs":{"weight":2.5,"dimensions":{"width":10}},"tags":["electronics"]}'
    )
""")

cursor.execute("""
    UPDATE #JsonMod
    SET JsonData = JSON_MODIFY(JsonData, '$.specs.weight', %(weight)s)
    WHERE ProductID = %(id)s
""", {"weight": 3.0, "id": 1})
conn.commit()

JSON-Eigenschaft hinzufügen

Füge eine neue Eigenschaft in ein bestehendes JSON-Objekt ein:

cursor.execute("""
    CREATE TABLE #JsonAdd (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonAdd (Name, JsonData) VALUES (
        'Widget Pro', '{"specs":{"weight":2.5}}'
    )
""")

cursor.execute("""
    UPDATE #JsonAdd
    SET JsonData = JSON_MODIFY(JsonData, '$.specs.color', %(color)s)
    WHERE ProductID = %(id)s
""", {"color": "blue", "id": 1})

JSON-Eigenschaft entfernen

Löschen Sie eine Eigenschaft aus einem JSON-Objekt, indem Sie sie auf NULLsetzen:

cursor.execute("""
    CREATE TABLE #JsonRem (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonRem (Name, JsonData) VALUES (
        'Widget Pro', '{"specs":{"weight":2.5,"color":"blue"}}'
    )
""")

cursor.execute("""
    UPDATE #JsonRem
    SET JsonData = JSON_MODIFY(JsonData, '$.specs.color', NULL)
    WHERE ProductID = %(id)s
""", {"id": 1})

Zu JSON-Array hinzufügen

Fügen Sie am Ende eines JSON-Arrays unter Verwendung der Direktive append in JSON_MODIFY einen neuen Wert hinzu:

cursor.execute("""
    CREATE TABLE #JsonAppend (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonAppend (Name, JsonData) VALUES (
        'Widget Pro', '{"tags":["electronics","gadgets"]}'
    )
""")

cursor.execute("""
    UPDATE #JsonAppend
    SET JsonData = JSON_MODIFY(
        JsonData, 
        'append $.tags', 
        %(tag)s
    )
    WHERE ProductID = %(id)s
""", {"tag": "new-arrival", "id": 1})

Konvertieren relationaler Daten in JSON

Die Klausel FOR JSON wandelt Anfrageergebnisse auf der Serverseite in eine JSON-Zeichenkette um.

FÜR JSON AUTO

JSON aus den Abfrageergebnissen generieren:

cursor.execute("""
    SELECT TOP 5 o.SalesOrderID, p.LastName AS CustomerName, o.TotalDue
    FROM Sales.SalesOrderHeader o
    JOIN Sales.Customer c ON o.CustomerID = c.CustomerID
    JOIN Person.Person p ON c.PersonID = p.BusinessEntityID
    FOR JSON AUTO
""")

# Result is a single string containing JSON
json_result = cursor.fetchval()
orders = json.loads(json_result)
print(json.dumps(orders, indent=2))

FÜR JSON-PFAD

Erhalten Sie mehr Kontrolle über die JSON-Struktur:

cursor.execute("""
    SELECT 
        o.SalesOrderID AS 'order.id',
        o.OrderDate AS 'order.date',
        p.LastName AS 'customer.name',
        e.EmailAddress AS 'customer.email'
    FROM Sales.SalesOrderHeader o
    JOIN Sales.Customer c ON o.CustomerID = c.CustomerID
    JOIN Person.Person p ON c.PersonID = p.BusinessEntityID
    JOIN Person.EmailAddress e ON p.BusinessEntityID = e.BusinessEntityID
    WHERE o.SalesOrderID = %(id)s
    FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
""", {"id": 43659})

json_result = cursor.fetchval()
order = json.loads(json_result)
# Structure: {"order": {"id": 43659, "date": "..."}, "customer": {"name": "...", "email": "..."}}

Geschachteltes JSON

Abfragen Sie Datenstrukturen mit verschachtelten JSON-Arrays und Objekten, indem Sie Unterabfragen FOR JSON verwenden, um hierarchische JSON-Ausgaben zu erstellen.

cursor.execute("""
    SELECT TOP 3
        c.CustomerID,
        p.LastName AS CustomerName,
        (SELECT TOP 3 o.SalesOrderID, o.TotalDue
         FROM Sales.SalesOrderHeader o
         WHERE o.CustomerID = c.CustomerID
         FOR JSON PATH) AS Orders
    FROM Sales.Customer c
    JOIN Person.Person p ON c.PersonID = p.BusinessEntityID
    WHERE c.PersonID IS NOT NULL
    FOR JSON PATH
""")

json_result = cursor.fetchval()
customers = json.loads(json_result)
# Each customer has nested Orders array

Python-Integrationsmuster

Diese Muster zeigen, wie man Python-Abstraktionen über JSON-unterstützten Tabellen baut.

Repository-Muster mit JSON

Implementieren Sie eine Datenzugriffsschicht, die Python-Objekte serialisiert und deserialisiert in JSON-Spalten, wodurch eine typsichere Schnittstelle zur Datenbank bereitgestellt wird.

from dataclasses import dataclass, asdict
from typing import Optional
import json

@dataclass
class ProductSpecs:
    weight: float
    color: str
    dimensions: dict

@dataclass
class Product:
    id: Optional[int]
    name: str
    specs: ProductSpecs

class ProductRepository:
    def __init__(self, connection):
        self.conn = connection
        cursor = self.conn.cursor()
        cursor.execute("""
            IF OBJECT_ID('#JsonRepo') IS NULL
                CREATE TABLE #JsonRepo (
                    ProductID INT IDENTITY PRIMARY KEY,
                    Name NVARCHAR(100),
                    JsonData NVARCHAR(MAX)
                )
        """)
        self.conn.commit()
    
    def save(self, product: Product) -> int:
        cursor = self.conn.cursor()
        specs_json = json.dumps(asdict(product.specs))
        
        if product.id:
            cursor.execute("""
                UPDATE #JsonRepo SET Name = %(name)s, JsonData = %(json)s
                WHERE ProductID = %(id)s
            """, {"name": product.name, "json": specs_json, "id": product.id})
        else:
            cursor.execute("""
                INSERT INTO #JsonRepo (Name, JsonData)
                OUTPUT INSERTED.ProductID
                VALUES (%(name)s, %(json)s)
            """, {"name": product.name, "json": specs_json})
            product.id = cursor.fetchval()
        
        self.conn.commit()
        return product.id
    
    def get(self, product_id: int) -> Optional[Product]:
        cursor = self.conn.cursor()
        cursor.execute("""
            SELECT ProductID, Name, JsonData FROM #JsonRepo WHERE ProductID = %(id)s
        """, {"id": product_id})
        
        row = cursor.fetchone()
        if row is None:
            return None
        
        specs_data = json.loads(row.JsonData)
        return Product(
            id=row.ProductID,
            name=row.Name,
            specs=ProductSpecs(**specs_data)
        )

Verbinde dich mit der Datenbank, erstelle dann das Repository und nutze es, um ein Produkt zu speichern und abzurufen. Die Methode save() verwendet den Zweig INSERT, wenn idNone ist, und andernfalls den Zweig UPDATE:

conn = mssql_python.connect(connection_string)

repo = ProductRepository(conn)

# id is None, so save() inserts a new row and returns the generated ProductID.
product = Product(
    id=None,
    name="Widget Pro",
    specs=ProductSpecs(weight=2.5, color="black", dimensions={"width": 10, "height": 5})
)
product_id = repo.save(product)
print(f"Saved product {product_id}")

# Read the product back into a typed Product object.
loaded = repo.get(product_id)
print(loaded)

conn.close()

Das Repository legt #JsonRepo als lokale temporäre Tabelle an, die auf die von dir übergebene Verbindung beschränkt ist; daher müssen save() und get() dieselbe Verbindung verwenden. Die Tabelle wird gelöscht, wenn die Verbindung geschlossen wird.

Effiziente Verarbeitung großer JSON-Ergebnisse

Wenn JSON-Ergebnisse groß sind, rufe sie in Teilen über mehrere Zeilen hinweg.

def fetch_json_in_parts(cursor, query: str, params: dict) -> list:
    """Handle JSON results that might span multiple rows."""
    cursor.execute(query, params)
    
    # FOR JSON might split large results across rows
    json_parts = []
    for row in cursor:
        json_parts.append(row[0])
    
    # Combine parts
    json_string = "".join(json_parts)
    return json.loads(json_string) if json_string else []

# Usage
data = fetch_json_in_parts(cursor, "SELECT TOP 100 * FROM Production.Product FOR JSON AUTO", {})

Konvertiere Abfrageergebnisse in JSON in Python

Relationale Abfrageergebnisse in Python in JSON-Format umwandeln, indem jede Zeile in ein Wörterbuch umgewandelt und dann in JSON serialisiert wird.

def query_to_json(cursor, query: str, params: dict = None) -> str:
    """Execute query and return results as JSON string."""
    cursor.execute(query, params or {})
    columns = [col[0] for col in cursor.description]
    
    rows = []
    for row in cursor:
        rows.append(dict(zip(columns, row)))
    
    return json.dumps(rows, default=str, indent=2)

# Usage
json_output = query_to_json(cursor, "SELECT TOP 5 ProductID, Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = %(cat)s", {"cat": 1})
print(json_output)

Indizieren von JSON-Daten

Erstellen Sie eine berechnete Spalte, die von einem JSON-Pfadausdruck unterstützt wird, um den Pfad indexierbar zu machen.

Berechnete Spalte mit Index

Definieren Sie eine berechnete Spalte, die einen JSON-Wert extrahiert, und wenden Sie einen Index darauf an, um auf häufig abgefragten JSON-Pfaden effizient zu filtern. Das folgende Beispiel erstellt eine permanente Tabelle, fügt eine persistent berechnete Spalte über den JSON-Pfad $.specs.weight hinzu und erstellt einen Index darauf.

cursor.execute("""
    IF OBJECT_ID('dbo.ProductCatalog', 'U') IS NOT NULL
        DROP TABLE dbo.ProductCatalog
""")
cursor.execute("""
    CREATE TABLE dbo.ProductCatalog (
        ProductID   INT IDENTITY PRIMARY KEY,
        Name        NVARCHAR(100),
        JsonData    NVARCHAR(MAX)
    )
""")

# Insert sample rows with JSON data
rows = [
    ("Widget Pro",   '{"specs":{"weight":2.5,"color":"blue"}}'),
    ("Gadget X",     '{"specs":{"weight":0.8,"color":"red"}}'),
    ("Heavy Duty",   '{"specs":{"weight":9.1,"color":"gray"}}'),
]
cursor.executemany(
    "INSERT INTO dbo.ProductCatalog (Name, JsonData) VALUES (%(name)s, %(json)s)",
    [{"name": n, "json": j} for n, j in rows]
)
conn.commit()

# Add a persisted computed column that extracts weight from JSON
cursor.execute("""
    ALTER TABLE dbo.ProductCatalog
    ADD ProductWeight AS CAST(JSON_VALUE(JsonData, '$.specs.weight') AS DECIMAL(5,2)) PERSISTED
""")

# Index the computed column for efficient range queries
cursor.execute("""
    CREATE INDEX IX_ProductCatalog_Weight
    ON dbo.ProductCatalog (ProductWeight)
""")
conn.commit()

Abfrage mit indizierter berechneter Spalte

Filtern Sie direkt nach der berechneten Spalte. Die Abfrage-Engine verwendet den Index, anstatt jedes JSON-Dokument zu scannen und zu parsen.

cursor.execute("""
    SELECT Name, ProductWeight
    FROM dbo.ProductCatalog
    WHERE ProductWeight > %(min_weight)s
    ORDER BY ProductWeight
""", {"min_weight": 1.0})

for row in cursor:
    print(f"{row.Name}: {row.ProductWeight} kg")

# Cleanup
cursor.execute("DROP TABLE dbo.ProductCatalog")
conn.commit()

Wählen Sie zwischen relationalen Spalten und JSON-Speicher

Verwenden Sie relationale Spalten, wenn Daten ein festes Schema haben, referenzielle Integrität benötigen, an JOINs teilnehmen oder häufig in WHERE-Klauseln erscheinen. Verwenden Sie JSON-Spalten (nvarchar(max)), wenn Daten spärlich sind, sich über Zeilen unterscheiden oder flexible Konfigurationen oder Metadaten darstellen.

Wann soll man serverseitige versus clientseitige JSON-Verarbeitung verwenden

Verwenden Sie Microsoft SQL JSON-Funktionen (JSON_VALUE, JSON_QUERY, OPENJSON), wenn Sie zwischen JSON-Feldern filtern, indexieren oder aggregieren müssen, ohne jede Zeile zum Client zu holen. Diese Wahl trifft sich, wenn nur eine Teilmenge von Zeilen Ihren Kriterien entspricht oder wenn Sie berechnete Spaltenindizes auf JSON-Pfaden wünschen.

Verwenden Sie clientseitige Python-Verarbeitung (json.loads()), wenn Sie gesamte Dokumente abrufen und in der Anwendungslogik verarbeiten. Dieser Ansatz funktioniert gut, wenn man das vollständige Dokument benötigt und nicht nach JSON-Feldern in der Datenbank filtert.

Dokumentenähnliche Arbeitsabläufe

Wenn Ihre Anwendung ganze Dokumente speichert und abruft, verwenden Sie Python-seitige Serialisierung und behandeln Sie die JSON-Spalte als undurchsichtigen Speicher. Verarbeiten und Abfragen der Dokumente in Python, indem Sie vollständige JSON-Blobs abrufen und deserialisieren:

import json

# Create the settings table
cursor.execute("""
    CREATE TABLE #Settings (
        UserID INT PRIMARY KEY,
        ConfigJson NVARCHAR(MAX)
    )
""")

# Store a configuration document
config = {
    "theme": "dark",
    "notifications": {"email": True, "sms": False},
    "custom_fields": {"department": "Engineering", "cost_center": "CC-100"}
}

cursor.execute(
    "INSERT INTO #Settings (UserID, ConfigJson) VALUES (%(uid)s, %(cfg)s)",
    {"uid": 1, "cfg": json.dumps(config)}
)

# Retrieve and process in Python
cursor.execute("SELECT ConfigJson FROM #Settings WHERE UserID = %(uid)s", {"uid": 1})
row = cursor.fetchone()
config = json.loads(row.ConfigJson)
print(config["notifications"]["email"])  # True

Serverseitige JSON-Abfragen

Verwenden Sie Microsoft SQL JSON-Funktionen, wenn Sie filtern, indexieren oder über JSON-Felder hinweg aggregieren müssen, ohne jede Zeile abzurufen. Dieser Ansatz ist effizienter, als alle Zeilen in Python zu laden, um sie im Speicher zu filtern:

  • JSON_VALUE extrahiert skalare Werte und kann berechnete Spaltenindizes zurückführen.
  • JSON_QUERY Extrahiert Objekte und Arrays.
  • OPENJSON entpackt JSON in Zeilen für JOINs und Aggregationen.
  • JSON_MODIFY aktualisiert bestimmte Pfade, ohne das gesamte Dokument neu zu schreiben.
# Filter by a JSON field server-side
cursor.execute("""
    SELECT UserID, ConfigJson
    FROM #Settings
    WHERE JSON_VALUE(ConfigJson, '$.custom_fields.department') = %(dept)s
""", {"dept": "Engineering"})

Für häufig abgefragte JSON-Pfade erstellen Sie eine berechnete Spalte mit einem Index:

ALTER TABLE Settings
ADD Department AS JSON_VALUE(ConfigJson, '$.custom_fields.department');

CREATE INDEX IX_Settings_Department ON Settings(Department);

Bewährte Methoden

Wenden Sie diese Richtlinien an, um JSON-Spalten zuverlässig zu verwenden.

Validiere JSON vor der Speicherung

Validiere JSON sowie Tabellen-/Spaltenkennungen vor dem Speichern, um Injektionsangriffe zu verhindern.

def store_json_safely(cursor, table: str, json_column: str, data: dict):
    """Store JSON with validation."""
    # Validate identifiers to prevent SQL injection
    import re
    if not re.match(r'^[A-Za-z_][A-Za-z0-9_.]*$', table):
        raise ValueError(f"Invalid table name: {table}")
    if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', json_column):
        raise ValueError(f"Invalid column name: {json_column}")

    json_str = json.dumps(data)
    
    # Check if valid JSON in Microsoft SQL
    cursor.execute("SELECT ISJSON(%(json)s)", {"json": json_str})
    if cursor.fetchval() != 1:
        raise ValueError("Invalid JSON")
    
    cursor.execute(f"INSERT INTO {table} ({json_column}) VALUES (%(json)s)", {"json": json_str})

Verwende JSON nicht zu viel

Verwenden Sie JSON-Spalten für flexible oder spärliche Daten, wie Benutzerpräferenzen oder benutzerdefinierte Felder. Verwenden Sie relationale Spalten für:

  • Häufig abgefragte Daten.
  • Daten, die referenzielle Integrität benötigen.
  • Spalten, die in WHERE-Klauseln verwendet werden.

Behandle None/NULL richtig

Behandle fehlende oder optionale JSON-Felder, indem du NULL-Werte für Spalten einfügst, die keine Daten enthalten.

cursor.execute("""
    CREATE TABLE #JsonOpt (
        ProductID INT IDENTITY, Name NVARCHAR(100), JsonData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #JsonOpt (Name, JsonData) VALUES (
        'Widget Pro', '{"required_field":"value"}'
    )
""")

cursor.execute("""
    SELECT 
        Name,
        JSON_VALUE(JsonData, '$.optional_field') AS OptionalValue
    FROM #JsonOpt
""")

for row in cursor:
    # JSON_VALUE returns NULL if path doesn't exist
    value = row.OptionalValue or "default"
    print(f"{row.Name}: {value}")