---
title: "Fiosrúcháin SQL amh a dhéanamh"
version: 5.2
locale: ga
source: https://docs.djangoproject.com/ga/5.2/topics/db/sql/
canonical: https://djangodocs.dev/ga/5.2/topics/db/sql/
---
# Fiosrúcháin SQL amh a dhéanamh

Tugann Django dhá bhealach duit chun ceisteanna SQL amh a dhéanamh: is féidir leat: meth: Manager.raw () a úsáid chun fiosruithe amh a dhéanamh agus instancí samhail a thabhairt ar ais \_\_, nó is féidir leat an ciseal samhail a sheachaint go hiomlán agus SQL saincheaptha a fhorghníomhú go díreach \_\_.

> **Déan iniúchadh ar an ORM sula n-úsáideann tú SQL amh!**
>
> Soláthraíonn an Django ORM go leor uirlisí chun ceisteanna a chur in iúl gan SQL amh a scríobh. Mar shampla:
>
> - Tá an: doc: QuerySet API fairsing \</ref/models/querysets\>.
> - Is féidir leat: meth: annotate \<.queryset.annotate\> agus:doc: aggregate ag baint úsáide as go leor feidhmean\</topics/db/aggregation\> \</ref/models/database-functions\> na bunachar sonraí ionsuite: doc: bunachar sonraí. Taobh amuigh de na cinn, is féidir leat: doc: abairtí ceisteanna saincheapaithe' \</ref/models/expressions/\> a chruthú.
>
> Sula n-úsáidtear SQL amh, déan iniúchadh: doc: an ORM \</topics/db/index\>. Fiafraigh ar cheann de:doc: na cainéil tacaíochta 'chun a fheiceáil an dtaca\</faq/help\> íonn an ORM le do chás úsáide.

> **Warning**
>
> Ba chóir duit a bheith an-chúramach aon uair a scríobhann tú SQL amh. Gach uair a úsáideann tú é, ba cheart duit éalú i gceart aon pharaiméadair is féidir leis an úsáideoir a rialú trí params' a úsáid d'fhonn cosaint a dhéanamh ar ionsaithe insteallta SQL. \<sql-injection-protection\>Léigh tuilleadh fao:ref: Cosaint insteallta SQL .

## Fiosrúcháin amh a dhéanamh

Is féidir an modh bainisteora raw () a úsáid chun ceisteanna SQL amh a dhéanamh a thugann cásanna samhail ar ais:

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

Tógann an modh seo fiosrúchán SQL amh, cuireann sé i bhfeidhm é, agus filleann sé sampla ```Django.db.Models.Query.RawQuerySet ``ar ais. Is féidir an sampla ``RawQuerySet``` seo a athrú cosúil le gnáth:class: ~django.db.models.query.querySet chun cásanna réada a sholáthar.

Is fearr é seo a léiriú le sampla. Cuir i gcás go bhfuil an tsamhail seo a leanas agat:

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

Ansin d'fhéadfá SQL saincheaptha a fhorghníomhú mar sin:

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

Níl an sampla seo an-spreagúil - tá sé díreach mar an gcéanna le rith Person.Objects.all () . Mar sin féin, tá dornán roghanna eile ag raw () a fhágann go bhfuil sé an-chumhachtach.

> **Ainmneacha tábla múnla**
>
> Cá as a tháinig ainm an tábla Person\` sa sampla sin?
>
> De réir réamhshocraithe, déanann Django ainm tábla bunachar sonraí amach trí “lipéad aip” an tsamhail a cheangal - an t-ainm a d'úsáid tú i manage.py startapp\` \- le hainm ranga an tsamhail, le béim eatarthu. Sa sampla ghlac muid leis go gcónaíonn an tsamhail ```Person` i aip darb ainm ``myapp```, mar sin bheadh a tábla `myapp_person`.
>
> Le haghaidh tuilleadh sonraí féach ar an doiciméadú don rogha: attr: ~Options.db\_table, a ligeann duit ainm an tábla bunachar sonraí a shocrú de láimh freisin.

> **Warning**
>
> Ní dhéantar aon seiceáil ar an ráiteas SQL a chuirtear isteach chuig .raw () . Tá Django ag súil go dtabharfaidh an ráiteas sraith sraitheanna ar ais ón mbunachar sonraí, ach ní dhéanann sé aon rud chun é sin a fhorfheidhmiú. Mura bhfilleann an cheist sraitheanna ar ais, beidh earráid (b'fhéidir criptic) mar thoradh air.

> **Warning**
>
> Má tá tú ag déanamh ceisteanna ar MySQL, tabhair faoi deara go bhféadfadh foréigean cineál ciúin MySQL a bheith ina chúis le torthaí gan choinne agus cineál Má fhiosraíonn tú ar cholún cineál sreangán, ach le luach sláimhir, cuirfidh MySQL na cineálacha na luachanna go léir sa tábla a chur i gcomhar sula ndéanann tú an comparáid. Mar shampla, má tá na luachanna `'abc'`, def'\`\` i do thábla agus má fhiosraíonn tú ar `WHERE mycolumn=0`, meaitneoidh an dá shraith. Chun é seo a chosc, déan an clóscáil cheart sula n-úsáidtear an luach i bhfiosrúchán.

### Réimsí fiosrúcháin a mapáil go réimsí

Léarscáil raw () réimsí san fhiosrúchán go réimsí ar an tsamhail go huathoibríoch.

Ní cuma ord na réimsí i d'fhiosrúchán. Is é sin le rá, oibríonn an dá cheist seo a leanas go comhionann:

```pycon
>>> 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")
```

Déantar meaitseáil de réir ainm. Ciallaíonn sé seo gur féidir leat clásail AS SQL a úsáid chun réimsí a mhapáil sna réimsí fiosrúcháin go réimsí samhlacha. Mar sin dá mbeadh tábla éigin eile agat ina raibh sonraí Person\` ann, d'fhéadfá é a mhapáil go héasca i gcásanna Person\`:

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

Chomh fada agus a mheaitseálann na hainmneacha, cruthófar na cásanna samhail i gceart.

De rogha air sin, is féidir leat réimsí san fhiosrúchán a mhapáil chuig réimsí samhlacha ag baint úsáide as an argóint ```aistriúcháin ``go `raw ()```. Is foclóir é seo a mhapáil ainmneacha réimsí san fhiosrúchán ar ainmneacha réimsí ar an tsamhail. Mar shampla, d'fhéadfaí an cheist thuas a scríobh freisin:

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

### Cuardaigh innéacs

Tacaíonn raw () le hinnéacsú, mar sin mura dteastaíonn ach an chéad toradh uait is féidir leat scríobh:

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

Mar sin féin, ní dhéantar an t-innéacsú agus an slisnú ag leibhéal an bhunachar sonraí. Má tá líon mór rudaí Person\` agat i do bhunachar sonraí, tá sé níos éifeachtaí an cheist a theorannú ag an leibhéal SQL:

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

### Réimsí samhail a chur ar iarchur

Féadfar réimsí a fhágáil amach freisin:

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

Is cásanna samhail iarchurtha iad na rudaí `Person` a thugtar ar ais leis an gceist seo (féach: meth: ~django.db.models.query.queryset.defer () ). Ciallaíonn sé seo go luchtálfar na réimsí a fhágtar ón gceist ar éileamh. Mar shampla:

```pycon
>>> 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
```

Ó láithreacha seachtracha, is cosúil go bhfuil an chéad ainm agus an t-ainm deireanach aisghabháilte ag an gceist. Mar sin féin, d'eisigh an sampla seo 3 cheist i ndáiríre. Ní aisghabhadh ach na céadainmneacha tríd an bhfiosrúchán raw () \- aisghabhadh na hainmneacha deireanacha araon ar éileamh nuair a cuireadh priontáil iad.

Níl ach réimse amháin ann nach féidir leat a fhágáil amach - an príomhréimse. Úsáideann Django an príomh-eochair chun cásanna samhail a aithint, mar sin caithfear é a áireamh i gcónaí i gceist amh. A: Class: Ardófar eisceacht ~django.core.exceptions.fieldDoesNotExist má dhéanann tú dearmad an príomh-eochair a áireamh.

### Anótaí a chur leis

Is féidir leat ceisteanna a fhorghníomhú ina bhfuil réimsí nach bhfuil sainmhínithe ar an tsamhail. Mar shampla, d'fhéadfaimis feidhm aois () PostgreSQL a úsáid \_\_ chun liosta daoine a bhfuil a n-aoiseanna a ríomh ag an mbunachar sonraí a fháil:

```pycon
>>> 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.
...
```

\<func-expressions\>Is minic gur féidir leat SQL amh a úsáid chun anótaí a ríomh a sheachaint trí a: ref: Func () abairt a úsáid ina ionad sin.

### Paraiméadair a chur isteach i raw () \`\`

Más gá duit ceisteanna paraiméadair a dhéanamh, is féidir leat an argóint params\` a úsáid chun raw () \`:

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

Is liosta nó foclóir paraiméadair é params'. Úsáidfidh tú áitealbhóirí \`\`%s\` sa teaghrán fiosrúcháin le haghaidh liosta, nó `% (key) s` sealbhóirí áiteacha do fhoclóir (áit a gcuirtear eochair foclóra in ionad `eochair`), beag beann ar d'inneall bunachar sonraí. Cuirfear paraiméadair ón argóint params' in ionad sealbhóirí áiteanna den sórt sin.

> **Note**
>
> Ní thacaítear le paramaí foclóra leis an gcúltaca SQLite; leis an gcúltaca seo, ní mór duit paraiméadair a rith mar liosta.

> **Warning**
>
> \*\* Ná húsáid formáidiú teaghrán ar fhiosrúcháin amh nó luaigh sealbhóirí áiteanna i do theagáin SQL! \*\*
>
> Tá sé mealltach an cheist thuas a scríobh mar:
>
> ```pycon
> >>> query = "SELECT * FROM myapp_person WHERE last_name = %s" % lname
> >>> Person.objects.raw(query)
> ```
>
> B'fhéidir go gceapfá freisin gur chóir duit do cheist a scríobh mar seo (le luachana timpeall `%s`):
>
> ```pycon
> >>> query = "SELECT * FROM myapp_person WHERE last_name = '%s'"
> ```
>
> \*\* Ná déan ceachtar de na botúin seo. \*\*
>
> Mar a pléadh in:ref: sql-injection-protection, ag baint úsáide as an argóint params\` agus na sealbhóirí áit a fhágáil gan luaite cosnaíonn tú ó , saothrú coitianta ina ndéanann ionsaitheoirí SQL treallach a instealladh isteach i do bhunachar sonraí. Má úsáideann tú idirghabháil sreangáin nó má luann tú an sealbhóir iontu, tá tú i mbaol instealladh SQL.

## SQL saincheaptha a fhorghníomhú

Uaireanta fion:meth: ní leor Manager.raw: b'fhéidir go mbeidh ort ceisteanna nach léarscálann go glan ar mhúnlaí a dhéanamh, nó ceisteanna `UPDATE`, INSERT\`, nó DELETE\` a fhorghníomhú go díreach.

Sna cásanna seo, is féidir leat rochtain a fháil ar an mbunachar sonraí go díreach i gcónaí, ag ródú timpeall an chiseal múnla

Léiríonn an réad `django.db.connection` an nasc réamhshocraithe bunachar sonraí. Chun an nasc bunachar sonraí a úsáid, glaoigh ar ```connection.cursor () ``chun réad cúrsóra a fháil. Ansin, glaoigh ar `cursor.execute (sql, [params]) ``chun an SQL agus `cursor.fetchone ()``` nó cursor.fetchall () a fhorghníomhú chun na sraitheanna mar thoradh air a thabhairt ar ais.

Mar shampla:

```
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
```

Chun cosaint a dhéanamh ar instealladh SQL, níor chóir duit luachana a áireamh timpeall na sealbhóirí %s\` sa sreangán SQL.

Tabhair faoi deara más mian leat comharthaí litriúla faoin gcéad a áireamh sa cheist, caithfidh tú iad a dhúbailt sa chás go bhfuil tú ag dul ar pharaiméadair:

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

Má tá tú ag baint úsáidea:doc: níos mó ná bunachar sonraí amháin ', is féidir leat \`\`django.db.connections\` \</topics/db/multi-db\> a úsáid chun an nasc (agus an cúrsóir) a fháil le haghaidh bunachar sonraí ar leith. Is réad cosúil le foclóir é `django.db.connections` a ligeann duit nasc ar leith a aisghabháil ag baint úsáide as a ainm:

```
from django.db import connections

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

De réir réamhshocraithe, cuirfidh an Python DB API torthaí ar ais gan a n-ainmneacha réimse, rud a chiallaíonn go mbeidh liosta \`\`luachanna agat, seachas \`\`dict\`. Ar chostas beag feidhmíochta agus cuimhne, is féidir leat torthaí a thabhairt ar ais mar `dict` trí rud éigin mar seo a úsáid:

```
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()]
```

Rogha eile is ea úsáid:func: collections.namedtuple ó leabharlann caighdeánach Python. Is réad cosúil le feadán é `namedtuple` a bhfuil réimsí inrochtana ag cuardach tréithe; tá sé innéacsaithe agus in-athraithe freisin. Tá na torthaí inathraithe agus inrochtana trí ainmneacha réimse nó innéacsanna, rud a d'fhéadfadh a bheith úsáideach:

```
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()]
```

Glacann na samplaí ```dictfetchall () ``agus ``namedtuplefetchall ()``` ainmneacha colún uathúla, ós rud é nach féidir le cúrsóir idirdhealú a dhéanamh idir colúin ó tháblaí éagsúla.

Seo sampla den difríocht idir na trí cinn:

```pycon
>>> 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
```

### Naisc agus cúrsaí

Forfheidhmíonn `nasc` agus `cursor` den chuid is mó an Python DB-API caighdeánach a thuairiscítear in:pep: 249 \- ach \</topics/db/transactions\> amháin maidir le: doc: láimhseáil idirbhearta.

Mura bhfuil tú eolach ar an Python DB-API, tabhair faoi deara go n-úsáideann an ráiteas SQL i cursor.execute () \`\`sealbhóirí ionaid, \`"%s", seachas paraiméadair a chur go díreach laistigh den SQL. Má úsáideann tú an teicníc seo, éalóidh an leabharlann bunachar sonraí bunúsach do pharaiméadair go huathoi

Tabhair faoi deara freisin go bhfuil Django ag súil leis an áitealbhóir `"%s"`, \* ní\* an ”? sealbhóir áit, a úsáideann na ceangail SQLite Python. Tá sé seo ar mhaithe le comhsheasmhacht agus sláine.

Cúrsóir a úsáid mar bhainisteoir comhthéacs:

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

atá coibhéiseach le:

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

#### Nósanna imeachta stóráilte

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

Glaonn sé nós imeachta stóráilte bunachar sonraí leis an ainm tugtha. Féadfar seicheamh (params\`) nó foclóir (kparams\`) de pharaiméadair ionchuir a sholáthar. Ní thacaíonn an chuid is mó de na bunachair sonraí le `kparams`. De chúltaca ionsuite Django, ní thacaíonn ach Oracle leis.

Mar shampla, de bharr an nós imeachta stóráilte seo i mbunachar sonraí Oracle:

```sql
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;
```

Déanfaidh sé seo glaoch air:

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