序言
Filecoin即將上線、我們知道filecoin是由goLang編寫的,所以在此間歇期,我打算同時複習一下go和python的知識,本文的側重點在於如何高效率的使用orm-sql語句。
Go操作mysql
Golang可以操作原生sql,具體實現如下,但基礎語句直接操作原生sql,在實際開發過程中,需要封裝大量的處理類函數,很是麻煩,因爲orm提供了更好的方式,所以我建議基礎語句(基本的增刪查改)使用orm,而複雜的語句就使用原生sql。
1.安裝git(略)
2.go get github.com/go-sql-driver/mysql 安裝之後會放在go path 目錄下
3.連接代碼如下
package main
import (
"database/sql"
_"database/sql/driver"
_"github.com/go-sql-driver/mysql"
)
import "fmt"
var(
dbhost="127.0.0.1"
dbuser="root"
dbpasswd="root"
dbName="project01"
)
func errorCheck(err error){
if err!=nil{
fmt.Println("mysql conncet error")
panic(err)
}
}
func main(){
db,err:=sql.Open("mysql",dbuser+":"+dbpasswd+"@tcp("+dbhost+")/"+dbName+"?charset=utf8")
defer db.Close()
errorCheck(err)
//檢測是否連接成功,如果返回值err有值則代表失敗
err=db.Ping()
fmt.Println(err)
}
4.執行語句如下:(包括增、刪、改)
func insert_db(insert_sql [][]string,db *sql.DB)(error){
db_obj,error:=db.Prepare("insert into stu values (?,?)")
for _,value :=range insert_sql{
resultobj,err:=db_obj.Exec(value[0],value[1])
n,_:=resultobj.RowsAffected()
fmt.Println(resultobj,err,n)
}
return error
}
5.查詢語句如下:
func get_info(sql string,db *sql.DB){
var id,name string
//單行查詢,默認返回第一行數據
row:=db.QueryRow(sql)
row.Scan(&id,&name)
fmt.Println(id,name)
//多行查詢,rows.Next 有值爲1,無值爲0
rows,_:=db.Query(sql)
for rows.Next(){
rows.Scan(&id,&name)
fmt.Println(id,name)
}
}
6.完整代碼如下:
package main
import (
"database/sql"
_"database/sql/driver"
_"github.com/go-sql-driver/mysql"
)
import "fmt"
var(
dbhost="127.0.0.1"
dbuser="root"
dbpasswd="root"
dbName="project01"
)
func errorCheck(err error){
if err!=nil{
fmt.Println("mysql conncet error")
panic(err)
}
}
func insert_db(insert_sql [][]string,db *sql.DB)(error){
db_obj,error:=db.Prepare("insert into stu values (?,?)")
for _,value :=range insert_sql{
resultobj,err:=db_obj.Exec(value[0],value[1])
n,_:=resultobj.RowsAffected()
fmt.Println(resultobj,err,n)
}
return error
}
func get_info(sql string,db *sql.DB){
var id,name string
//單行查詢,默認返回第一行數據
row:=db.QueryRow(sql)
row.Scan(&id,&name)
fmt.Println(id,name)
//多行查詢,rows.Next 有值爲1,無值爲0
rows,_:=db.Query(sql)
for rows.Next(){
rows.Scan(&id,&name)
fmt.Println(id,name)
}
}
func main(){
db,err:=sql.Open("mysql",dbuser+":"+dbpasswd+"@tcp("+dbhost+")/"+dbName+"?charset=utf8")
defer db.Close()
errorCheck(err)
//檢測是否連接成功,如果返回值err有值則代表失敗
err=db.Ping()
get_sql:="select * from stu"
get_info(get_sql,db)
//insert_values:=[][]string{{"5","laughing"},{"6","spring"}}
//error1:=insert_db(insert_values,db)
//fmt.Println(error1)
}
Beego操作ORM(基礎語句建議多使用)
安裝 ORM:
go get github.com/astaxie/beego/orm
據數據庫自動生成 go 代碼(從數據庫自動生成models):
1.安裝
首先我們要下載該工具 :
go get github.com/gohouse/converter
然後我們創建一個go文件執行:
package main
import (
"fmt"
"github.com/gohouse/converter"
)
func main() {
err := converter.NewTable2Struct().
SavePath("/home/go/project/model/model.go").
Dsn("root:root@tcp(localhost:3306)/test?charset=utf8").
Run()
fmt.Println(err)
}
2.查看
此時在gopath中 我們可以看見一個models的目錄,點擊進入這個目錄 裏面的model.go即爲生成的文件
創建、最簡單ID查詢、插入一條數據操作如下:
package controllers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
_"github.com/go-sql-driver/mysql" //請手動引入mysql驅動
)
type UserController struct {
beego.Controller
}
type User struct {
Id int
Name string
}
func ErrorHandler(err error){
beego.Info(err)
}
func (this *UserController) Get(){
//1.連接數據庫
err:=orm.RegisterDataBase("default","mysql","root:root@tcp(127.0.0.1:3306)/project01?charset=utf8")
ErrorHandler(err)
//2.註冊創建數據庫、若已有database則可將參數force改爲false跳過創建,verbose參數爲True時顯示創建過程
orm.RegisterModel(new(User))
err=orm.RunSyncdb("default",false,true)
ErrorHandler(err)
//3.獲取orm對象和待查詢的User對象
OrmObject:=orm.NewOrm()
UserObj:=User{Id:1}
//4.將兩個對象搭橋,創建查詢關係
err=OrmObject.Read(&UserObj)
ErrorHandler(err)
//5.打印查詢的數據
beego.Info(UserObj.Name)
this.Ctx.WriteString("GET sucess")
}
func (this *UserController) Post(){
//1.連接數據庫
err:=orm.RegisterDataBase("default","mysql","root:root@tcp(127.0.0.1:3306)/project01?charset=utf8")
ErrorHandler(err)
//2.註冊創建數據庫、若已有database則可將參數force改爲false跳過創建,verbose參數爲True時顯示創建過程
orm.RegisterModel(new(User))
err=orm.RunSyncdb("default",false,true)
ErrorHandler(err)
//3.獲取orm對象和待插入數據的User對象
OrmObject:=orm.NewOrm()
UserObj:=User{}
UserObj.Name="韓梅梅"
//4.將兩個對象搭橋,創建查詢關係
Number,err:=OrmObject.Insert(&UserObj)
beego.Info(Number)
ErrorHandler(err)
this.Ctx.WriteString("sucess")
}
以上類容便是基礎知識點了,下面我們通過練習來加強對orm、sql的理解:
(ps:
1、 一道題會用三種方案解決:1sql、2beego Orm 3Django Orm
2、Django爲python的重量級框架,爲了鞏固python知識這裏我們也將djangoOrm的解決方案寫入。)
一、我們先利用python Django生成表結構
from django.db import models
# 創建表結構
# Create your models here.
class Class_grade(models.Model):
"""年級表"""
gid = models.AutoField(primary_key=True)
gname = models.CharField(max_length=32)
class Teacher(models.Model):
"""老師表"""
tid = models.AutoField(primary_key=True)
tname = models.CharField(max_length=32)
class Classtb(models.Model):
"""班級表"""
cid = models.AutoField(primary_key=True)
caption = models.CharField(max_length=32)
grade = models.ForeignKey(to="Class_grade", on_delete=models.CASCADE)
# 多對多
teachers = models.ManyToManyField(to="Teacher")
class Student(models.Model):
"""學生表"""
sid = models.AutoField(primary_key=True)
sname = models.CharField(max_length=32)
gender = models.CharField(max_length=32)
classtb = models.ForeignKey(to="Classtb",on_delete=models.CASCADE)
class Course(models.Model):
"""課程表"""
cname = models.CharField(max_length=32)
teacher = models.ForeignKey(to="Teacher",on_delete=models.CASCADE)
class Score(models.Model):
"""成績表"""
student = models.ForeignKey(to="Student",on_delete=models.CASCADE)
course = models.ForeignKey(to="Course",on_delete=models.CASCADE)
score = models.IntegerField() #整數
二、增加數據
def addclass(request):
Student.objects.create(sname="喬丹",gender="女",classtb_id=1)
Student.objects.create(sname="艾弗森",gender="女",classtb_id=1)
Student.objects.create(sname="科比",gender="男",classtb_id=2)
Student.objects.create(sname="清風徐來",gender="男",classtb_id=3)
Course.objects.create(cname="生物",teacher_id=1)
Course.objects.create(cname="體育",teacher_id=1)
Course.objects.create(cname="物理",teacher_id=2)
c1=Classtb.objects.create(caption="一年一班",grade_id=1)
c2=Classtb.objects.create(caption="二年一班",grade_id=2)
c3=Classtb.objects.create(caption="三年二班",grade_id=3)
Score.objects.create(student_id=1,course_id=1,score=60)
Score.objects.create(student_id=1,course_id=2,score=59)
Score.objects.create(student_id=2,course_id=2,score=99)
#多對多添加表記錄
c1.teachers.add(*[1, 2])
c2.teachers.add(*[1, 3])
c3.teachers.add(2)
return HttpResponse("ok")
三、練習題:
下文查詢格式爲:
1. 問題 //此處爲問題
select * from XXX //第一句爲sql語句
models.User.object.all() //第二句爲Django
ormObj.QueryTable("XXX").RelatedSel() //第三句爲Beego
2、查詢學生總人數;Count
SELECT COUNT(sid) FROM project_student; //sql
studentNum=Student.objects.all().count() //Django orm
n,err:=o.QueryTable("Project_student").Count() //beego orm
# 3、查詢“生物”課程和“物理”課程成績都及格的學生id和姓名;
sql:
分組:
select sid,sname from student where sid in(
select score.student_id from score inner join course on score.course_id=course.cid
where course.cname in(
"生物",
"物理")
and score.score >= 60
group by score.student_id
having count(course_id) = 2
);
# 3、查詢“生物”課程和“物理”課程成績都及格的學生id和姓名;
Django:
Score.objects.filter(Q(course__cname='生物')|Q(course__cname='物理'),score__gte=60).values("student_id","student__sname").annotate(c_course=Count("course__cname")).filter(c_course=2)
# 3、查詢“生物”課程和“物理”課程成績都及格的學生id和姓名;(Beego)
1.orm執行原生sql:
o:=orm.NewOrm()
var maps []orm.Params
var sql string
tmp:=[]string{"生物","物理"}
score:=60
sql="select sid,sname from student where sid in( " +
"select score.student_id from score inner join course on score.course_id=course.id " +
"where course.cname in(?,?) and score.score >= ? " +
"group by score.student_id " +
"having count(course_id) = ? " +
");"
num,err:=o.Raw(sql,tmp,score,"2").Values(&maps)
if err!=nil{
beego.Info(err)
}
if err==nil && num>0{
for _,value:=range maps{
beego.Info(value)
}
}
2.orm查詢數據、beego處理數據
func removePro(ddbenv []string, k int) []string {
return append(ddbenv[:k], ddbenv[k+1:]...)
}
func (this *SqlControllers)HandleSql(){
o:=orm.NewOrm()
var score []*model.Score
qs:=o.QueryTable("Score")
n,err:=qs.RelatedSel("Student","Course").Filter("Score__gte",60,).Filter("Course__id__in",1,3).All(&score)
beego.Info(n,err)
tmp:=[]string{}
num:=map[string]int{}
for _,value :=range score{
beego.Info(value.Student.Sname,value.Score,value.Course.Cname,"Wwwwwwwwwww")
if len(tmp)!=0{
//1.如果tmp中老元素已存在,則將加1、 2.若加了1則刪除tmp中的老元值,防止重複
for _,item:= range tmp{
if item==value.Student.Sname{
num[item]+=1
for k,v :=range tmp{
if v==item{
tmp=removePro(tmp,k)
}
}
}
}
}
//添加數據庫中取出的元素
tmp=append(tmp,value.Student.Sname )
}
beego.Info(tmp,num)
this.Ctx.WriteString("ok")
}