序言
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")
}