使用Oracle中的emp,dept來學習Django ORM
學習Django的時候,總是覺得這部分內容和實際的應用有一定的差別或者距離。一方面Django自帶的ORM對於底層資料庫來說是一種適配性很強的元件,可以不強依賴於某一種資料庫,sqlite,MySQL,Oracle,PG等等都可以,學習起來需要一定的週期。另外一方面是因為這種方式是通用的API,一下子沒有了SQL語句,要理解並接受這種思想,需要一點時間,對很多DBA來說需要適應。第三點就是沒有融會貫通,好像看明白了,但是實際寫的時候發現還是摸黑,不知道從何入手。
所以我就換個思路,從資料庫的角度來反向解析Django怎麼實現我們常見的資料需求。先做減法,側重於說查詢的部分。常見的資料需求,這個需求有些大,怎麼讓他更通用呢,我想到了Oracle裡面的emp,dept,自打學習資料庫,很多的測試案例就和這兩個表分不開,所以我們就從這個為切入點來逐步分析。
有的同學可能開始就打了退堂鼓,Oracle的還要轉換語句,還有資料型別,而使用的資料庫是MySQL,是不是有些麻煩啊,其實這些都不是事兒,不花一點功夫肯定難有收穫。
我們配置下emp,dept的結構,是在Django的models.py的檔案中配置即可。
from django.db import models
import django.utils.timezone as timezone
class dept(models.Model):
deptno = models.AutoField( primary_key= True)
dname = models.CharField( max_length= 30)
loc = models.CharField( max_length= 30, default= ' ')
class Meta:
db_table = 'dept'
verbose_name = 'DEPT'
verbose_name_plural = 'DEPT'
ordering = [ 'deptno']
def __unicode__( self):
return '%s %s' % ( self.deptno , self.dname)
class dept(models.Model):
deptno = models.AutoField( primary_key= True)
dname = models.CharField( max_length= 30)
loc = models.CharField( max_length= 30, default= ' ')
class Meta:
db_table = 'dept'
verbose_name = 'DEPT'
verbose_name_plural = 'DEPT'
ordering = [ 'deptno']
def __unicode__( self):
return '%s %s' % ( self.deptno , self.dname)
class emp(models.Model):
empno = models.AutoField( primary_key= True)
ename = models.CharField( max_length= 30)
job = models.CharField( max_length= 30)
mgr = models.IntegerField()
hiredate = models.DateTimeField( 'hire date', default=timezone.now)
sal = models.IntegerField()
comm = models.IntegerField
deptno = models.ForeignKey( 'dept')
class Meta:
db_table = 'emp'
verbose_name = 'EMP'
verbose_name_plural = 'EMP'
verbose_name_plural = 'EMP'
ordering = [ 'empno', 'ename']
def __unicode__( self):
return '%s %s' % ( self.empno , self.ename)
其實內容來看倒也不難,型別是通用的。
使用python manage.py makemigrations得到變化的結構和資料
Migrations for 'scott':
0001_initial.py:
- Create model dept
- Create model emp
得到的SQL如下:
>python manage.py sqlmigrate scott 0001
BEGIN;
CREATE TABLE "dept" ( "deptno" integer NOT NULL PRIMARY KEY AUTOINCREMENT , "dname" varchar( 30) NOT NULL , "loc" varchar( 30) NOT NULL);
CREATE TABLE "emp" ( "empno" integer NOT NULL PRIMARY KEY AUTOINCREMENT , "ename" varchar( 30) NOT NULL , "job" varchar( 30) NOT NULL , "mgr" integer NOT NULL
, "hiredate" datetime NOT NULL , "sal" integer NOT NULL , "deptno_id" integer NOT NULL REFERENCES "dept" ( "deptno"));
CREATE INDEX "emp_d6b13549" ON "emp" ( "deptno_id");
COMMIT;
簡單確認下,我們就可以生成建立出來這兩個表了,使用python manage.py migrate即可。
emp的表結構如下:
dept的表結構如下:
我們初始化一下資料,這個時候直接使用SQL也可以.
dept表的初始化語句如下:
insert into dept values( 10,'ACCOUNTING','NEW YORK');
insert into dept values( 20,'RESEARCH','DALLAS');
insert into dept values( 30,'SALES','CHICAGO');
insert into dept values( 40,'OPERATIONS','BOSTON');
emp表的初始化語句如下,特別需要注意的就是欄位不是deptno,而是deptno_id
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7369,'SMITH','CLERK',7902,'1980-12-17',800.00,20);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600.00,30);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7521,'WARD','SALESMAN',7698,'1981-2-22',1250.00,30);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7566,'JONES','MANAGER',7839,'1981-4-2',2975.00,20);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7654,'MARTIN','SALESMAN',7698,'1981-9-28',1250.00,30);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7698,'BLAKE','MANAGER',7839,'1981-5-1',2850.00,30);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7782,'CLARK','MANAGER',7839,'1981-6-9',2450.00,10);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7788,'SCOTT','ANALYST',7566,'1987--4-19',3000.00,20);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7839,'KING','PRESIDENT',0,'1981-11-17',5000.00,10);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7844,'TURNER','SALESMAN',7698,'1981-9-8',1500.00,30);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7876,'ADAMS','CLERK',7788,'1987-5-23',1100.00,20);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7900,'JAMES','CLERK',7698,'1981-12-3',950,30);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7902,'FORD','ANALYST',7566,'1981-12-3',3000,20);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 7934,'MILLER','CLERK',7782,'1982-1-23',1300,10);
insert into emp(EMPNO ,ENAME ,JOB ,MGR ,HIREDATE ,SAL ,DEPTNO_ID) values( 9999,'SHUNPING','CLERK',7782,'1988-5-5',2456.34,10);
剩下的事情就是實踐了。我們就選擇emp,dept常見的一些SQL來看看ORM能否完成這個任務。
1、顯示所有的姓名、工種、工資和獎金,按工種降序排列,若工種相同則按工資升序排列。
如果使用MySQL,語句和資料結果如下:
mysql> select ename ,job ,sal from emp order by job desc ,sal asc;
+----------+-----------+------+
| ename | job | sal |
+----------+-----------+------+
| WARD | SALESMAN | 1250 |
| MARTIN | SALESMAN | 1250 |
使用order_by的方式來處理,可以看到有了一點頭緒,但是還是沒有實現需求。
>>> emp.objects.all().order_by( 'job')
[<emp: 7788 SCOTT> , <emp: 7902 FORD> , <emp: 7369 SMITH> , ....
所以我們的重點就是排序了,ORM本身有order_by函式,還可以調整DESC,ASC,所以一個基本符合要求的方式如下:
>>> emp.objects.all().order_by(( '-job') ,( 'sal'))
[<emp: 7521 WARD> , <emp: 7654 MARTIN> , <emp: 7844 TURNER>
第二個題目也是類似的。
2、查詢員工的姓名和入職日期,並按入職日期從先到後進行排列。
SQL語句如下:
select ename,hiredate from emp order by hiredate asc;
現在的語句如下:
emp.objects.all().order_by(( 'hiredate'))
3. 計算工資最高的員工
這個需求充分考慮到聚合函式的部分,我們可以使用aggregate來完成這個工作。
>>> emp.objects.all().aggregate(Max( 'sal'))
{ 'sal__max': 5000}
4.查詢至少有一個員工的部門資訊。
這個部分會涉及到表關聯關係,如果是通過SQL的方式,語句如下:
select * from dept where deptno in (select distinct deptno from emp where mgr is not null);
執行的結果如下,可以看到第一種方式能出結果,但是還是存在重複值,需要用distinct過啦一下。
>>> dept.objects.filter( emp__mgr__isnull= False)
[<dept: 10 ACCOUNTING> , <dept: 10 ACCOUNTING> , <dept: 10 ACCOUNTING> , <dept: 10 ACCOUNTING> , <dept: 20 RESEARCH> , <dept: 20 RESEARCH> , <dept: 20 RESEARCH> , <dept: 20 RESEARCH> , <dept: 20 RESEARCH> , <dept: 30 SALES> , <dept: 30 SALES> , <dept: 30 SALES> , <dept: 30 SALES> , <dept: 30 SALES> , <dept: 30 SALES>]
>>> dept.objects.filter( emp__mgr__isnull= False).distinct()
[<dept: 10 ACCOUNTING> , <dept: 20 RESEARCH> , <dept: 30 SALES>]
>>>
後續繼續補充ORM的內容。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2149273/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- oracle之 手動建立 emp 表 與 dept 表Oracle
- django中orm的使用DjangoORM
- Oracle通過scott使用者中的emp練習單表操作Oracle
- 根據emp,dept,salgrade表進行的sql查詢語句(1)SQL
- Django中ORM外來鍵和表的關係(Django程式設計-4)DjangoORM程式設計
- Django ORMDjangoORM
- django ORM 中 select_related 與 prefetch_related 的使用場景DjangoORM
- Django ORM QuerySetDjangoORM
- django mysqlclient ormDjangoMySqlclientORM
- django指令碼orm中使用原生sqlDjango指令碼ORMSQL
- Django學習(二) 之 模板的使用Django
- odoo ORM API學習總結兼orm學習教程OdooORMAPI
- 03.Django-ORMDjangoORM
- Django ORM 多表操作DjangoORM
- 如何在Django ORM中進行not查詢?DjangoORM
- Django中ORM找出內容不為空的資料DjangoORM
- Django ORM 單表操作DjangoORM
- python中web開發框架Django的學習PythonWeb框架Django
- Django學習Django
- django的orm有什麼優點DjangoORM
- Django之ORM連表操作DjangoORM
- Django-ORM-單表操作DjangoORM
- Django的學習資源Django
- 學習Django的推薦Django
- django學習(三)Django
- node 整合sequelize ORM 框架學習ORM框架
- Django-基礎-2-ORMDjangoORM
- Django-ORM 之查詢排序DjangoORM排序
- Django 中 Aggregation聚合的使用Django
- 靈活使用 SQLAlchemy 中的 ORM 查詢SQLORM
- 【Python】Django學習1PythonDjango
- Django-ORM---查詢集介紹DjangoORM
- django | 常見 SQL 及其對應的 ORM 寫法DjangoSQLORM
- Django中content_type的使用Django
- python django中restful框架的使用PythonDjangoREST框架
- Django中F函式的使用Django函式
- Django學習筆記(13)——Django的使用者認證元件,檢視層和QuerySet APIDjango筆記元件API
- JSON欄位型別在ORM中的使用JSON型別ORM
- orm使用ORM