SSAFY/Django

[Django] SQL 과 장고 ORM 사용 방법

황성안 2021. 3. 26. 08:50
728x90
[TOC]

SQL with django ORM

기본 준비 사항

# 폴더구조

99_sql # only SQL
    hellodb.csv
    tutorial.sqlite3
    users.csv
99_sql_orm # SQL + ORM
    ...
    users.csv # 해당 디렉토리로 다운로드
  • django app
    • 가상환경 세팅
    • 패키지 설치
    • migrate
    • $ python manage.py sqlmigrate users 0001
  • db.sqlite3 활용
    • sqlite3 실행
    • $ ls db.sqlite3 manage.py ... $ sqlite3 db.sqlite3
    • csv 파일 data 로드
    • sqlite > .tables auth_group django_admin_log auth_group_permissions django_content_type auth_permission django_migrations auth_user django_session auth_user_groups auth_user_user_permissions users_user sqlite > .mode csv sqlite > .import users.csv users_user sqlite > SELECT COUNT(*) FROM users_user; 100
  • 확인
    • sqlite3에서 스키마 확인
    • sqlite > .schema users_user CREATE TABLE IF NOT EXISTS "users_user" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "first_name" varchar(10) NOT NULL, "last_name" varchar(10) NOT NULL, "age" integer NOT NULL, "country" varchar(10) NOT NULL, "phone" varchar(15) NOT NULL, "balance" integer NOT NULL);

 


 

문제

아래의 문제들을 보면서 서로 대응되는 ORM문과 SQL문을 작성하시오.

vscode 터미널을 좌/우로 나누어 진행하시오. (sqlite / shell_plus)

.headers on 만 켜고 작성해주세요.

 

1. 기본 CRUD 로직

  1. 모든 user 레코드 조회
    -- sql
    SELECT * FROM users_user;
    
  2. # orm User.objects.all() print(User.objects.all().query) # 궁금하면 처보세요
  3. user 레코드 생성
    -- sql
    INSERT INTO users_user
    (first_name, last_name, age, country, phone, balance)
    VALUES ('홍','길동',100,'제주도','010-1234-1234',100000);
    
    • 하나의 레코드를 빼고 작성 후 NOT NULL constraint 오류를 orm과 sql에서 모두 확인 해보세요.
  4. # orm User.objects.create( first_name='홍', last_name='길동', age=100, country='제주도', phone='010-1234-1234', balance=100000 )
  5. 해당 user 레코드 조회
    • 101 번 id의 전체 레코드 조회
    # orm
    User.objects.get(pk=101)
    
    -- sql
    SELECT *
    FROM users_user
    WHERE id=1001;
    
  6. 해당 user 레코드 수정
    • ORM: 101 번 글의 last_name 을 '김' 으로 수정
    • SQL: 101 번 글의 first_name 을 '철수' 로 수정
    # orm
    user = User.objects.get(pk=1001)
    user.last_name = '김'
    user.save()
    
    user.last_name
    
    -- sql
    UPDATE users_user
    SET first_name='철수'
    WHERE id=1001;
    
    SELECT *
    FROM users_user
    WHERE id=1001;
    
  7. 해당 user 레코드 삭제
    • ORM: 101 번 글 삭제
    • SQL: 101 번 글 삭제 (ORM에서 삭제가 되었기 때문에 아무런 응답이 없음)
    # orm
    User.objects.get(pk=1001).delete()
    
   
   ```sql
   -- sql
   DELETE FROM users_user
   WHERE id=1001;

 


 

2. 조건에 따른 쿼리문

  1. 전체 인원 수
    • User 의 전체 인원수
    # orm
    len(User.objects.all())
    User.objects.count()
    
    -- sql
    SELECT COUNT(*)
    FROM users_user;
    
  2. 나이가 30인 사람의 이름
    • ORM : .values 활용
      • 예시: User.objects.filter(조건).values(컬럼이름)
    # orm
    User.objects.filter(age=30).values('first_name')
    
    #영환씨를 뽑고싶다.(첫번째 값을 뽑고싶다.)
    User.objects.filter(age=30).values('first_name')[0].get('first_name')
    
    -- sql
    SELECT first_name
    FROM users_user
    WHERE age=30;
    
  3. 나이가 30살 이상인 사람의 인원 수
    • ORM: __gte , __lte , __gt, __lt -> 대소관계 활용
    # orm
    #gte 이상
    #lte 이하
    #gt 초과
    #lt 미만
    User.objects.filter(age__gte=30).count()
    
    -- sql
    SELECT count(*)
    FROM users_user
    WHERE age >= 30;
    
  4. 나이가 20살 이하인 사람의 인원 수
    -- sql
    SELECT count(*)
    FROM users_user
    WHERE age <= 20;
    
    -- sql 문에서 같지 않음을 표현할 때는
    -- != 또는 <>를 사용합니다.
    
  5. # orm User.objects.filter(age__lte=20).count()
  6. 나이가 30이면서 성이 김씨인 사람의 인원 수
    -- sql
    SELECT count(*)
    FROM users_user
    WHERE age = 30 AND last_name='김';
    
  7. # orm User.objects.filter(age=30, last_name='김').count()
  8. 나이가 30이거나 성이 김씨인 사람?별도로 import해서 사용해야합니다.
    # orm
    from django.db.models import Q
    Q(age=30)
    Q(last_name='김')
    User.objects.filter(Q(age=30) | Q(last_name='김')).count()
    #query 확인
    print(User.objects.filter(Q(age=30) | Q(last_name='김')).query)
    
    -- sql
    SELECT *
    FROM users_user
    WHERE age>=30 OR last_name='김';
    
  9. from django.db.models import Q Model.objects.filter(Q(x=1)|Q(y=2))
  10. : OR을 활용하고 싶다면, Q 오브젝트를 사용해야합니다.
  11. 지역번호가 02인 사람의 인원 수
    • ORM: __startswith
    # orm
    #__startswith ~으로 시작하는
    User.objects.filter(phone__startswith='02-').count()
    
    -- sql
    SELECT COUNT(*)
    FROM users_user
    WHERE phone LIKE '02-%';
    
  12. 거주 지역이 강원도이면서 성이 황씨인 사람의 이름
    -- sql
    SELECT first_name
    FROM users_user
    WHERE country='강원도' AND last_name='황';
    
  13. # orm User.objects.filter(country='강원도', last_name='황').values('first_name') #한명만일떄 User.objects.filter(country='강원도', last_name='황')[0].first_name # User.objects.filter(country='강원도', last_name='황').values('first_name')[0].get('first_name')

 


 

3. 정렬 및 LIMIT, OFFSET

  1. 나이가 많은 사람순으로 10명
    -- sql
    SELECT *
    FROM users_user
    ORDER BY age DESC
    LIMIT 10;
    
  2. # orm User.objects.order_by('-age')[:10] # 정말 10개인지 확인 User.objects.order_by('-age')[:10].count()
  3. 잔액이 적은 사람순으로 10명
    -- sql
    SELECT *
    FROM user_user
    ORDER BY balance
    LIMIT 10;
    
  4. # orm User.objects.order_by('balance')[:10]
  5. 잔고는 오름차순, 나이는 내림차순으로 10명?
  6. # orm User.objects.order_by('balance', '-age')[:10]
   
   ```sql
   -- sql
   SELECT *
   FROM users_user
   ORDER BY balance ASC, age DESC
   LIMIT 10;
  1. 성, 이름 내림차순 순으로 5번째 있는 사람
  2. # orm User.objects.order_by('-last_name', '-first_name')[4]
   
      ```sql
   -- sql
   SELECT *
   FROM users_user
   ORDER BY last_name DESC, first_name DESC
   LIMIT 1 OFFSET 4;

 


 

4. 표현식

ORM: aggregate 사용

https://docs.djangoproject.com/en/3.1/topics/db/aggregation/#aggregation

  • '종합', '합계' 등의 사전적 의미
  • 특정 필드 전체의 합, 평균 등을 계산할 때 사용
  1. 전체 평균 나이
    -- sql
    SELECT AVG(age)
    FROM users_user;
    
  2. # orm from django.db.models import Avg #Avg('age') 형태로 값을 구하고.. #annotate로 필드를 추가합니다. User.objects.annotate(my_awesome_avg=Avg('age')).values()[0] User.objects.annotate(Avg('age')).values()[0]
  3. 김씨의 평균 나이
    -- sql
    SELECT AVG(age)
    FROM users_user
    WHERE last_name='김';
    
  4. # orm User.objects.filter(last_name='김').aggregate(Avg('age'))
  5. 강원도에 사는 사람의 평균 계좌 잔고
    -- sql
    SELECT AVG(balance)
    FROM users_user
    WHERE country='강원도';
    
  6. # orm User.objects.filter(country='강원도').aggregate(Avg('balance'))
  7. 계좌 잔액 중 가장 높은 값
    -- sql
    SELECT MAX(balance)
    FROM user_user;
    
  8. # orm User.objects.aggregate(Max('balance')) #User.objects.aggregate(Max('balance'))
  9. 계좌 잔액 총액
    -- sql
    SELECT MAX(balance)
    FROM users_user
    
  10. # orm from django.db.models import Q, Max, Avg, Sum, .... User.objects.aggregate(Sum('balance'))
728x90

'SSAFY > Django' 카테고리의 다른 글

[Django] 로그인한 사용자 판별하기  (0) 2021.03.27
[Django] 댓글 삭제  (0) 2021.03.26
[DJANGO] 댓글 만들기  (0) 2021.03.25
[Django] 회원가입 만들기  (0) 2021.03.22
[Django]Form  (0) 2021.03.21