# Django 5.2.8 documentation

# Utföra SQL-frågor i råformat

Django gives you two ways of performing raw SQL queries: you can use `Manager.raw()` to perform raw queries and return model instances, or you can avoid the model layer entirely and execute custom SQL directly.

Utforska ORM innan du använder rå SQL!

Django ORM tillhandahåller många verktyg för att uttrycka frågor utan att skriva rå SQL. Till exempel:

- Den QuerySet API är omfattande.

- Du kan `annotera` och aggregera med hjälp av många inbyggda databasfunktioner. Utöver dessa kan du skapa custom query expressions.

Innan du använder rå SQL bör du utforska ORM. Fråga på en av supportkanalerna för att se om ORM stöder ditt användningsfall.

Varning

Du bör vara mycket försiktig när du skriver rå SQL. Varje gång du använder det bör du på rätt sätt undkomma alla parametrar som användaren kan kontrollera genom att använda `params` för att skydda mot SQL-injektionsattacker. Läs gärna mer om SQL injection protection.

## Utföra råa förfrågningar

Hanteringsmetoden `raw()` kan användas för att utföra råa SQL-frågor som returnerar modellinstanser:

Manager.raw(raw_query, params=(), translations=None)

Den här metoden tar en rå SQL-fråga, kör den och returnerar en `django.db.models.query.RawQuerySet`-instans. Denna `RawQuerySet`-instans kan itereras över som en normal `QuerySet` för att tillhandahålla objektinstanser.

Detta illustreras bäst med ett exempel. Anta att du har följande modell:

    class Person(models.Model):
        first_name = models.CharField(...)
        last_name = models.CharField(...)
        birth_date = models.DateField(...)

Du kan sedan köra anpassad SQL på följande sätt:

    >>> for p in Person.objects.raw("SELECT * FROM myapp_person"):
    ...     print(p)
    ...
    John Smith
    Jane Jones

Det här exemplet är inte särskilt spännande - det är exakt samma sak som att köra `Person.objects.all()`. Men `raw()` har en massa andra alternativ som gör den mycket kraftfull.

Namn på modelltabeller

Varifrån kom namnet på tabellen `Person` i det exemplet?

Som standard räknar Django ut ett databastabellnamn genom att ansluta modellens ”appetikett” - det namn du använde i `manage.py startapp` - till modellens klassnamn, med ett understreck mellan dem. I exemplet har vi antagit att modellen `Person` lever i en app som heter `myapp`, så dess tabell skulle vara `myapp_person`.

Mer information finns i dokumentationen för alternativet `db_table`, där du också kan ange databasens tabellnamn manuellt.

Varning

Ingen kontroll görs på SQL-satsen som skickas in till `.raw()`. Django förväntar sig att satsen kommer att returnera en uppsättning rader från databasen, men gör ingenting för att genomdriva det. Om frågan inte returnerar rader, kommer ett (eventuellt kryptiskt) fel att uppstå.

Varning

Om du utför frågor på MySQL, observera att MySQL: s tysta typcoercion kan orsaka oväntade resultat när du blandar typer. Om du ställer en fråga på en kolumn av strängtyp, men med ett heltalsvärde, kommer MySQL att tvinga typerna för alla värden i tabellen till ett heltal innan jämförelsen utförs. Om din tabell till exempel innehåller värdena `'abc'`, `'def'` och du frågar efter `WHERE mycolumn=0`, kommer båda raderna att matcha. För att förhindra detta måste du utföra korrekt typecasting innan du använder värdet i en fråga.

### Mappning av frågefält till modellfält

`raw()` mappar automatiskt fält i frågan till fält i modellen.

Ordningen på fälten i din fråga spelar ingen roll. Med andra ord fungerar båda följande frågor på samma sätt:

    >>> Person.objects.raw("SELECT id, first_name, last_name, birth_date FROM myapp_person")
    >>> Person.objects.raw("SELECT last_name, birth_date, first_name, id FROM myapp_person")

Matchningen görs med hjälp av namn. Det innebär att du kan använda SQL:s `AS`-klausuler för att mappa fält i frågan till modellfält. Så om du hade någon annan tabell som hade `Person`-data i den, kan du enkelt mappa den till `Person`-instanser:

    >>> Person.objects.raw(
    ...     """
    ...     SELECT first AS first_name,
    ...            last AS last_name,
    ...            bd AS birth_date,
    ...            pk AS id,
    ...     FROM some_other_table
    ...     """
    ... )

Så länge namnen stämmer överens kommer modellinstanserna att skapas på rätt sätt.

Alternativt kan du mappa fält i frågan till modellfält med hjälp av argumentet `translations` till `raw()`. Detta är en ordbok som mappar namn på fält i frågan till namn på fält i modellen. Till exempel kan ovanstående fråga också skrivas:

    >>> name_map = {"first": "first_name", "last": "last_name", "bd": "birth_date", "pk": "id"}
    >>> Person.objects.raw("SELECT * FROM some_other_table", translations=name_map)

### Indexuppslagningar

`raw()` stöder indexering, så om du bara behöver det första resultatet kan du skriva:

    >>> first_person = Person.objects.raw("SELECT * FROM myapp_person")[0]

Indexeringen och skivningen utförs dock inte på databasnivå. Om du har ett stort antal `Person`-objekt i din databas är det mer effektivt att begränsa frågan på SQL-nivå:

    >>> first_person = Person.objects.raw("SELECT * FROM myapp_person LIMIT 1")[0]

### Uppskjutande av modellfält

Fält kan också utelämnas:

    >>> people = Person.objects.raw("SELECT id, first_name FROM myapp_person")

The `Person` objects returned by this query will be deferred model instances (see `defer()`). This means that the fields that are omitted from the query will be loaded on demand. For example:

    >>> for p in Person.objects.raw("SELECT id, first_name FROM myapp_person"):
    ...     print(
    ...         p.first_name,  # This will be retrieved by the original query
    ...         p.last_name,  # This will be retrieved on demand
    ...     )
    ...
    John Smith
    Jane Jones

Utåt sett ser det ut som om frågan har hämtat både förnamnet och efternamnet. Men i det här exemplet ställdes faktiskt tre frågor. Endast förnamnen hämtades av `raw()`-frågan - efternamnen hämtades båda på begäran när de skrevs ut.

Det finns bara ett fält som du inte kan utelämna - fältet för primärnyckeln. Django använder primärnyckeln för att identifiera modellinstanser, så den måste alltid inkluderas i en rå fråga. Ett `FieldDoesNotExist` undantag kommer att uppstå om du glömmer att inkludera den primära nyckeln.

### Lägga till anteckningar

Du kan också köra frågor som innehåller fält som inte är definierade i modellen. Vi kan till exempel använda PostgreSQL’s age() function för att få en lista över personer med deras åldrar beräknade av databasen:

    >>> people = Person.objects.raw("SELECT *, age(birth_date) AS age FROM myapp_person")
    >>> for p in people:
    ...     print("%s is %s." % (p.first_name, p.age))
    ...
    John is 37.
    Jane is 42.
    ...

Du kan ofta undvika att använda rå SQL för att beräkna annoteringar genom att istället använda ett Func()-uttryck.

### Överföra parametrar till `raw()`

Om du behöver utföra parametriserade frågor kan du använda argumentet `params` till `raw()`:

    >>> lname = "Doe"
    >>> Person.objects.raw("SELECT * FROM myapp_person WHERE last_name = %s", [lname])

`params` är en lista eller en ordbok med parametrar. Du använder `%s` platshållare i frågesträngen för en lista, eller `%(key)s` platshållare för en ordbok (där `key` ersätts av en ordboksnyckel), oavsett vilken databasmotor du använder. Sådana platshållare kommer att ersättas med parametrar från argumentet `params`.

Observera

Dictionary-parametrar stöds inte med SQLite-backend; med denna backend måste du skicka parametrar som en lista.

Varning

Använd inte strängformatering på råa frågor eller citattecken i dina SQL-strängar!

Det är frestande att skriva ovanstående fråga som:

    >>> query = "SELECT * FROM myapp_person WHERE last_name = %s" % lname
    >>> Person.objects.raw(query)

Du kanske också tycker att du ska skriva din fråga så här (med citationstecken runt `%s`):

    >>> query = "SELECT * FROM myapp_person WHERE last_name = '%s'"

Gör inte något av dessa misstag.

Som diskuterats i Skydd mot SQL-injektion, genom att använda `params` argumentet och lämna platshållarna ociterade skyddar du dig från SQL injection attacks, en vanlig exploatering där angripare injicerar godtycklig SQL i din databas. Om du använder stränginterpolering eller citerar platshållaren löper du risk för SQL-injektion.

## Exekvera anpassad SQL direkt

Ibland räcker inte ens `Manager.raw()`: du kan behöva utföra frågor som inte mappar rent till modeller, eller direkt köra `UPDATE`, `INSERT` eller `DELETE`-frågor.

I dessa fall kan du alltid komma åt databasen direkt och helt undvika modellagret.

Objektet `django.db.connection` representerar standardanslutningen till databasen. För att använda databasanslutningen, anropa `connection.cursor()` för att få ett cursor-objekt. Anropa sedan `cursor.execute(sql, [params])` för att köra SQL och `cursor.fetchone()` eller `cursor.fetchall()` för att returnera de resulterande raderna.

Till exempel:

    from django.db import connection

    def my_custom_sql(self):
        with connection.cursor() as cursor:
            cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
            cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
            row = cursor.fetchone()

        return row

För att skydda mot SQL-injektion får du inte inkludera citattecken runt platshållarna `%s` i SQL-strängen.

Observera att om du vill inkludera bokstavliga procenttecken i frågan måste du dubbla dem i det fall du skickar parametrar:

    cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
    cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' AND id = %s", [self.id])

Om du använder fler än en databas kan du använda `django.db.connections` för att hämta anslutningen (och markören) för en specifik databas. `django.db.connections` är ett ordboksliknande objekt som gör att du kan hämta en specifik anslutning med hjälp av dess alias:

    from django.db import connections

    with connections["my_db_alias"].cursor() as cursor:
        # Your code here
        ...

Som standard kommer Python DB API att returnera resultat utan deras fältnamn, vilket innebär att du får en ”lista” med värden, snarare än ett ”dict”. Med en liten prestanda- och minneskostnad kan du returnera resultat som en `dict` genom att använda något liknande detta:

    def dictfetchall(cursor):
        """
        Return all rows from a cursor as a dict.
        Assume the column names are unique.
        """
        columns = [col[0] for col in cursor.description]
        return [dict(zip(columns, row)) for row in cursor.fetchall()]

Ett annat alternativ är att använda `collections.namedtuple()` från Pythons standardbibliotek. En `namedtuple` är ett tuple-liknande objekt som har fält som är tillgängliga genom attributuppslagning; det är också indexerbart och itererbart. Resultaten är oföränderliga och tillgängliga med fältnamn eller index, vilket kan vara användbart:

    from collections import namedtuple

    def namedtuplefetchall(cursor):
        """
        Return all rows from a cursor as a namedtuple.
        Assume the column names are unique.
        """
        desc = cursor.description
        nt_result = namedtuple("Result", [col[0] for col in desc])
        return [nt_result(*row) for row in cursor.fetchall()]

Exemplen `dictfetchall()` och `namedtuplefetchall()` förutsätter unika kolumnnamn, eftersom en markör inte kan skilja på kolumner från olika tabeller.

Här är ett exempel på skillnaden mellan de tre:

    >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2")
    >>> cursor.fetchall()
    ((54360982, None), (54360880, None))

    >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2")
    >>> dictfetchall(cursor)
    [{'parent_id': None, 'id': 54360982}, {'parent_id': None, 'id': 54360880}]

    >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2")
    >>> results = namedtuplefetchall(cursor)
    >>> results
    [Result(id=54360982, parent_id=None), Result(id=54360880, parent_id=None)]
    >>> results[0].id
    54360982
    >>> results[0][0]
    54360982

### Anslutningar och markörer

`connection` och `cursor` implementerar mestadels standard Python DB-API som beskrivs i PEP 249 - förutom när det gäller transaktionshantering.

Om du inte är bekant med Python DB-API, notera att SQL-satsen i `cursor.execute()` använder platshållare, `"%s"`, snarare än att lägga till parametrar direkt i SQL. Om du använder den här tekniken kommer det underliggande databasbiblioteket automatiskt att escape dina parametrar vid behov.

Observera också att Django förväntar sig platshållaren `"%s"`, inte platshållaren `"?"`, som används av SQLite Python-bindningar. Detta är för konsekvensens och sanitetens skull.

Använda en markör som kontexthanterare:

    with connection.cursor() as c:
        c.execute(...)

är likvärdig med:

    c = connection.cursor()
    try:
        c.execute(...)
    finally:
        c.close()

#### Anropa lagrade procedurer

CursorWrapper.callproc(procname, params=None, kparams=None)

  Anropar en databaslagrad procedur med det angivna namnet. En sekvens (`params`) eller ett lexikon (`kparams`) med inparametrar kan anges. De flesta databaser stöder inte `kparams`. Av Djangos inbyggda backends är det bara Oracle som stöder det.

  Till exempel, med den här lagrade proceduren i en Oracle-databas:

      CREATE PROCEDURE "TEST_PROCEDURE"(v_i INTEGER, v_text NVARCHAR2(10)) AS
          p_i INTEGER;
          p_text NVARCHAR2(10);
      BEGIN
          p_i := v_i;
          p_text := v_text;
          ...
      END;

  Detta kommer att kalla det:

      with connection.cursor() as cursor:
          cursor.callproc("test_procedure", [1, "test"])