天天看點

Django執行原生 SQL 查詢

執行原生查詢

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

raw_query:執行的sql語句

params:需要格式化的參數,類型:清單

translations:值為字典,将查出來的資料鍵值對化,根據模型屬性聲明查詢出來的鍵,如:{模型屬性:鍵}

模型

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

然後你可以像這樣執行自定義 SQL:

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

我們還可以這樣讓sql語句更有閱讀性

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

這個例子并不令人興奮——實際上,這就是運作 Person.objects.all()。然而, raw() 有很多額外選項,使得它非常強大。比如省略字段,支援索引

或者,你可以用 raw() 的 translations 參數将查詢語句中的字段映射至模型中的字段。這是一個字典,将查詢語句中的字段名映射至模型中的字段名。例如,上面的查詢也能這樣寫:

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

标題将參數傳給 raw()

如果你需要執行參數化的查詢,可以使用 raw() 的 params 參數:

lname = 'Doe'
#下面這種方式可以防止sql注入
Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])
#下面這種方式存在隐患,可以被sql注入
Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s' %lname)
           

直接執行自定義 SQL

有時候,甚至 Manager.raw() 都無法滿足需求:你可能要執行不明确映射至模型的查詢語句,或者就是直接執行 UPDATE, INSERT 或 DELETE 語句。

這些情況下,你總是能直接通路資料庫,完全繞過模型層。

對象 django.db.connection 代表預設資料庫連接配接。要使用這個資料庫連接配接,調用 connection.cursor() 來擷取一個指針對象。然後,調用 cursor.execute(sql, [params]) 來執行該 SQL 和 cursor.fetchone(),或 cursor.fetchall() 擷取結果資料。

例如:

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
           

若你同時使用 不止一個資料庫,你可以使用 django.db.connections 擷取指定資料庫的連接配接(和指針)。 django.db.connections 是一個類字典對象,它允許你通過連接配接别名擷取指定連接配接:

from django.db import connections
with connections['my_db_alias'].cursor() as cursor:
    # 邏輯代碼
           

三種查詢方法的輸出類型

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