이 문서에서는 Django 애플리케이션의 SQL Server 대해 원시 SQL 쿼리를 실행하는 방법을 설명합니다. 원시 SQL은 복잡한 Transact-SQL(T-SQL), 공간 쿼리 또는 성능에 중요한 작업과 같이 Django ORM을 통해 노출되지 않는 작업에 유용합니다.
connection.cursor() 사용
Django의 connection 객체를 통해 데이터베이스 커서에 직접 액세스할 수 있습니다.
from django.db import connection
def get_server_version():
with connection.cursor() as cursor:
cursor.execute("SELECT @@VERSION;")
row = cursor.fetchone()
return row[0]
with 구문은 사용 후 커서가 올바르게 닫히도록 보장합니다.
매개 변수가 있는 쿼리
항상 매개 변수가 있는 쿼리를 사용하여 SQL 삽입을 방지합니다. 매개 변수를 목록으로 전달합니다.
Note
다음 예제에서는 Django의 기본 테이블 명명 규칙 <app_label>_<model_name> (예: myapp_product)을 사용합니다. 모델의 Meta에서 db_table를 재정의하는 경우 해당 이름으로 대체합니다.
Product._meta.db_table를 사용하여 런타임에 해석된 이름을 읽을 수도 있습니다.
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
문자열 서식 또는 f 문자열을 사용하여 SQL 쿼리에 값을 포함하면 안 됩니다. 항상 매개 변수가 있는 쿼리(%s 매개 변수 목록이 있는 자리 표시자)를 사용하여 SQL 삽입을 방지합니다.
결과 가져오기
Django의 커서는 결과를 검색하는 몇 가지 방법을 제공합니다.
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()
결과를 사전으로 반환
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)
모델 쿼리에 Manager.raw() 사용
원시 SQL을 원하지만 Django 모델 인스턴스를 원하는 경우 다음을 사용합니다 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}")
쿼리는 모델의 기본 키에 정의된 모든 필드를 반환해야 합니다. 추가 필드는 지연 로딩됩니다.
DDL 구문 실행
Django에서 직접 지원하지 않는 스키마 작업에 원시 SQL을 사용합니다.
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);"
)
여러 데이터베이스 연결
여러 데이터베이스를 사용하는 경우 사용할 연결을 지정합니다.
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]