SQL and Django ORM
์ฐธ๊ณ ๋ฌธ์
Making queries | Django documentation | Django
QuerySet API reference | Django documentation | Django
Aggregation | Django documentation | Django
๊ธฐ๋ณธ ์ค๋น ์ฌํญ
django app
django_extensions
์ค์นusers
app ์์ฑcsv ํ์ผ์ ๋ง์ถฐ
models.py
์์ฑ ๋ฐ migratepython 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; 1000
ํ์ธ
sqlite3์์ ์คํค๋ง ํ์ธ
sqlite > .schema users_user
๋ฌธ์
์๋์ ๋ฌธ์ ๋ค์ sql๋ฌธ๊ณผ ๋์๋๋ orm์ ์์ฑ ํ์ธ์.
Table ์์ฑ
django
# django class User(models.Model): first_name = models.CharField(max_length=10) last_name = models.CharField(max_length=10) age = models.IntegerField() country = models.CharField(max_length=10) phone = models.CharField(max_length=15) balance = models.IntegerField() # python manage.py makemigrations # python manage.py migrate
SQL
sql.sqlite3์ ๋์ผํ๊ฒ ํ ์ด๋ธ ์์ฑ
--sql 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 );
๊ธฐ๋ณธ CRUD ๋ก์ง
๋ชจ๋ user ๋ ์ฝ๋ ์กฐํ
# orm users = User.objects.all() type(users) # => django.db.models.query.QuerySet print(users.query) # queryset๋ง sql๋ฌธ ์ถ๋ ฅ ๊ฐ๋ฅ # => SELECT "users_user"."id", "users_user"."first_name", "users_user"."last_name", "users_user"."age", "users_user"."country", "users_user"."phone", "users_user"."balance" FROM "users_user"
-- sql SELECT*FROM users_user;
user ๋ ์ฝ๋ ์์ฑ
# orm User.objects.create ( first_name='๊ตฌ๋ฆ', last_name='๊น', age=100, country='์ ์ฃผ๋', phone='010-1234-5678', balance=10000000 )
-- sql INSERT INTO users_user(first_name, last_name, age, country, phone, balance) VALUES ('์ฃผํ', '๊น', 26, '๊ฒฝ๊ธฐ๋', '010-0000-0000', 100000000000);
ํ๋์ ๋ ์ฝ๋๋ฅผ ๋นผ๊ณ ์์ฑ ํ
NOT NULL
constraint ์ค๋ฅ๋ฅผ orm๊ณผ sql์์ ๋ชจ๋ ํ์ธ ํด๋ณด์ธ์.# orm IntegrityError: NOT NULL constraint failed: users_user.age
-- sql Error: NOT NULL constraint failed: users_user.last_name
ํด๋น user ๋ ์ฝ๋ ์กฐํ
# orm User.objects.get(id=100) #=> <User: User object (100)>
get
์ query ๊ฒฐ๊ณผ๊ฐ ๋ฐ๋์ ํ๋์ฌ์ผ ํ๋ค. (์ด์ธ์๋ ๋ชจ๋ return error!)User.object.get(last_name='๊น') # MultipleObjectsReturned: get() returned more than one User -- it returned 24! User.objects.get(id=1000) # DoesNotExists: User matching query does not exists.
-- sql
SELECT * FROM users_user WHERE id = 100;
ํด๋น user ๋ ์ฝ๋ ์์
# orm user = User.objects.get(id=100) user.last_name='์ฑ' user.save()
-- sql UPDATE users_user SET last_name='์ต' WHERE id=100;
ํด๋น user ๋ ์ฝ๋ ์ญ์
# orm User.objects.get(id=101).delete()
-- sql DELETE FROM users_user WHERE id = 102;
์กฐ๊ฑด์ ๋ฐ๋ฅธ ์ฟผ๋ฆฌ๋ฌธ
์ ์ฒด ์ธ์ ์
# orm # ver1) User.objects.all().count() # ver2) - ์ด๊ฑธ ์ฐ๋ผ User.objects.count()
-- sql -- ver1) SELECT COUNT(*) FROM users_user; -- ver2) SELECT COUNT(id) FROM users_user;
๋์ด๊ฐ 30์ธ ์ฌ๋์ ์ด๋ฆ
# orm User.objects.filter(age=30) #=> <QuerySet [<User: User object (5)>, <User: User object (57)>, <User: User object (60)>]> User.objects.filter(age=30).values('first_name') #=> <QuerySet [{'first_name': '์ํ'}, {'first_name': '๋ณด๋'}, {'first_name': '์์'}]> type(User.objects.filter(age=30).values('first_name')[0]) #=> dict print(User.objects.filter(age=30).values('first_name').query) #=> SELECT "users_user"."first_name" FROM "users_user" WHERE "users_user"."age" = 30
-- sql SELECT first_name FROM users_user WHERE age = 30;
๋์ด๊ฐ 30์ด ์ด์์ธ ์ฌ๋์ ์ธ์ ์
๋์๊ด๊ณ __gte : >=
__gt : >
__lte : <=
__lt : <
# orm
User.objects.filter(age__gte=30)
print(User.objects.filter(age__gte=30).query)
# SELECT "users_user"."id", "users_user"."first_name", "users_user"."last_name", "users_user"."age", "users_user"."country", "users_user"."phone", "users_user"."balance" FROM "users_user" WHERE "users_user"."age" >= 30
User.objects.filter(age__gte=30).count()
-- sql
SELECT COUNT(*) FROM users_user
WHERE age>=30;
๋์ด๊ฐ 30์ด๋ฉด์ ์ฑ์ด ๊น์จ์ธ ์ฌ๋์ ์ธ์ ์
# orm -1 User.objects.filter(age=30).filter(last_name='๊น').count() # orm -2 User.objects.filter(age=30, last_name='๊น').count() # query print(User.objects.filter(age=30).filter(last_name='๊น').query) # => SELECT "users_user"."id", "users_user"."first_name", "users_user"."last_name", "users_user"."age", "users_user"."country", "users_user"."phone", "users_user"."balance" FROM "users_user" WHERE ("users_user"."age" = 30 AND "users_user"."last_name" = ๊น)
-- sql SELECT COUNT(*) from users_nuser WHERE age = 30 AND last_name ='๊น';
์ง์ญ๋ฒํธ๊ฐ 02์ธ ์ฌ๋์ ์ธ์ ์
# orm User.objects.filter(phone__startswith='02-').count() # query print(User.objects.filter(phone__startswith='02-').query) #=> SELECT "users_user"."id", "users_user"."first_name", "users_user"."last_name", "users_user"."age", "users_user"."country", "users_user"."phone", "users_user"."balance" FROM "users_user" WHERE "users_user"."phone" LIKE 02-% ESCAPE '\'
-- sql SELECT COUNT(*) FROM users_user WHERE phone LIKE '02-%';
๊ฑฐ์ฃผ ์ง์ญ์ด ๊ฐ์๋์ด๋ฉด์ ์ฑ์ด ํฉ์จ์ธ ์ฌ๋์ ์ด๋ฆ
# orm
-- sql
์ ๋ ฌ ๋ฐ LIMIT, OFFSET
๋์ด๊ฐ ๋ง์ ์ฌ๋ 10๋ช
# orm User.objects.order_by('-age')[:10] # query print(User.objects.order_by('-age')[:10].query) #=> SELECT "users_user"."id", "users_user"."first_name", "users_user"."last_name", "users_user"."age", "users_user"."country", "users_user"."phone", "users_user"."balance" FROM "users_user" ORDER BY "users_user"."age" DESC LIMIT 10
-- sql SELECT * FROM users_user ORDER BY age DESC LIMIT 10; id | first_name | last_name | age | country | phone | balance 1 | ์ ํธ | ์ | 40 | ์ ๋ผ๋ถ๋ | 016-7280-2855 | 370 4 | ๋ฏธ๊ฒฝ | ์ฅ | 40 | ์ถฉ์ฒญ๋จ๋ | 011-9079-4419 | 250000 28 | ์ฑํ | ๋ฐ | 40 | ๊ฒฝ์๋จ๋ | 011-2884-6546 | 580000
์์ก์ด ์ ์ ์ฌ๋ 10๋ช (์ค๋ฆ์ฐจ์)
# orm User.objects.order_by('balance')[:10]
-- sql SELECT * FROM users_user ORDER BY balance ASC LIMIT 10;
์ฑ, ์ด๋ฆ ๋ด๋ฆผ์ฐจ์ ์์ผ๋ก 5๋ฒ์งธ ์๋ ์ฌ๋
# orm User.objects.order_by('-last_name', '-first_name')[4] #=> <User: User object (67)>
-- sql SELECT * FROM users_user ORDER BY last_name DESC, first_name DESC LIMIT 1 OFFSET 4; id | first_name | last_name | age | country | phone | balance 67 | ๋ณด๋ | ํ | 28 | ์ถฉ์ฒญ๋ถ๋ | 016-4392-9432 | 82000
ํํ์
ํํ์์ ์ํด์๋ aggregate ๋ฅผ ์์์ผํ๋ค.
์ ์ฒด ํ๊ท ๋์ด
# orm from django.db.models import Avg User.objects.aggregate(Avg('age')) #=> {'age__avg': 28.23}
-- sql SELECT AVG(age) FROM users_user; AVG(age) 28.23
๊น์จ์ ํ๊ท ๋์ด
# orm from django.db.models import Avg User.objects.filter(last_name='๊น').aggregate(Avg('age'))
-- sql SELECT AVG(age) FROM users_user WHERE last_name = '๊น';
๊ณ์ข ์์ก ์ค ๊ฐ์ฅ ๋์ ๊ฐ
# orm from django.db.models import Max User.objects.aggregate(Max('balance'))
-- sql SELECT MAX(balance) FROM users_user;
๊ณ์ข ์์ก ์ด์ก
# orm from django.db.models import Sum User.objects.aggregate(Sum('balance'))
-- sql SELECT SUM(balance) FROM users_user;
Group by
annotate๋ ๊ฐ๋ณ item์ ์ถ๊ฐ ํ๋๋ฅผ ๊ตฌ์ฑํ๋ค. ์ถํ 1:N ๊ด๊ณ์์ ํ์ฉ๋๋ค.
์ง์ญ๋ณ ์ธ์ ์
# orm User.objects.values('country') # <QuerySet [{'country': '์ ๋ผ๋ถ๋'}, {'country': '๊ฒฝ์๋จ๋'}, {'country': '์ ๋ผ๋จ๋'}, ... from django.db.models import Count User.objects.values('country').annotate(Count('country')) # <QuerySet [{'country': '๊ฐ์๋', 'country__count': 14}, {'country': '๊ฒฝ๊ธฐ๋', 'country__count': 9}, {'country': '๊ฒฝ์๋จ๋', 'country__count': 9}, {'country': '๊ฒฝ์๋ถ๋', 'country__count': 15}, {'country': '์ ๋ผ๋จ๋', 'country__count': 10}, {'country': '์ ๋ผ๋ถ๋', 'country__count': 11}, {'country': '์ ์ฃผํน๋ณ์์น๋', 'country__count': 9}, {'country': '์ถฉ์ฒญ๋จ๋', 'country__count': 9}, {'country': '์ถฉ์ฒญ๋ถ๋', 'country__count': 14}]>
-- sql SELECT country, COUNT(country) FROM users_user GROUP BY country; country | COUNT(country) ๊ฐ์๋ | 14 ๊ฒฝ๊ธฐ๋ | 9 ๊ฒฝ์๋จ๋ | 9 ๊ฒฝ์๋ถ๋ | 15 ์ ๋ผ๋จ๋ | 10 ์ ๋ผ๋ถ๋ | 11 ์ ์ฃผํน๋ณ์์น๋ | 9 ์ถฉ์ฒญ๋จ๋ | 9 ์ถฉ์ฒญ๋ถ๋ | 14
Last updated
Was this helpful?