Fiosrúcháin SQL amh a dhéanamhLink to this heading

Django gives you three ways of performing raw SQL queries: you can embed raw SQL fragments into ORM queries using RawSQL (see Raw SQL fragments), use Manager.raw() to perform raw queries and return model instances, or avoid the model layer entirely and execute custom SQL directly.

Raw SQL fragmentsLink to this heading

In some cases, you may need to embed raw SQL fragments directly into ORM queries — for example, in annotate() or filter() calls. Use Func() expressions for calling database functions across backends, or RawSQL for arbitrary parameterized SQL fragments.

Fiosrúcháin amh a dhéanamhLink to this heading

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)Link to this definition

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:

Code
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:

Python console
>>> 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.

Réimsí fiosrúcháin a mapáil go réimsíLink to this heading

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:

Python console
>>> 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`:

Python console
>>> 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:

Python console
>>> 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éacsLink to this heading

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

Python console
>>> 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:

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

Réimsí samhail a chur ar iarchurLink to this heading

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

Python console
>>> 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:

Python console
>>> 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.

Paraiméadair a chur isteach i ``raw () ``Link to this heading

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

Python console
>>> 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.

SQL saincheaptha a fhorghníomhúLink to this heading

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 ()`cursor.fetchall () ``a fhorghníomhú chun na sraitheanna mar thoradh air a thabhairt ar ais.

Mar shampla:

Code
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:

Code
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:

Code
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:

Code
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:

Code
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:

Python console
>>> 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íLink to this heading

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:

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

atá coibhéiseach le:

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

Nósanna imeachta stóráilteLink to this heading

CursorWrapper.callproc(procname, params=None, kparams=None)Link to this definition

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:

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