• 数据库


    第八章 数据库

    数据库的作用

    #解决了操作文件的效率和便捷问题
    #解决了多个服务同时使用数据的一致性问题
    #解决了安全的问题
    #解决了并发问题

    数据库的分类

    #关系型数据库:mysql,oracle,sqlserver,sqllite,accesse
    #非关系型数据库(存储数据快):redis,mongodb,memcache(内存级别)

    MYSQL数据库

    MYSQL操作语言分类

    1、DDL语句 数据库定义语言: 数据库、表、视图、索引、存储过程,例如CREATE DROP ALTER
    2、DML语句 数据库操纵语言: 插入数据INSERT、删除数据DELETE、更新数据UPDATE、查询数据SELECT
    3、DCL语句 数据库控制语言: 例如控制用户的访问权限GRANT、REVOKE

    Mysql存储引擎(了解)

    • 存储引擎的概念

      1:存储引擎的概念是Mysql才里才有的,不是所有的关系型数据库都有存储引擎这个概念
      2:存储引擎就是在如何存储数据、提取数据、更新数据等技术方法的实现上,底层的实现方式不同,那么就会呈现出不同存储引擎有着一些自己独有的特点和功能,对应着不同的存取机制。
      3:其实MySQL支持多种存储引擎,每种引擎有着一些自己独特的功能,用户在使用的时候,可以根据自己的业务场景来使用不同的存储引擎,其中MySQL最常用的存储引擎为:MyISAM和InnoDB。
    • Mysql工作流程

       

    • InnoDB引擎

      InnoDB引擎
             介绍:InnoDB引擎是MySQL数据库的另一个重要的存储引擎,正称为目前MySQL AB所发行新版的标准,被包含在所有二进制安装包里。和其他的存储引擎相比,InnoDB引擎的优点是支持兼容ACID的事务(类似于PostGreSQL),以及参数完整性(即对外键的支持)。Oracle公司与2005年10月收购了Innobase。Innobase采用双认证授权。它使用GNU发行,也允许其他想将InnoDB结合到商业软件的团体获得授权。

      InnoDB引擎特点:
             1.支持事务:支持4个事务隔离界别,支持多版本读。
        四大特点:原子性,隔离性,持久性,一致性*****
             2.行级锁定(更新时一般是锁定当前行):通过索引实现,全表扫描仍然会是表锁,注意间隙锁的影响。
             3.读写阻塞与事务隔离级别相关(有多个级别,这就不介绍啦~)
             4.具体非常高效的缓存特性:能缓存索引,也能缓存数据。
             5.整个表和主键与Cluster方式存储,组成一颗平衡树。(了解)
             6.所有SecondaryIndex都会保存主键信息。(了解)
             7.支持分区,表空间,类似oracle数据库。
             8.支持外键约束,不支持全文索引(5.5之前),以后的都支持了。
             9.和MyISAM引擎比较,InnoDB对硬件资源要求还是比较高的。
             
             小结:三个重要功能:Supports transactions,row-level locking,and foreign keys
    • MyISam引擎

      MyISAM引擎调优精要
             1.设置合适的索引(缓存机制)(where、join后面的列建立索引,重复值比较少的建索引等)
             2.调整读写优先级,根据实际需求确保重要操作更优先执行,读写的时候可以通过参数设置优先级。
             3.启用延迟插入改善大批量写入性能(降低写入频率,尽可能多条数据一次性写入)
             4.尽量顺序操作让insert数据都写入到尾部,较少阻塞。
             5.分解大的操作,降低单个操作的阻塞时间,就像操作系统控制cpu分片一样。
             6.降低并发数(减少对MySQL访问),某些高并发场景通过应用进行排队队列机制Q队列。
             7.对于相对静态(更改不频繁)的数据库数据,充分利用Query Cache(可以通过配置文件配置)或memcached缓存服务可以极大的提高访问频率。
             8.MyISAM的Count只有在全表扫描的时候特别高效,带有其他条件的count都需要进行实际的数据访问。
             9.可以把主从同步的主库使用innodb,从库使用MyISAM引擎。主库写,从库读可以(不推荐,有些麻烦的地方,市场上有人这么用)
    • 区别和特点

       

    MYSQL数据库安装配置文件

    #在数据库安装目录下创建一个my.ini文件,写入下面的配置,然后重启服务端(注意保存,复制pycharm上修改文件路径即可)**********

    [client]
    #设置mysql所有客户端默认字符集
    default-character-set=utf8

    [mysql]
    # 设置mysql客户端默认字符集
    default-character-set=utf8
    user = 'root'
    password = 'root'
    [mysqld]
    #设置3306端口
    port = 3306
    # 设置mysql的安装目录
    basedir=D:mysoftwaremysql-5.6.45-winx64
    # 设置mysql数据库的数据的存放目录
    datadir=D:mysoftwaremysql-5.6.45-winx64data
    # 允许最大连接数
    max_connections=200
    # 服务端使用的字符集默认为8比特编码的latin1字符集
    character-set-server=utf8
    # 创建新表时将使用的默认存储引擎
    default-storage-engine=INNODB
    #设置严格模式
    sql_mode=STRICT_TRANS_TABLES

    sql_mode设置

    • sql_mode的解释

      sql_mode是个很容易忽视的变量,默认值是空值(5.6版本,5.7版本是严格模式),在这种模式下允许一些非法操作,比如一些非法数据的插入,在生产环境必须将这个值设置为严格模式,所以开发、测试环境的数据库也必须要设置,这样在开发测试阶段就可以发现问题.
    • sql_mode常用来解决这几种问题

      (1) 通过设置sql mode, 可以完成不同严格程度的数据校验,有效地保障数据准备性。
      (2) 通过设置sql model 为宽松模式,来保证大多数sql符合标准的sql语法,这样应用在不同数据库之间进行迁移时,则不需要对业务sql 进行较大的修改。
      (3) 在不同数据库之间进行数据迁移之前,通过设置SQL Mode 可以使MySQL 上的数据更方便地迁移到目标数据库中
    • sql_mode的查询和修改方式

      #方式一:
      执行sql语句: select @@sql_mode可以查看当前会话框的sql_mode模式,
      执行sql语句: set session sql_mode='STRICT_TRANS_TABLES',就改为严格模式
      此方法在次回话关闭之后,就会失效
      #方式二:
      执行sql语句: select @@global.sql_mode 查看当前全局的sql_mode设置
      执行sql语句: set global.sql_mode = 'STRICT_TRANS_TABLES',就回修改尾严格模式
         此方法在mysql服务关闭重启之后失效,只在此次服务中有效
      #方法三:
      再mysql安装目录下,找到配置文件,在mysqld的配置文件下添加:
      sql_mode = 'STRICT_TRANS_TABLES',就能设置成严格模式,此方法需要重启mysql服务,
      从方法永久生效.当然公司的生产环境上事禁止重启mysql服务的

       

    查看mysql所有的编码格式

    #查看字符集编码的指令:
    show variables like '%char%';

    MYSQL客户端链接服务端的完整指令

    #完整版指令
    mysql -h 127.0.0.1 -P 3306 -uroot -p(密码)
    #平时使用的版本
    mysql -uroot -p(密码)

    mysql登陆密码忘记后的修改方式

    #1:停掉Mysql服务端
    net stop mysql
    #2:在cmd中路径切换到Mysql安装目录下的bin目录,然后手动启动mysql服务端:
    mysqld.exe --skip-grant-tables
    #3:服务端启动成功后,重新启动一个新的cmd窗口,链接mysql服务端
    #4:修改mysql这个库中的user表中的root用户记录的密码
    update user set password = password('123') where user='root';
    #5:关掉mysqld服务端:
    tasklist | findstr mysqld#找到mysqld的服务
    taskkill /F /PID 进程号#关闭mysqld的服务
    #6:重新启动mysql服务端(正常启动)

    登陆Mysql后修改密码的三种方式

    #方法1: 用SET PASSWORD命令 
        首先登录MySQL,使用mysql自带的那个客户端连接上mysql。
        格式:mysql> set password for 用户名@localhost = password('新密码');
        例子:mysql> set password for root@localhost = password('123');
    #方法2:用mysqladmin (因为我们将bin已经添加到环境变量了,这个mysqladmin也在bin目录下, 所以可以直接使用这个mysqladmin功能,使用它来修改密码)
        关于mysqladmin的介绍:是一个执行管理操作的客户端程序。它可以用来检查服务器的配置和 当前状态、创建和删除数据库、修改用户密码等等的功能,虽然mysqladmin的很多功能通过使 用MySQL自带的mysql客户端可以搞定,但是有时候使用mysqladmin操作会比较简单。
        格式:mysqladmin -u用户名 -p旧密码 password 新密码
        例子:mysqladmin -uroot -p123456 password 123
    #方法3:用UPDATE直接编辑那个自动的mysql库中的user表
        1:首先登录MySQL,连接上mysql服务端。
        2:mysql> use mysql;   use mysql的意思是切换到mysql这个库,这个库是所有的用户表 和权限相关的表都在这个库里面,我们进入到这个库才能修改这个库里面的表。
        3:mysql> update user set password=password('123') where user='root' and host='localhost';   #其中password=password('123') 前面的password是变量,后面 的password是mysql提供的给密码加密用的,我们最好不要明文的存密码,对吧,其中user是 一个表,存着所有的mysql用户的信息。

        4:mysql> flush privileges;  #刷新权限,让其生效,否则不生效,修改不成功

    MYSQL账号操作(了解)

    mysql> select user();  #查看当前用户
    mysql> exit     # 也可以用q quit退出

    # 默认用户登陆之后并没有实际操作的权限
    # 需要使用管理员root用户登陆
    $ mysql -uroot -p   # mysql5.6默认是没有密码的
    #遇到password直接按回车键
    mysql> set password = password('root'); # 给当前账户设置密码

    # 创建账号(IDENTIFIED BY '123',指定密码)
    create user 'eva'@'192.168.10.%' IDENTIFIED BY '123';# 指示该网段可以使用eva登陆
    create user '田彩'@'192.168.10.5' IDENTIFIED BY '123';   # 指示ip和用户名连接
    create user 'eva'@'%' IDENTIFIED BY '123';  #指示所有机器都可以通过eva账户连接  
    drop user 'eva'@'192.168.1.1'     #删除用户
    rename user '用户名'%'IP地址' to '新用户名'%'IP地址';#修改用户名
    set password for '用户名'%'IP地址'=password('新密码');#修改用户密码

    # 远程登陆(使用创建的账号,在别人的电脑)
    mysql -uroot -p123 -h 192.168.10.3;
    mysql -h 192.168.10.3 -P 3306 -uroot -p123;

    # 给账号授权
    grant all privileges on *.* to 'eva'@'%'; #给eva用户所有的权限(privileges可以不写)
    grant select,insert on 数据库.表名 to '田彩'@'%';#给用户某个库中某个表的查询,增加权限
    grant all privileges  on db1.* to "chao"@'%';#chao用户对db1数据库中的文件执行任何操作
    grant all privileges  on *.*  to "chao"@'%';#chao用户对所有数据库中文件有任何操作
    show grants for 'eva'@'192.168.10.5';#查看某个用户的权限
    flush privileges;    # 刷新使授权立即生效

    #取消权限
    revoke all on db.t1 from 'cai'@'%';#取消用户cai对t1表的所有操作
    revoke all on db.* from 'cai'@'%';#取消用户彩对db库的所有权限
    revoke all on *.* from 'cai'@'%'#取消用户彩对所有数据库所有表的权限

    # 创建账号并授权(*代表所有)
    mysql> grant all on 数据库.表名 to 'eva'@'%' identified by '123'
    mysql> grant select on *.* to 'eva'@'%' identified by '123'

    mysql数据库库的操作

    '''库操作'''
    show databases; #查询所有的数据库
    create database student; #创建一个student的库
    create database db1 charset utf8, #创建一个db1的库',并指定编码
    use student; #进去student这个库,(然后才能操作表)
    drop database student; #删除student这个库(慎用)

    mysql数据库的表操作

    1:#创建一个叫t1的表,申明引擎为innoDB
       create table t1(id int,name char(16))engine=innodb;
    2:#查看库下面的所有表
       show tables;
    3:#查看t1的表结构(desc全称describe)
       desc t1;
    4:#查看创建表的详细详细(创建语句,编码等)
       show create table t1;
    5:#删除t1这个表
       drop table t1;
    6:#修改表的名字
       alter table t1 rename student;
    7:#修改表的数据类型
       alter table t1 modify name char(16);
    8:#修改表的字段名和数据类型
       alter table t1 change name name1 char(15);
       alter table t1 change name name1 旧数据类型;
       '''
      change比modify多了一个修改字段名的功能,如果change后面要修改的数据类型使用的还是旧的 数据类型,那么就只修改了字段名,如果写的新字段名和就得字段名一样,就和modify一样只是修改   了数据类型
      '''
    9:#给t1这个表增加一个字段
    alter table t1 add name char(10) first;
    alter table t1 add age int unsigned ,add sex enum('男','女')default '男';
    alter table t1 add salary float(7,2) not null after name;
       '''
      添加字段时,可以使用逗号分割一次添加多个字段,first是表示将新添加的字段放到第一个字段的 位置去(类似于在表第一个字段前面插入一个字段),after表示的是将新添加的字段放到指定的字 段后面,上面的例子就是把salary这个字段加到name的后面,有了这两个字段就可以将新增加的字 段放到任意一个位置
      '''
    10:#给t1这个表中的字段bname添加一个约束条件
    alter table t1 add unique(bname);
    11:#把t1这个表中的主键取消
    alter table t1 drop primary key;
    12:#把t1这个表中bname字段的unique这个约束条件取消
    alter table t1 drop index 'bname';
    13:#删除表中的一个字段
    alter table t1 drop name;
    14:#复制表(了解就好)
       create table student select * from service;
       create table student select * from server where 1=2;只复制表结构
       '''
    这句话的意思是从service这个表里查询到的数据直接给了student这个要创建的表,表结构和数 据是一样的,但是不能复制主键,外键和索引,可以使用alter 给他加回来
      '''
    15:#删除外键关系
       alter table book drop foreign key book_ibfk_1(外键名称);
    16:#创建表完成之后,后添加外键关系
    alter table book add foreign key(pid) references publish(id);
    17:#创建外键时指定外键名称
       #创建表时:
    create table t1(id int,pid int,constraint fk_t1_publish foreign key(pid) references publish(id);)
    #创建表完成之后,后添加外键关系
    alter table book add constraint fk_t1_publish foreign key(pid) references publish(id);

    MYSQL数据简单操作

    '''数据操作,简单操作,详细的看下面的数据库操作'''
    1:#查看student这个表中的所有数据(*代表所有)一般少用*,因为查询效率低
        select * from student;
    2:#往student表中添加两条数据,还可以指定字段添加数据,可以插入一条和多条,用逗号分割
        insert into student values(1,'田彩'),(2,'李杰');
        insert into student(name) values('田彩'),('李杰');
        insert into student(id,name,age)select (id,name,age)from t1;
        '''
        insert 可以同时插入多条数据,也可以指定数据插入,还可以讲查询到数据插入到一张表中,上面
        最后一个示例就是把t1表中查询到的三个字段的数据,插入到student表中对应的字段中,但是这种
        插入数据的方式需要字段和数据类型等意义对应好
        '''
    3:#将id为1的name改成田少岗
        update student set name='田少岗' where id=1;
    4:#将id为1的name改成田少岗,id改成2可以指定修改多个字段的值,用逗号分割就好
        update student set name='田少岗' id=2 where id=1 
    5:#把student这个表的数据清空(慎用),删除后插入数据还是从以前最后一个id的位置开始,
        delete from student;
    6:#把student这个表中id为1的数据删掉(如果有自增id,新增的数据,仍然是以删除前的最后一样作	为起始。)
        delete from student where id = 1;
    7:#数据量大,删除速度比上一条快,且id直接从零开始,
        truncate table t1;
    

    Mysql支持的数据类型

    • 数值

      1:tinyint(1个字节)小整数型(0,255)(-128,127)tinyint unsigned(指定使用正数,不能有符	号)#*********
      2:int(4个字节)	大整数型(0,4294967295)int unsigned(指定使用正数,不能有符号)#******
      3:float 单精度浮点数值 (4个字节)float(10,5)10代表这个数据一共几位,5表示小数点后面保留	几位,最大(255,30)一般情况下不指定范围,小数点后面只保留5位,不是很准确,double也是,	  在能保留的最后一位小数上会四舍五入#***********
      4:double 双精度 浮点数 (8个字节)
      5:decimal(65,30)可以精确到小数点后面30位,不写参数,默认是10位的整数
      
    • 时间

      1:datetime 年月日时分秒 ******(可以把timestamp的属性写到后面.抄过来,show)
      2:date	   年月日   ******
      3:time	   时分秒   ***
      4:year	
      5:timestamp(约束不能为空,默认当前时间,在修改表数据时同时更新时间)
      #now()获取当前时间
      存储时间时,可以写字符串('2019-8-29 12:01:20').也可以写数字类型(201908291026)但是不能少位数
      
    • 字符串

      1:char (0-255个字节) 定长存储 设置几个就占几个位置,char(10)输入一个'田彩',也占10位,
          存储速度快,占用空间(默认为一)
      2:varchar (0-65535个字节) 变长存储 只存数输入的长度,比如输入'田彩',站的位数是2+1,这个	1是数据的长度,存储速度慢,占用空间小(必须指定长度 )
         # 记住这两个就可以了
      
    • set和enum

      1:enum enum('男','nv'),单选,只能选择括号里的选项
      2:set  set则是多选但是也必须是括号里的内容,
      

    约束

    • 约束的介绍和作用

      1:约束条件和数据类型一样,都是可选参数
      2:约束条件的作用是用于数据的完整性,和数据的一致性
      
    • 主键与常见约束(****)

      1:unsigned 无符号的,只对数字有效
      2:not null 非空约束  (是否允许为空,默认NULL,可设置NOT NULL,字段不允许为空,必须赋值)
          #create table t1(name char(10) not null);
      3:unique 唯一约束(标识该字段的值是唯一的)
          #create table t1(name char(10) unique);
      4:anto_increment 自动增加(标识该字段的值自动增长(整数类型,而且为主键))
          #create table t1(id int primary key auto_increment); 前面必须是个主键key
      5:primary key 主键约束,第一个使用not null和unique的字段就会变成主键
          #create table t1(id int primary key);
      6:default 默认值(字段是否有默认值,缺省的默认值是NULL,如果插入记录时不给字段赋值,此字段使用默认值)
          #create table t1(name char(10) not null default 'xx');
      
    • 外键 foreign key references

      • foreign key外键介绍

        1:外键就是标明表与表之间的关系
        2:表与表之间的关系有三种:一对一.一对多.多对多
        3:级联关系
            #严格模式(默认的),外键有强制约束效果,被关联字段不能随意删除和修改
            #外键有强制约束效果,被关联字段删除或者修改,关联他的那么字段数据会随之删除或者	修改
            on update cascade , on delete cascade 级联更新和删除
            #set null模式: 被关联字段删除时,关联他的字段数据会置成null
        #级联set null的示例
        mysql> create table tt2(id int primary key auto_increment,name char(10));
        
        mysql> create table tt3(id int,pid int,foreign key(pid) references tt2(id) on delete set null);
        Query OK, 0 rows affected (1.06 sec)
        
        mysql> desc tt3;
        +-------+---------+------+-----+---------+-------+
        | Field | Type    | Null | Key | Default | Extra |
        +-------+---------+------+-----+---------+-------+
        | id    | int(11) | YES  |     | NULL    |       |
        | pid   | int(11) | YES  | MUL | NULL    |       |
        +-------+---------+------+-----+---------+-------+
        2 rows in set (0.01 sec)
        
        mysql> insert into tt2(name) values('xx1'),('xx2');
        Query OK, 2 rows affected (0.14 sec)
        Records: 2  Duplicates: 0  Warnings: 0
        
        mysql> insert into tt3 values(1,1),(2,1);
        Query OK, 2 rows affected (0.12 sec)
        Records: 2  Duplicates: 0  Warnings: 0
        
        mysql> select * from tt3;
        +------+------+
        | id   | pid  |
        +------+------+
        |    1 |    1 |
        |    2 |    1 |
        +------+------+
        2 rows in set (0.00 sec)
        
        mysql> delete from tt2 where id = 1;
        Query OK, 1 row affected (0.10 sec)
        
        mysql> select * from tt3;
        +------+------+
        | id   | pid  |
        +------+------+
        |    1 | NULL |
        |    2 | NULL |
        +------+------+
        2 rows in set (0.00 sec)
        
      • 外键的作用

        1:使表的组织结构变得清晰
        2:节省空间
        3:增强扩展性
        4:保证了数据的安全性和逻辑性
        ===========
        约束作用:
            1:先要建立被关联的表,才能建立关联表
            2:再插入数据的时候,要先往被关联表中插入数据,才能往关联表中插入数据
            3:更新或者删除的时候都要考虑关联表和被关联表的关系
        
      • 一对多的关系

        1:create table dep(id int primary key auto_increment,dep_name char(16) not null);#创建部门表(被关联的表)
        2:create table emp(id int primary key auto_increment,name char(10) not null,dep_id int, foreign key(dep_id) references dep(id))#员工表(关联表)
        ================================
        '''
        创建表时,先创建被关联的表,因为关联表中外键的字段数据事来自与被关联的表中的字段,否则就会报错,再插入数据时,也是先再被关联的表中创建数据,先在关联表中创建数据的话,外键是没有值得这样也报错,在修改删除数据时,而是先删除关联表的数据,如果先删除被关联表中的数据,就会报错,原因一样,在关联表中,这个数据被关联着,是无法删除的
        
        有一个解决方案是可以在被关联表中添加两个方法,做到被关联表更新和删除的操作的时候,关联表中同步更新和删除的效果,在申明外键的时候,在后面加上两句话
        1:on delete cascade 删除同步
        2:on update cascade 更新同步
        '''
        
      • 多对多的关系

        1:create table author(id int primary key auto_increment,name char(16) not null);#表一
        2:create table blook(id int primary key auto_increment,bname char(16) not null);#表二
        3:create table author_blook(id int primary key auto_increment,author_id int,book_id int ,foreign key(author_id) references author(id) on update cascade on delete cascade,foreign key(book_id) references book(id) on update cascade on delete cascade);#中间表
        '''
        中间表需要指定两个外键,来关联两个表
        '''
        多对多的关系,可以查看博客:https://www.cnblogs.com/clschao/articles/9968396.html#_label6
        
        
      • 一对一的关系

        1:create table customer(id int primary key auto_increment,name char(16) not null,phone char(11) not null unique ,qq char(15) not null unique);#表一
        2:create table student(id int primary key auto_increment,name char(10) not null , class_name char(15) not null,cid int unique,foreign key(cid) references customer(id));#表二
        '''
        一对一的状态下,被关联的字段中的数据只能在关联表中关联一次,所有我们把关联的字段设置成unique 唯一的,这样就不会出现重复的
        '''
        
      • 对于查看表关系的总结

        #查看表关系的步骤:
        1:先从左表的角度去找(条件一)
            是否左表的多条记录可以对应右表的一条记录,则证明左表中有一个外键对应右表的一个		字段
        2:先从右表的角度去找(条件二)
            是否右表的多条记录可以对应左表的一条记录,则证明右表中有一个外键对应左表的一个		字段
        #关系总结:
        	1:如果上面的1条件成立.就是左表多对一右表
        	2;如果上面的2条件成立,就是右表多对一左表
        	3:如果两个条件都成立,就是多对多,需要定义一个三方表,来存放两张表的关系
        	4:如果两个条件都不成立,而是左表的一条数据对应右表的一条数据,就是一对一,那么确	 定主从关系,从级表中就回有一个外键指向主表,这个外键要用unique 设置唯一,
        

    数据库查询(单表查询)

    • 关键字执行的优先级(重点)

      重点中的重点:关键字的执行优先级
      1:from #找到表
      2:where #使用where指定的条件,去表中取出一条条记录
      3:group by #将取出的数据进行分组,如果没有指定,则整体作为一组
      4:having #将分组的结果按照having指定的条件进行过滤
      5:select #指定select查询
      6:distinct #去重
      7:order by #将查询的结果按照order by指定的字段进行排序
      8:limit #限制结果的显示数量
      
    • select查询操作(筛选列)

      1:#select 查询操作
      	'''
      	注意所有select 查询后面右加括号的方法,比如,select user()这种带括号的都是Mysql的	 内置方法,select本身就是查询操作,from只是说明从哪查,
      	'''
      	select * from 表名; #查询表中所有的数据  *代表所有
      	select 字段名 from 表名;#查询表中某一个字段的数据
      	select 字段名,字段名,字段名 from 表名;#查询表中多个字段的数据
      	select database();#查询返回当前操作的数据库
      	select user();#查询当前登陆的用户
      	select now;#查询返回当前的时间
      ===========================================================
      2:#distinct 去重操作
      	'''
      	当使用select查询表某些字段数据的时候,这个字段中可能出现多个重复的数据,就可以使用	distinct对查询出来的数据进行去重操作,distinct也可以对多个字段的数据进行联合去重
      	'''
      	select dictinct 字段名 from 表名;#对查出来的字段数据进行去重
      	select distinct 字段名,字段名 from 表名;#对多个字段查询的数据进行联合去重
      ===========================================================
      3:#四则运算
      	'''
      	使用select 查询某个字段的数据的时候,对数值类型的字段数据,可以进行四则运算,四则运	 算包括加减乘除等操作
      	'''
      	select 字段名*12 from 表名;#对查询出来的数据乘以12,返回结果,>>字段名要是数值类		型
      ===========================================================
      4:#concat字符串拼接和concat_ws指定分割符进行拼接(自定义显示的格式)
      	'''
      	concat内置函数可以对查询出来的字段数据进行字符串拼接
      	'''
      	select concat('姓名:',name) from 表名;#对查询出来的姓名字段的数据前面都加上一	  个字符串姓名,能够友好的显示查询出来的数据的意思,其实就是字符串拼接
      	select concat(name,':',salary)as info from 表名;#concat还可以将两个字段的数		据拼接,,产生一个新的字段数据显示出来,as是个这个字段重命名
      	'''
      	concat_ws()函数也只是字符串拼接,不过concat_ws的凭借方式是类似与python join拼接	    的方式,就是以某个元素对多个字段的数据进行拼接
      	'''
      	
          select concat_ws('_','姓名:',name,'性别:',sex)as info from 表名;
      ==========================================================
      5:#case end 语句 对查询出来的每一个数据进行加工和显示
      	'''
      	case语句的作用是,对表中数据进行查询时,对于查询出来的语句进行进一步的加工,并且显示	出来,case end语句有点像python里的if语句,不过sql的case语句需要表明开始和结		束,case代表开始,end代表结束.when代表的就是if条件,else就是其他,当有多个when的时	候,从第二个when开始就代表的类似于elif的意思,,,,,知道了解就好>>>>>>
      	'''
      select(
      	case
          when name='田少岗' concat(name,'逗比')
          when name='田彩' concat(name,'女神')
          else 
          	concat(name,'边玩去')
         	end
      )as now_name from 表名;
      ==========================================================
      6:#select的相关总结;
          可以查一个,多个,*所有
          调用函数:now(),database(),concat(),concat_ws()
          可以四则运算
          可以去重 distinct
          可以使用case end 条件判断语句
      
    • where 筛选行语句

      1:#范围查询
          #< > >= <= !=  <>代表不等于和!=是一个意思 
          select age from 表名 where age <100 and age>20;(多条件查询)
          #between 1 and 10 找寻1到10之间的
          select age from 表名 where between 1 and 100; >>注意包含1和100
          #in (1,2,3,4) 多选一
          select age from 表名 where age in (10,20,30,40);
          #将age=10和age=20的都能取出来
          select age from 表名 where age=10 or age=20;
      2:#模糊查询
          #like
          like的表现形式是,'%a'查询以a结尾的,'a%'查询以a开始的,'%a%'查询包含a的
          select name from 表名 where name like '田%';>>>查询出姓田的所有人
          like还有一种形式,'_a','a_','a__'一个划线代表一个字符,%代表的是任意长度
          select name from 表名 where name 'like '田_';>>>查询出以田开头的两个字的姓名
          #regexp 可以使用正则匹配(记一下正则表达式)
      3:#is is not 
          is null is not null 一般用来判断是不是空,
      4:#逻辑运算
          and or not	
      
    • group by(分组)

      '''group by可以对某个字段的值进行分组,这个字段有多少种值就分多少组,group by还有一个特性就是去重,一旦使用group by对数据分组了,就不能对某一条数据进行操作,永远都是这一组数据'''
      group_concat()函数(只用来做最终的显示,不做中间数据的操作)可以显示当前这一组的所有信息,拼在一起显示
      select post,group_concat(name),count(id) from employee group by post having count(id) < 2;
      '''
      mysql> set global sql_mode='STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY';
      ONLY_FULL_GROUP_BY的语义就是确定select target list中的所有列的值都是明确语义,简单的说来,在ONLY_FULL_GROUP_BY模式下,target list中的值要么是来自于聚集函数的结果,要么是来自于group by list中的表达式的值。(了解就好)
      '''
      
    • 聚合函数

      1:#count 计数
      2:#max  求最大值
      3:#avg  求平均值
      4:#min  求最小值
      5:#sum  求和
      
    • having 过滤条件

      '''
      having是针对一个组做的过滤条件,是放在group by 后面执行的,他的意思和where是一样的
      where group 和 having的执行顺序是,where>group by>having,所以having一般都是和having一起用的
      '''
      select post,group_concat(name),count(id) from employee group by post having count(id) < 2;
      
    • order by 排序

      '''
      对查询出来的数据进行排序,可以升序或者降序(desc),可以使用多个条件一起排序,执行顺序按照从左到右执行排序
      '''
      SELECT * FROM employee ORDER BY salary; #默认是升序排列
      SELECT * FROM employee ORDER BY salary ASC; #升序
      SELECT * FROM employee ORDER BY salary DESC; #降序
      
    • limit 分页

      '''
      可以和order by一起使用,先排序再分页取几个,还可以指定删选的范围,limit m,n这个意思是从m+1开始取n条数据,不如limit 0,6,就是从1开始取六条数据,然是limit分页时,只适合做小数据的分页,当数据量过大时,效率就会非常慢,limit还有一种语法是:limit n offset m,这个意思也是从m+1开始,取n条,这个语法知道就行,
      '''
      #默认初始位置为0,从第一条开始顺序取出三条 
      	SELECT * FROM employee ORDER BY salary DESC LIMIT 3;
      #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
          SELECT * FROM employee ORDER BY salary DESC
              LIMIT 0,5;  
      ##从第5开始,即先查询出第6条,然后包含这一条在内往后查5条
          SELECT * FROM employee ORDER BY salary DESC
              LIMIT 5,5; 
      

    多表查询

    • 笛卡尔积查询

      select * from 表一,表二;
      '''
      上面这个语句的执行是想查出来两张表中所有的数据,但是发现执行结果多出来好多数据,当联表查询的时候,mysql不知道如何连接两孩子那个表的关系,也不知道你想要查询那些数据,mysql就会将两张表中所有可能组合起来的数据,全部组合起来返回给你,当然这样的好处是,帮你把所有可能的组合都做好,方便查询数据,但是效率慢,
      '''
      select * from emp,dep;#将两张表拼在一起
      select * from emp,dep where dep.id = emp.dep_id; #找到两张表中对应的关系记录
      select emp.name from dep,emp where dep.id = emp.dep_id and dep.name='技术';
      #拿到筛选后的技术部门数据中emp.name的数据
      
    • inner join on 内连接

      '''
      在写sql语句的时候,让我们对语句有一个清晰的区分,增强代码的可读性,联表的操作和查询的操作有个明确的区分,就用到了内连接,左链接,右链接的方式inner join on就是内连接的意思,内连接的方式就一个弊端就是,当两个表的数据中无法通过联表指定的字段对应上的时候,就无法显示这些数据,类似集合中交集的意思,
      '''
      第一步:连表
      	select * from dep inner join emp on dep.id=emp.dep_id;
      第二步: 过滤
      	select * from dep inner join emp on dep.id=emp.dep_id where dep.name='技术';
      第三步:找对应字段数据
      	select emp.name from dep inner join emp on dep.id=emp.dep_id where dep.name='技术';
      
    • left join on 左连接(外连接)

      '''
      左连接的意思就是在内连接的基础上增加左边有,右边没有的数据,将左边的表作为主表,右边的表作为辅表,当辅表的数据没办法对应上左表的数据时,就通过null来表示(把左表的所有数据都显示)
      '''
      select * from dep left join emp on dep.id=emp.dep_id;
      
    • right join on 右链接(外连接)

      '''
      右连接于左连接的用法使一样的,不过右连接是将右表作为主表,左表作为辅表
      '''
      select * from dep right join emp on dep.id=emp.dep_id;
      
    • union 全连接

      '''
      不管是内连接还是左连接,右连接,都会由一些数据使无法显示出来的,那么就可以用全连接的方式来链接,写法是写一个左连接,一个右链接,中间用union 来连接
      '''
      select * from dep left join emp on dep.id=emp.dep_id union select * from dep right join emp on dep.id=emp.dep_id;
      
    • 子查询

      '''
      子查询是将一个查询的结果作为另一个查询的条件
      '''
      select name from emp where dep_id = (select id from dep where name = '技术');
      

    Navicat数据库链接的安装使用

    安装使用教程:https://www.cnblogs.com/clschao/articles/10022040.html
    掌握:
    #1. 测试+链接数据库
    #2. 新建库
    #3. 新建表,新增字段+类型+约束
    #4. 设计表:外键
    #5. 新建查询
    #6. 备份库/表
    
    #注意:
    批量加注释:ctrl+?键
    批量去注释:ctrl+shift+?键
    

    PyMysql模块

    • 链接参数

      host='127.0.0.1'	#计算机的IP地址
      port=3306 			#数据库的端口号
      user='root'			#数据库的用户名
      password='root'		#用户密码
      database='lucky'	#要连接数据库名
      charset='utf8'		#链接数据的编码格式
      
    • 代码示例

      import pymysql
      1:#查询
      conn = pymysql.connect(
      	host='127.0.0.1', #主机
      	port=3306, #端口号
      	user='root',#用户名
      	password='666', #密码
      	database='day43', #需要连接的库
      	charset='utf8'#指定编码
      )
      cursor = conn.cursor()#获取游标,默认获取的是元祖嵌套形式的数据
      sql = "select * from dep;" #sql语句
      ret = cursor.execute(sql) #ret 受影响的行数
      print(cursor.fetchall())  #取出所有的
      print(cursor.fetchmany(3))  #取出多条不写参数默认是取一条
      print(cursor.fetchone())  #取出单条
      
      cursor.scroll(3,'absolute')  #绝对移动,按照数据最开始位置往下移动3条
      cursor.scroll(3,'relative')  #相对移动,按照当前光标位置往下移动3条
      '''
      cursor 获取游标的时候默认获取的是元祖套元祖的数据类型,可以指定使用字段的方式,来获取字典的数据格式
      '''
      #字典格式的游标
      cursor = conn.cursor(pymysql.cursors.DictCursor)
      
    • pymysql插入数据

      #插入
      conn = pymysql.connect(
      	host='127.0.0.1', #主机
      	port=3306, #端口号
      	user='root',#用户名
      	password='666', #密码
      	database='day43', #需要连接的库
      	charset='utf8'#指定编码
      )
      cursor = conn.cursor()#获取游标,默认获取的是元祖嵌套形式的数据
      sql = "insert into t1 values (3,'xx3',18);" #sql语句
      ret = cursor.execute(sql) #ret 受影响的行数
      conn.commit()  #增删改操作时,需要进行提交
      

       

    • sql注入解决方案

      #sql注入:解决方案
      	cursor.execute(sql,[参数1,参数2...])
       import pymysql
      
      conn = pymysql.connect(
          host='127.0.0.1',
          port=3306,
          user='root',
          password='666',
          database='day43',
          charset='utf8',
      )
      while 1:
          username = input('请输入用户名:')
          password = input('请输入密码:')
          cursor = conn.cursor(pymysql.cursors.DictCursor)
          sql = "select * from userinfo where username=%s and password=%s;"
          #cursor.execute(sql,[uname,pword]) ,其实它本质也是帮你进行了字符串的替换,只不过它会将uname和pword里面的特殊字符给过滤掉。
          ret = cursor.execute(sql,[username,password])
          #ret我们说是得到的行数,如果这个行数不为零,说明用户输入的用户名和密码存在,如果为0说名存在
          if ret:#如果输入的用户名和密码错误,这个结果为0,如果正确,这个结果为1
              print('登录成功')
          else:
              print('账号或者密码错误,请重新输入!!!')
      

       

    • 获取插入的最后一条数据的自增ID

      import pymysql
      conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
      cursor=conn.cursor()
      sql='insert into userinfo(name,password) values("xxx","123");'
      rows=cursor.execute(sql)
      print(cursor.lastrowid) #在插入语句后查看
      conn.commit()
      cursor.close()
      conn.close()
      

    Mysql数据库数据备份和恢复

    #使用mysqldump实现数据库的备份
    mysqldump -uroot -p -B -d 库名 > f:数据库备份练习crm2stru.sql
    Enter password: ***
    '''
    mysqldump也是mysql数据库的一个命令,-u用户名,-p密码 -B指的是在备份数据的时候,备份的数据增加建库的语句和use语句,>号后面指定路径数据备份保存的路径和文件名
    '''
    #利用mysql命令回复数据
    '''
    恢复数据首先要把数据库中原来的库删除,然后把备份的数据导入进来,<号表示得就是要导入进来,后面写上备份数据的路径,运行就可以回复数据
    '''
    mysql -u用户名 -p 密码 库名 < f:数据库备份练习crm2stru.sql
    

    索引

    • 原理

      索引在MySQL中也叫做“键”或者"key"(primary key,unique key,还有一个index key),是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要,减少io次数,加速查询。(其中primary key和unique key,除了有加速查询的效果之外,还有约束的效果,primary key 不为空且唯一,unique key 唯一,而index key只有加速查询的效果,没有约束效果)
      
      强调:一旦为表创建了索引,以后的查询最好先查索引,再根据索引定位的结果去找数据
      
      索引的影响
            1、在表中有大量数据的前提下,创建索引速度会很慢
            2、在索引创建完毕后,对表的查询性能会发幅度提升,但是写性能会降低
      
          本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
      '''
      索引的作用主要是用来加速查询的效率,数据存储时,会根据聚集索引存储成一种数据结构,叫做B+树的数据结构(下图),数据都回存储在叶子节点上(图中最下面的一层),除了聚集索引还有普通话索引,普通索引存储的是索引字段这一列的数据和聚集索引(回表操作),存储数据的时候选择索引尽量选择字段数据较小的尾索引字段
      '''
      
    • 索引的数据结构

       

    • 主键索引

      #添加主键索引:
      		创建的时候添加:  添加索引的时候要注意,给字段里面数据大小比较小的字段添加,给字段里面的数据区分度高的字段添加(一般添加到id字段上).
      		聚集索引的添加方式
      		创建的时候添加
      		Create table t1(
      			id int primary key,
      		)#方式一
      		Create table t1(
      			id int,
      			primary key(id)
      		)#方式二
      		表创建完了之后添加
      			Alter table 表名 add primary key(id);#当数据量大的时候,效率会很慢
      		删除主键索引:
      			Alter table 表名 drop primary key;#当数据量大的时候,效率会很慢
      
    • 普通索引

      #普通索引:
      '''
      当查询的数据就是普通索引这一列的时候,普通索引也叫覆盖索引
      '''
      		创建:
      			Create table t1(
      				Id int,
      				Index index_name(id)
      			)
      			Alter table s1 add index index_name(id);
      			Create index index_name on s1(id);
      
      		删除:
      			Alter table s1 drop index u_name;
      			DROP INDEX 索引名 ON 表名字;
      
    • 联合索引

      #联合索引(联合主键联合唯一联合普通索引)	
      		Create table t1(
      				Id int,
      				name char(10),
      				Index index_name(id,name)
      			)
          '''
      	联合索引在申明的时候,是申明几个字段作为索引,再查找的数据的时候,如果也要使用索引来提升查询速度,就要按照索引字段的顺序来查找,比如在查找一条数据的时候,联合索引的字段为name,age,那个在指定where条件的时候,一定更要使用到name字段,否则就无法使用这个索引,还有当使用联合索引的时候,多个字段中,如果出现范围查找的字段,那么在这个范围字段后面的字段再查找的时候联合索引也无法使用		
      			'''
          
      #explain可以查看查找数据时,扫描了多少条数据,数字越少速度越快
      explain select * from student where name='田cai'; 
      

       

    • 唯一索引

      #唯一索引:
      		Create table t1(
      			int unique,
      		)
      
      		Create table t1(
      			id int,
      			unique key uni_name (id)
      		)'''unique key 后面是给这个索引取名字,这个名字可以写可以不写,不写的情况下一般以指定的索引字段名命名'''
      		表创建好之后添加唯一索引:
      		alter table s1 add unique key  u_name(id);
      		删除:
      		Alter table s1 drop index u_name;
      

       

    事务和锁

    #行锁:
    	select * from 表名 where id=1 for update;#排他锁,上锁之后,其他用户对这个表的增删改查就回阻塞,等你操作完成之后,其他用户才能操作
        SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE;#共享锁(其他用户可以查询,不能对数据进行增删改)
    #表锁:
    	共享读锁:lock table tableName read;
       独占写锁:lock table tableName write;
    	批量解锁:unlock tables;
    #事务:
    	begin;或者 start transaction;#开启事务
        commit;提交#提交事务
        rollback;回滚#回滚事务
        https://www.cnblogs.com/clschao/articles/10034539.html#_label4(博客链接)
    '''
    原子性(Atomicity):事务是一个原子操作单元。在当时原子是不可分割的最小元素,其对数据的修改,要么全部成功,要么全部都不成功。
    一致性(Consistent):事务开始到结束的时间段内,数据都必须保持一致状态。
    隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的"独立"环境执行。
    持久性(Durable):事务完成后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。。'''
  • 相关阅读:
    ansible-playbook启动的多种方式
    git版本控制
    特征工程
    特征工程:图像特征提取和深度学习
    tensorflow数据读取机制tf.train.slice_input_producer 和 tf.train.batch 函数
    浙大版《C语言程序设计(第3版)》题目集 练习2-9 整数四则运算 (10 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-8 计算摄氏温度 (10 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-6 计算物体自由下落的距离 (5 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-4 温度转换 (5 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-3 输出倒三角图案 (5 分)
  • 原文地址:https://www.cnblogs.com/Tian-Cai-1996/p/12245830.html
Copyright © 2020-2023  润新知