zoukankan      html  css  js  c++  java
  • 数据库总结

    多表之间的关联最好是用逻辑上的关联,而不是物理上的关联,导致后期的扩展性差!!!

    原生sql

    --mysql5.6

    建表

    一对多:

    create table dept(id int primary key auto_increment,name char(20),job char(20));
    create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id));
    一对多建表

    多对多:

     1 create table teacher(id int primary key auto_increment,name char(15));
     2 create table student(id int primary key auto_increment,name char(15));
     3 #中间表
     4 create table tsr(
     5 id int primary key auto_increment,
     6 t_id int,s_id int,
     7 foreign key(t_id) references teacher(id),
     8 foreign key(s_id) references student(id)
     9 );
    10 现在老师和学生 都是主表  关系表是从表
    11 先插入老师和学生数据
    12 insert into teacher values
    13 (1,"高跟"),
    14 (2,"矮跟");
    15 
    16 insert into student values
    17 (1,"炜哥"),
    18 (2,"仨疯");
    19 
    20 # 插入对应关系
    21 insert into tsr values
    22 (null,1,1),
    23 (null,1,2),
    24 (null,2,2);
    25 
    26 建表语句,中间表及插数据语句
    多对多建表

    一对一:

    客户和学生
    一个客户只能产生一个学生
    一个学生只能对应一个客户
    这样的关系是一对一
    使用外键来关联,但是需要给外键加上唯一约束
    客户和学生有主从关系,需要先建立客户,再建学生
    
    create table customer(c_id int primary key auto_increment,
    name char(20),phonenum char(11),addr char(20));
    
    create table student1(s_id int primary key auto_increment,
    name char(20),
    class char(11),
    number char(20),
    housenum char(20),c_id int UNIQUE,
    foreign key(c_id) references customer(c_id)
    );
    
    示例,建表语句
    一对一建表

    查询

    单表查询:

    不带关键字的查询
        select  {*|字段名|四则运行|聚合函数} from 表名 [where 条件]
        1.* 表示查询所有字段
        2.可以手动要查询的字段
        3.字段的值可以进行加减乘除运算
        4.聚合函数,用于统计
        where是可选的
    View Code

    一对多查询五种方式:

    1.笛卡尔积查询
    select *from 表1,表n
    查询结果是
    将左表中的每条记录,与右表中的每条记录都关联一遍
    因为他不知道什么样的对应关系是正确,只能帮你都对一遍
    a表有m条记录,b表有n条记录
    笛卡尔积结果为m * n 记录
    
    需要自己筛选出正确的关联关系
    select *from emp,dept where emp.dept_id = dept.id;
    
    2.内连接查询就是笛卡尔积查询:[inner] join
    select *from emp [inner] join dept;
    select *from emp inner join dept where emp.dept_id = dept.id;
    
    3.左外链接查询:left join
    select *from emp left join dept on emp.dept_id = dept.id;
    左表数据全部显示,右表只显示匹配上的
    
    4.右外链接查询:right join
    select *from emp right join dept on emp.dept_id = dept.id;
    右表数据全部显示,左表只显示匹配上的
    
    内和外的理解:内指的是匹配上的数据,外指的是没匹配上的数据
    
    5.全外连接:union
    select *from emp full join dept on emp.dept_id = dept.id;  ##mysql不支持
    
     union: 合并查询结果,默认会去重
     select *from emp left join dept on emp.dept_id = dept.id
     union
     select *from emp right join dept on emp.dept_id = dept.id;
    
     union 去除重复数据,只能合并字段数量相同的表
     union all 不会去除重复数据
    
    on,where关键字都是用于条件过滤,没有本质区别
    在单表中where的作用是筛选过滤条件
    只要是连接多表的条件就使用on,为了区分是单表还是多表,搞个新的名字就是on
    在多表中on用于连接多表,满足条件就连接,不满足就不连接
    View Code

     多对多查询:

    create table stu(id int primary key auto_increment,name char(10));
    create table tea(id int primary key auto_increment,name char(10));
    
    #中间表
    create table tsr(id int primary key auto_increment,t_id int,s_id int,
    foreign key(s_id) references stu(id),
    foreign key(s_id) references stu(id));
    #插数据
    insert into stu values(null,"张三"),(null,"李李四");
    insert into tea values(null,"chuck"),(null,"wer");
    insert into tsr values(null,1,1),(null,1,2),(null,2,2);
    #查询语句,多表查询过滤条件用on
    select *from stu join tea join tsr
    on stu.id = tsr.s_id and tea.id = tsr.t_id
    where tea.name = "chuck";
    View Code

     子查询:

    给你部门的的名称,查部门有哪些人?
        第一步查到部门的id
        第二部拿着id去员工表查询
    select *from dept join emp on dept.id = emp.dept_id;
    
    select *from emp join
    # 使用子查询,得到每个部门的id以及部门的最高工资,形成一个虚拟表,把原始表和虚拟表连接在一起
    (select dept_id,max(salary)as m from emp group by dept_id) as t1
    # 如果这个人的部门编号等于虚拟表中的部门编号
    on emp.dept_id = t1.dept_id
    and
    # 并且,如果这个人的工资等于虚拟表中的最高工资,就是你要找的人
    emp.salary = t1.m;
    View Code

    orm增删改

    --django

    单表操作

    增:

    date类型,传的时候,可以传字符串(格式必须是:2018-06-17),可以传时间对象
    ret=models.Book.objects.create(name='洪流吗',price=23.7,publish='北京出版社',pub_data='2018-06-17')
    
    生成对象,再调save方法
    book=models.Book(name='三国演义',price=46.89,publish='南京出版社',pub_data='2017-08-17')
    book.save()
    create或create-save

    删:

    ret=models.Book.objects.filter(pk=1).delete()  --pk指主键
    
    book=models.Book.objects.filter(pk=1).first()
    book.delete()
    delete或取first-delete

    改:

    ret = models.Book.objects.filter(pk=2).update(name='ddd')
    
    book=models.Book.objects.filter(pk=2).first()
    book.name='XXX'
    # 没有update这个方法的
    # book.update()
    # 既可以保存,又可以更新
    book.save()
    
    get方法
    book = models.Book.objects.filter(pk=2).first()
    # book拿到的是 book对象
    #get查到的数据有且只有一条,如果多,少,都抛异常
    book=models.Book.objects.get(name='XXX')
    print(book.name)
    update或赋值-save

    查:

    • 基于对象:
    <1> all():                  查询所有结果
       book=models.Book.objects.all()
    <2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象              
    <3> get(**kwargs):          返回与所给筛选条件相匹配的对象,返回结果有且只有一个,超过一个或者没有都会抛出错误。              
    <4> exclude(**kwargs):      它包含与所给筛选条件不匹配的对象,exclude = 排除
    <5> order_by(*field):       对查询结果排序('-id'),取负号即反转
    <6> reverse():              对查询结果反向排序,必须在order_by之后才能调用。
       book=models.Book.objects.order_by('price').reverse()
    <8> count():                返回数据库中匹配查询(QuerySet)的对象数量。 
       book=models.Book.objects.all().count()
    <9> first():                返回第一条记录  
    <10> last():                返回最后一条记录  
    <11> exists():              如果QuerySet包含数据,就返回True,否则返回False 
    <12> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后不是一系列model的实例化对象,而是一个可迭代的字典序列
    <13> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
    <14> distinct():            从返回结果中剔除重复纪录
    查询API
    • 基于双下划线:
    price__in:__前为字段名,后为对应方法;
    Book.objects.filter(price__in=[100,200,300]) --在列表范围内
    Book.objects.filter(price__gt=100) --大于
    Book.objects.filter(price__lt=100) --小于
    Book.objects.filter(price__gte=100) --大于等于
    Book.objects.filter(price__lte=100) --小于等于
    Book.objects.filter(price__range=[100,200]) --在100-200之间
    Book.objects.filter(title__contains="python") --包含Python
    Book.objects.filter(title__icontains="python") --包含Python且区分大小写
    Book.objects.filter(title__startswith="py") --以py开头
    Book.objects.filter(pub_date__year=2012) --获取对应年份,月,日数据
    基于双下划线模糊查询

    多表操作

    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField()
        # 阅读数
        # reat_num=models.IntegerField(default=0)
        # 评论数
        # commit_num=models.IntegerField(default=0)
    
        publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
        authors=models.ManyToManyField(to='Author')
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)
    
    
    class AuthorDatail(models.Model):
        nid = models.AutoField(primary_key=True)
        telephone = models.BigIntegerField()
        birthday = models.DateField()
        addr = models.CharField(max_length=64)
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    
    models.py
    创建模型
    正向:关联关系在当前表中,从当前表去另一个表;正向查询按字段名
    反向:关联关系不在当前表,从当前表去另一个表;反向查询按表名小写 

    一对一:

    • 增加
    author=models.Author.objects.create(name='小猴',age=16,author_detail_id=authordetail.pk)
    create

    一对多:

    • 增加
    # publish:可以传一个publish对象
    publish=models.Publish.objects.get(pk=1)
    print(publish.name)
    ret=models.Book.objects.create(name='西游记',price=88,publish_date='2018-09-12',publish=publish)
    
    # publish_id:传一个id
    ret=models.Book.objects.create(name='三国演义',price=32,publish_date='2018-07-12',publish_id=publish.pk)
    print(type(ret.publish))
    create--传对象或id
    • 修改
    book=models.Book.objects.get(pk=2)
    book.publish_id=2
    # book.publish=出版社对象
    book.save()
    
    ret=models.Book.objects.filter(pk=2).update(publish=publish对象)
    
    ret=models.Book.objects.filter(pk=2).update(publish_id=2)
    save/update对象或ID
    • 删除

    多对多:

    • 增加
    #给红楼梦这本书添加两个作者(lqz,egon)
    book = models.Book.objects.get(pk=1)
    #相当于拿到了第三张表
    往第三章表中添加纪录(问题来了?要传对象还是传id),都支持
    book.authors.add(1,2)
    
    lqz = models.Author.objects.get(pk=1)
    egon = models.Author.objects.get(pk=2)
    book.authors.add(lqz,egon)
    
    book.authors.add(*[lqz,egon])
    add对象或Id
    • 删除
    #remove字段authors的id和名字都可以(名字为通过id获取的)
    book.authors.remove(2)
    book.authors.remove(egon,lqz)
    book.authors.remove(1,2)
    book.authors.remove(*[1,2])
    book.authors.remove(*[lqz,egon])
    remove对象或id
    • 修改
    #修改红楼梦这本书的作者为lqz和egon
    #先清空(清空这本的所有作者记录)
    book.authors.clear()
    book.authors.add(1,2)
    #id
    book.authors.set(*[6,])   #这样不行
    book.authors.set([6,])   #需要这样传
    
    #对象
    lqz=models.Author.objects.get(pk=2)
    set 必须传一个可迭代对象
    book.authors.set([lqz,])   #需要这样传
    clear+add或set

    orm查询

    基于对象的跨表查询(多次查询)
        一对一:
            -正向查询按字段
            -反向查询按表名小写
        一对多:
            -正向查询按字段(正向查询一定会查出一个来)
            -反向查询按表名小写_set.all()(返回结果是queryset对象)
        
        多对多:
            -正向查询按字段.all()(正向查询一定会查出多个来)
            -反向查询按表名小写_set.all()(返回结果是queryset对象)
        
    基于双下划线的跨表查询
        -在filter和values中都可以做连表操作(也就是都可以写 __)
        -正向查询按字段
        -反向查询按表名小写
        
        无论以谁做基表,没有效率之分
    查询之禅

     基于对象:

    • 一对一

    #查询lqz作者的地址(正向查询,按字段)
    lqz=models.Author.objects.filter(name='lqz').first()
    # 作者详情对象
    print(lqz.author_detail.addr)
    
    #查询地址为上海的,作者的名字(反向查询,按表名小写)
    authordetail=models.AuthorDatail.objects.filter(addr='上海').first()
    #拿到的是作者对象authordetail.author
    print(authordetail.author.name)
    View Code
    • 一对多

    #查询红楼梦这本书的出版社名字(正向,按字段)
    book=models.Book.objects.get(pk=1)
    #出版社对象 book.publish
    print(book.publish.name)
    #查询北京出版社出版的所有书名(反向查询按 表名小写_set.all())
    publish=models.Publish.objects.get(pk=1)
    #结果是queryset对象
    books=publish.book_set.all()
    for book in books:
        print(book.name)
    #查询以红开头的
    books=publish.book_set.all().filter(name__startswith='')
    for book in books:
        print(book.name)
    View Code
    • 多对多

    #红楼梦这本书所有的作者(正向 字段)
    book=models.Book.objects.get(pk=1)
    # book.authors.all()拿到所有的作者,是一个queryset对象
    authors=book.authors.all()
    for author in authors:
        print(author.name)
    #查询egon写的所有书(反向 表名小写_set.all())
    egon=models.Author.objects.get(pk=2)
    #拿到的是queryset对象
    books=egon.book_set.all()
    for book in books:
    print(book.name)
    View Code

     基于双下划线:

    • 一对一

    #查询lqz作者的名字,地址(正向查询,按字段)
    ret=models.Author.objects.filter(name='lqz').values('name','author_detail__addr')
    print(ret)
    #查询地址为上海的作者的名字(反向,按表名小写)
    ret=models.AuthorDatail.objects.filter(addr='上海').values('addr','author__name','author__age')
    print(ret.query)
    print(ret)
    View Code
    • 一对多

    #查询红楼梦这本书的出版社的名字(正向  按字段)
    ret=models.Book.objects.filter(name='红楼梦').values('name','publish__name')
    print(ret)
    #查询北京出版社出版的所有书的名字(反向  按表名小写)
    ret=models.Publish.objects.filter(name='北京出版社').values('book__name')
    print(ret)
    View Code
    • 多对多

    #红楼梦这本书所有的作者名字(正向  按字段)
    ret=models.Author.objects.filter(book__name='红楼梦').values('name')
    print(ret)
    
    ret=models.Book.objects.filter(name='红楼梦').values('authors__name')
    print(ret)
    #egon出版的所有书的名字(反向 表名小写)
    ret=models.Book.objects.filter(authors__name='egon').values('name')
    print(ret)
    ret=models.Author.objects.filter(name='egon').values('book__name')
    print(ret)
    #查询北京出版社出版过的所有书籍的名字以及作者的姓名
    ret=models.Publish.objects.filter(name='北京出版社').values('book__name','book__authors__name')
    print(ret)
    ret=models.Book.objects.filter(publish__name='北京出版社').values('name','authors__name')
    print(ret)
    ret=models.Author.objects.filter(book__publish__name='北京出版社').values('book__name','name')
    print(ret)
    
    #地址是以北开头的作者出版过的所有书籍名称以及出版社名称
    #以authordetial为基表
    ret = models.AuthorDatail.objects.filter(addr__startswith='').values('author__book__name',
                                                                          'author__book__publish__name')
    print(ret)
    #以book为基表
    ret=models.Book.objects.filter(authors__author_detail__addr__startswith='').values('name','publish__name')
    print(ret.query)
    #以author为基表
    ret=models.Author.objects.filter(author_detail__addr__startswith='').values('book__name','book__publish__name')
    print(ret.query)
    View Code
  • 相关阅读:
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 88怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 81.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 40怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 24.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 21.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器试运行提示过速度保护怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器如何执行绝对值清零
    倍福TwinCAT(贝福Beckhoff)基础教程 松下绝对值驱动器如何做初始化设置
    倍福TwinCAT(贝福Beckhoff)基础教程 松下官方软件开启报错伺服未就绪怎么办
    JAVA Eclipse 启动 Eclipse 弹出“Failed to load the JNI shared library jvm_dll”怎么办
  • 原文地址:https://www.cnblogs.com/xuechengeng/p/10542442.html
Copyright © 2011-2022 走看看