Raw SQL-Abfragen in mssql-django

In diesem Artikel wird erläutert, wie Roh-SQL-Abfragen für SQL Server aus Django-Anwendungen ausgeführt werden. Raw SQL ist nützlich für Vorgänge, die nicht über django ORM verfügbar gemacht werden, z. B. komplexe Transact-SQL (T-SQL), räumliche Abfragen oder leistungskritische Vorgänge.

Verwenden Sie connection.cursor()

Greifen Sie direkt über das Django-Objekt auf den Datenbankcursor connection zu:

from django.db import connection

def get_server_version():
    with connection.cursor() as cursor:
        cursor.execute("SELECT @@VERSION;")
        row = cursor.fetchone()
    return row[0]

Die with Anweisung stellt sicher, dass der Cursor nach der Verwendung ordnungsgemäß geschlossen wird.

Parametrisierte Abfragen

Verwenden Sie parametrisierte Abfragen immer, um die SQL-Einfügung zu verhindern. Übergeben Sie Parameter als Liste:

Note

In den folgenden Beispielen wird die standardmäßige Benennungskonvention <app_label>_<model_name> für Tabellen von Django verwendet (z. B myapp_product. ). Wenn Sie db_table im Meta eines Modells überschreiben, ersetzen Sie diesen Namen. Sie können den aufgelösten Namen auch zur Laufzeit mit Product._meta.db_table auslesen.

from django.db import connection

def get_products_by_price(min_price, max_price):
    with connection.cursor() as cursor:
        cursor.execute(
            "SELECT id, name, price FROM myapp_product WHERE price BETWEEN %s AND %s;",
            [min_price, max_price],
        )
        results = cursor.fetchall()
    return results

Important

Verwenden Sie niemals Zeichenfolgenformatierungen oder F-Zeichenfolgen, um Werte in SQL-Abfragen einzubetten. Verwenden Sie immer parametrisierte Abfragen (%s Platzhalter mit einer Parameterliste), um die SQL-Einfügung zu verhindern.

Ergebnisse abrufen

Der Cursor von Django bietet mehrere Methoden zum Abrufen von Ergebnissen:

from django.db import connection

def demonstrate_fetch_methods():
    with connection.cursor() as cursor:
        cursor.execute("SELECT id, name FROM myapp_product;")

        # Fetch one row
        row = cursor.fetchone()

        # Fetch the next 10 rows (continues from where fetchone stopped)
        rows = cursor.fetchmany(10)

        # Fetch all remaining rows (continues from where fetchmany stopped)
        all_rows = cursor.fetchall()

Zurückgeben von Ergebnissen als Wörterbücher

Konvertieren von Zeilen in Wörterbücher mithilfe von cursor.description:

from django.db import connection

def dictfetchall(cursor):
    columns = [col[0] for col in cursor.description]
    return [dict(zip(columns, row)) for row in cursor.fetchall()]

def get_all_products():
    with connection.cursor() as cursor:
        cursor.execute("SELECT id, name, price FROM myapp_product;")
        return dictfetchall(cursor)

Verwenden von Manager.raw() für Modellabfragen

Wenn Sie rohes SQL verwenden, aber weiterhin Django-Modellinstanzen möchten, verwenden Sie Manager.raw():

from myapp.models import Product

products = Product.objects.raw(
    "SELECT id, name, price FROM myapp_product WHERE price > %s",
    [10.00],
)

for product in products:
    print(f"{product.name}: ${product.price}")

Die Abfrage muss alle felder zurückgeben, die im Primärschlüssel des Modells definiert sind. Zusätzliche Felder werden bei Bedarf geladen.

DDL-Anweisungen ausführen

Verwenden Sie raw SQL für Schemavorgänge, die Django nicht direkt unterstützt:

from django.db import connection

def create_index():
    with connection.cursor() as cursor:
        cursor.execute(
            "CREATE INDEX IX_product_name ON myapp_product (name) "
            "INCLUDE (price);"
        )

Mehrere Datenbankverbindungen

Wenn Sie mehrere Datenbanken verwenden, geben Sie an, welche Verbindung verwendet werden soll:

from django.db import connections

def query_reporting_db():
    with connections["reporting"].cursor() as cursor:
        cursor.execute("SELECT COUNT(*) FROM myapp_product;")
        return cursor.fetchone()[0]