zoukankan      html  css  js  c++  java
  • mysql 业务SQL语句使用记录

    /*
    
    SQL语句分类
    
    DQL(数据库查询语言): 凡是select语句都是DQL。
    
    DML(数据库操纵语言): insert delete update ,对表当中的数据进行增删改。
    
    DDL(数据库定义语言): create drop alter ,对于表结构的增删改。
    
    DCL(数据控制语言): grant授权、revoke撤销权限等。
    
    TCL(事务控制语言): commit提交事务,rollback回滚事务。
    
    
    
    
    一、导入sql脚本文件方法
    
    方法一:直接使用数据库连接工具连接数据库,然后创建相应数据库,最后直接用工具导入。
    方法二:登录mysql,创建数据库,进入数据库,执行导入 source xxx.sql。
    
    
    
    二、Mysql常用命令
    
    1、创建数据库
        create database 数据库名称;
        create database T1;
    
    2、进入数据库
        user T1;
    
    3、查询当前使用的数据库
        select database();
    
       查询数据库版本号也可以使用
        select version();
    
    4、查看表结构
        desc T1.danny;
    
    5、查看创建表的语句
        show create table T1.danny; 
    
    6、查看创建库的语句
        show create database T1
    
    
    
    三、SQL语句(不区分大小写)
    
    1、简单的查询语句(DQL)
        select 字段名1,字段名2... from 表名;
    
        select name,id from T1.user; 
    
               查询一个人的年薪(字段可以参与数学运算)
        select name,sal * 12 from T1.user;  (年薪是月薪乘以12)
    
              给查询结果的列重命名(as关键字也可以省略)
        select name,sal * 12 as yearsal from T1.user;
    
        别名中有中文
        select name as '姓名',sal * 12 as '年薪' from T1.user;  
        //也可以用双引号,但是建议字符串都用单引号,因为其他数据库不支持双引号
    ----------------------------------------------------------------------------
    
    2、条件查询
        select 字段名1,字段名2... from 表名 where 条件;
    
        查询工资等于5000的员工姓名
        select name from T1.user where sal = 5000;
    
        查询danny的工资
        select sal from T1.user where name = 'danny';
    
        找出工资高于7000的员工
        select name,sal from user where sal > 7000;
    
        找出工资不等于7000的员工
        select name,sal from user where sal <> 7000;
        select name,sal from user where sal != 7000;
    
        找出工资在3000到7000之间的员工(包括) -> [3000 ~ 7000]
        select name,sal from user where sal >= 3000 and sal <= 7000;
        select name,sal from user where sal between 3000 and 7000; 
    
        select name from user where name between 'A' and 'C';
        //用在字符上面时左闭右开
    
        
        查询哪些人津贴为空
        select name,sal,comm from user where comm is null;
        
        查询哪些人津贴不为空
        select name,sal,comm from user where comm is not null;
    
    
        查询哪些人没有津贴(包括0)
        select name,sal,comm from user where comm is null or comm = 0;
    
        and 和 or联合起来使用:找出薪资大于3000并且部门编号是20或者30的员工
        select * from user where sal > 3000 and (number = 20 or number = 30);
        注意:当运算符的优先级不确定的时候加小括号。
        
        in等同于or :找出部门编号是20和30的员工
        select name,sal,number from user where number = 20 or number = 30;
        select name,sal,number from user where number in (20,30); 
        //注意:in后面的值不是个区间,是具体的值。
    
        not in :不在这个取值当中
        select name,sal,number from user where number not in (20,30); 
        
        模糊查询like
        找出名字当中含有a的。
        其中涉及两个特殊的符号,一个是%,一个是_
        %代表任意多个字符,
        _代表任意1个字符。
        select name from user where name like '%a%';
    
        找出第二个字母是A的
        select name from user where name like '_A%';
    
        找出名字中有下划线_的
        select name from user where name like '%\_%';
    
        找出名字最后一个字母是T的
        select name from user where name like '%T';
    ----------------------------------------------------------------------------
    
    3、排序
    
        按照工资升序排序,找出员工名和薪资
        select name,sal from user order by sal;  (默认是升序)
        select name,sal from user order by sal desc;  //降序
    
        注意:asc表示升序,desc表示降序。
    
        按照工资的降序排,工资一样的按照名字升序排。
        select name,sal from user order by sal desc ,name asc;
    
        (不建议在java程序里这样写)select name,sal from user order by 2; //按照第二列排序,第二列是sal,就按sal排序。
    
    
        找出工作岗位是SALESMAN的员工,并且要求按照薪资的降序排列。
        select 
            name,sal,job 
        from 
            user 
        where 
            job = 'SALESMAN' 
        order by 
            sal desc;
        
    ----------------------------------------------------------------------------    
    
    4、分组函数(多行处理函数)
        count 计数
        sum    求和
        avg    平均值
        max    最大值
        min    最小值
        
        注意:所有的分组函数都是对"某一组"数据进行操作的。
    
        找出工资总和
        select sum(sal) from user;
    
        找出最高工资
        select max(sal) from user;
    
        找出最低工资
        select min(sal) from user;
    
        找出平均工资
        select avg(sal) from user;
    
        找出总人数
        select count(name) from user;
        select count(*) from user;
    
        注意:分组函数自动忽略NULL。
        count(*)和count(具体某个字段),他们有什么区别?
            count(*):不是统计某个字段中数据的个数,而是统计总记录条数。(和某个字段无关)
            count(comm):表示统计comm字段中不为NULL的数据总数量。
        
        分组函数组合使用
        select 
            conut(*),sum(sal),avg(sal),max(sal),min(avg)
        from
            user;
    
    
        找出工资高于平均工资的员工?(运用子查询)
            select 
                name,sal
            from
                user
            where
                sal > (select avg(sal) from user);
    ----------------------------------------------------------------------------
    
    5、单行处理函数
    
        计算每个员工的年薪(工资+津贴)
            select
                name,(sal+comm)*12
            as
                yearsal
            from
                user;
            这条sql语句执行会有问题,导致很多员工结果为NULL;
    
        注意:所有数据库都是这样规定的,只有有NULL参与的运算结果一定是NULL。
    
        ifnull() 空处理函数,属于单行处理函数
            ifnull(可能为NULL的数据,被当做什么处理)
        例:
            select 
                name,ifnull(comm,0) as comm   //把comm为NULL的当做0来处理
            from 
                user;
    
        所以上面计算每个员工的年薪(工资+津贴)修改后:
            
            select
                name,(sal + ifnull(comm,0))*12 as yearsal
            from
                user;
    ----------------------------------------------------------------------------
    
    6、group by和having (这俩货是搭档,having只能出现在group by中)
        group by;按照某个字段或者某些字段进行分组。
        having:having是对分组之后的数据进行再次过滤。
    
        案例1:找出每个工作岗位的最高薪资。
        select
            job,max(sal)     //不能加入查询name字段,因为name没有加入job分组
        from
            user
        group by
            job;
    
        以上结论:当一条语句中有group by的话,select后面只能跟分组函数和参与分组的字段。
    
    
        案例2:每个工作岗位的平均薪资
        select
            job,avg(sal)
        from
            user
        group by
            job;
        
    
        注意:分组函数一般都会和group by联合使用。
        这也是为什么它被称为分组函数的原因。
        并且任何一个分组函数都是在group by语句执行结束之后才会执行的。
        当一条sql语句没有group by的话,整张表的数据会自成一组。
    
    
        多个字段联合分组
        案例1:找出每个部门不同工作岗位的最高薪资。(此处是两个字段联合分组)
        select
            number,job,max(sal)
        from
            user
        group by
            number,job;
    
        
        案例2:找出每个部门的最高薪资,要求显示薪资大于2500的数据。
            方法一:(效率低)
            select
                number,max(sal)
            from
                user
            group by
                number
            having
                max(sal) > 2500;
    
            方法二:(实用)先过滤,再分组,效率高,建议能使用where过滤的尽量使用where,where搞不定的再用having
            select
                number,max(sal)
            from
                user
            where
                sal > 2500
            group by
                number;
    
        
        案例3:找出每个部门的平均薪资,要求显示薪资大于2000的数据。(此例where就搞不定,使用having)
            select
                number,avg(sal)
            from
                user
            group by
                number
            having
                avg(sal) > 2000;
    ----------------------------------------------------------------------------
    
    7、总结一个完整的DQL语句
        执行顺序:
        select        5
            ...
        from        1
            ...
        where        2
            ...
        group by    3
            ...
        having        4
            ...
        order by    6
            ...
        limit
            ...;    7
    
    ----------------------------------------------------------------------------
    
    8、去除重复记录
        select distinct 
            job 
        from 
            user;
    
    
        select distinct   //后面所有的字段联合起来去重
            job,number
        from
            user;
    
        案例:统计岗位的数量
        select 
            count(distinct job) 
        from 
            user;
    ----------------------------------------------------------------------------
    
    9、连接查询
        在实际开发中,大部分的情况下都不是单表中查询数据,一般都是多张表联合查询。
        根据表的连接方式来划分,包括:
            内连接:
                等值连接
                非等值连接
                自连接
            外连接:
                左外连接(左连接)
                右外连接(右连接)
    
        在表的连接查询方面有一种现象被称为:笛卡尔积现象(笛卡尔乘积现象)。
        -->当两张表进行连接查询的时候,并且没有条件限制,那么查询结果条数为两张表内数据条目的乘积。
    
    
        ---------------------------------------------------
    
        emp a 员工表 (有的人即是员工,又是领导)
        empno    ename  deptno    sal        mgr(领导编号)
        7699    danny    20        8600    NULL
        7566    jack    20        3200    7699
        7901    nancy    30        5600    7743
        7543    han        30        5400    7699
        7876    ford    10        2200    7901
        7743    james    10        6500    7699
        7231    wang    20        3000    7743
    
        上表分解出来(领导表)
        emp b 领导表
        empno    ename  deptno    sal        mgr(领导编号)
        7699    danny    20        8600    NULL
        7901    nancy    30        5600    7743
        7743    james    10        6500    7699
    
        员工的领导的编号 = 领导的员工编号
        ---------------------------------------------------
    
        dept表
        deptno    dname            loc
        10        accounting        new york
        20        research        dallas
        30        sales            chicago
        40        operations        boston
        ---------------------------------------------------
    
        salgrade表
        grade    losal    hisal
        1        700        1200
        2        1201    1400
        3        1401    2000
        4        2001    3000
        5        3001    9999
        ---------------------------------------------------
    
        案例:找出每一个员工的部门名称,要求显示员工名和部门名。
    
        SQL92:(很少用了现在)
        select
            e.ename,d.dname
        from
            emp e ,dept d
        where
            e.deptno = d.deptno; 
    ----------------------------------------------------------------------------
    9.1、内连接之等值连接:最大特点是:条件是等量关系
    
        案例:找出每一个员工的部门名称,要求显示员工名和部门名。
    
        SQL99:(常用)-->SQL99语法优点:把表连接条件和where过滤分离,结构更清晰。
        select
            e.ename,d.dname
        from
            emp e
        join   
            dept d
        on
            e.deptno = d.deptno;
    
        语法:
        ...
            A
        inner join    //此处inner可以省略,inner表示内连接
            B
        on
            连接条件
        where
            ...
    ----------------------------------------------------------------------------
    9.2、内连接之非等值连接:最大特点是:连接条件中的关系是非等量关系
    
        案例:找出每个员工的工资等级,要求显示员工名、工资、工资等级。
        select 
            e.ename,e.sal,s.grade
        from 
            emp e
        join
            salgrade s
        on
            e.sal between s.losal and s.hisal;
            
    ----------------------------------------------------------------------------
    9.3、内连接之自连接:最大特点是:一张表看做两张表,自己连接自己。
    
        案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。
        select 
            a.ename as '员工名' , b.ename as '领导名'
        from
            emp a
        join
            emp b
        on
            a.mgr = b.empno;
    ----------------------------------------------------------------------------
    9.4、外连接
        什么是外连接,和内连接有什么区别?
    
        外连接最重要的特点是:主表的数据无条件的全部查询出来。
    
        内连接:
            假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。
            AB两张表没有主副之分,两张表是平等的。
    
        外连接:
            假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询s
            主表的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL
            与之匹配。
        
        外连接的分类:
            左外连接(左连接):表示左边的这张表是主表。
            右外连接(右连接):表示右边的这张表是主表。
    
            左连接有右连接的写法,右连接也会有对应的左连接的写法。
    
        案例1:找出每个员工的上级领导。(所有员工都需要查询出来)
        内连接:
        select 
            a.ename as '员工名' , b.ename as '领导名'
        from
            emp a
        join
            emp b
        on
            a.mgr = b.empno;
    
        外连接(左连接):
        select 
            a.ename as '员工名' , b.ename as '领导名'
        from
            emp a
        left join        //表示左边的a表是主表,主表的数据都需要查出来。
            emp b
        on
            a.mgr = b.empno;  //当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL。
        
        外连接(右连接):
        select 
            a.ename as '员工名' , b.ename as '领导名'
        from
            emp b
        right outer join   //表示右边的a表是主表,主表的数据都需要查出来。outer表示外连接,可以省略
            emp a
        on
            a.mgr = b.empno;
    
    
        案例2:找出哪个部门没有员工
        select
            d.*
        from
            emp e
        right join
            dept d
        on
            e.deptno = d.deptno
        where
            e.empno is null;
    
    ----------------------------------------------------------------------------
    9.5、三张表怎么连接查询?
    
    注意:解释一下:
        ...
            A
        join
            B
        join
            C
        on
            ...
        
        表示:A表和B表先进行表连接,连接之后,A表继续和C表进行连接。
    
    
        案例1:找出每一个员工的部门名称以及工资等级。
        select 
            e.ename,d.dname,s.grade 
        from 
            emp e
        join
            dept d 
        on 
            e.deptno = d.deptno 
        join 
            salgrade s  
        on    
            e.sal between s.losal and s.hisal;
    
        
        案例2:找出每一个员工的部门名称、工资等级、上级领导。(经典例子,超级常用)这个是自己写出来的
        select 
            e.ename,b.ename as '领导',d.dname,s.grade
        from
            emp e
        left join
            emp b
        on
            e.mgr = b.empno
        join
            dept d
        on
            e.deptno = d.deptno
        join
            salgrade s
        on
            e.sal between s.losal and s.hisal;
    
    ----------------------------------------------------------------------------
    10、子查询
        什么是子查询,子查询都可以出现在哪里?
        select语句当中嵌套select语句,被嵌套的select语句是子查询。
        子查询可以出现在哪里?
            select
                ..(select).
            from
                ..(select).
            where
                ..(select).
    ----------------------------------------------------------------------------
    10.1、where子句中使用子查询
        
        案例1:找出高于平均薪资的员工信息。
        select 
            *
        from
            emp
        where sal > (select avg(sal) from emp);
        
    ----------------------------------------------------------------------------
    10.2、from后面嵌套子查询  ---以后基本用的都是这种形式的子查询
    
        案例1:找出每个部门平均薪水的薪资等级。
    
        分析:
            1.先找出每个部门对应的平均薪资作为新表
            2.用新表和等级表连接查询
    
        select 
            a.dname '部门',a.sal '平均工资',s.grade '等级' 
        from
            (select 
                d.dname,e.deptno,avg(e.sal) sal
            from 
                emp e 
            join 
                dept d
            on
                e.deptno = d.deptno
            group by 
                e.deptno) as a
        join
            salgrade s
        on
            a.sal between s.losal and s.hisal
    
        
        案例2:找出每个部门平均的薪水等级。
    
        分析:和案例1不一样了,平均的薪水等级指的是1、2、3、4、5这5个等级的平均值。
            1.先找出每个员工的薪水等级。
            2.连接部门表,把每个员工按部门分开
            3.算出平均薪水等级
    
        select
            d.dname , e.deptno, e.sal ,avg(s.grade)
        from
            emp e
        join
            dept d
        on
            e.deptno = d.deptno
        join
            salgrade s
        on 
            e.sal between s.losal and s.hisal
        group by
            e.deptno 
    
        当然如果不需要部门名称可以直接写为:
        select
            e.deptno, e.sal ,avg(s.grade)
        from
            emp e
        join
            salgrade s
        on 
            e.sal between s.losal and s.hisal
        group by
            e.deptno;
    ----------------------------------------------------------------------------
    10.3、在select后面嵌套子查询
        案例1:找出每个员工所在的部门名称,要求显示员工名和部门名
        
        写法一:
        SELECT
        e.ename,d.dname
        from 
            emp e
        JOIN
            dept d
        on 
            e.deptno = d.deptno
    
        写法二:
        SELECT
        e.ename,
        (
            SELECT
                d.dname
            FROM
                dept d
            WHERE
                e.deptno = d.deptno
        ) AS dname
        FROM
        emp e;
    
    ----------------------------------------------------------------------------
    
    11、unino (可以将查询结果集相加)
    
        案例1:找出部门是sales和research的员工
        写法一:
            select
                *
            from 
                emp e
            join dept d on e.deptno = d.deptno
            where 
                d.dname = 'sales' 
            or 
                d.dname = 'research';
        写法二:
            SELECT
                *
            FROM
                emp e
            JOIN dept d ON e.deptno = d.deptno
            WHERE
                d.dname IN ('sales', 'research')
    
        写法三:(unino)  -->两张不相干的表中的数据拼接在一起显示时,unino就可以了,or和in就不行。
            SELECT
                *
            FROM    
                emp e
            join dept d on e.deptno = d.deptno
            WHERE    
                d.dname = 'sales'
            UNION
            SELECT
                *
            FROM    
                emp e
            join dept d on e.deptno = d.deptno
            WHERE    
                d.dname = 'research'
    
    ----------------------------------------------------------------------------
    
    12、limit(重点,分页查询全靠它了)--最后执行的一个环节
        limit是mysql特有的,其他数据库没有,不通用。limit取结果集中的部分数据,这是它的作用。
    
        语法机制:
            limit startIndex,length
                startIndex    表示起始位置
                length    表示取几个
        
        案例1:取出工资前5名的员工。(思路:降序取前5个)
        select 
            * 
        from 
            emp
        order by
            sal desc
        limit 0,5;
    
        或者
    
        select 
            * 
        from 
            emp
        order by
            sal desc
        limit 5;  //可以省略前面默认的0
    
        案例2:找出工资排名在第3到6名的员工
        select 
            * 
        from 
            emp
        order by
            sal desc
        limit 2,4;  (从0开始的,第3名下标是2)
    
    ----------------------------------------------------------------------------
    
    12.1、通用的标准分页sql
        每页显示3条记录:
        第1页:0,3
        第2页:3,3
        第3页:6,3
        
        每页显示pageSize条记录:
        第pageNo页: (pageNo-1) * 3,pageSize
    
        java代码{
                int pageNo = 2; //页码是2
                int pageSize = 10; //每页显示10条
    
                limit (pageNo - 1) * pageSize,pageSize
        
        }
    
    
    
    13、MySQL触发器里的流程控制语句
        MySQL 的 case when 的语法有两种:
    
        简单函数 
        CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END
        搜索函数 
        CASE WHEN [expr] THEN [result1]…ELSE [default] END
        这两种语法有什么区别呢?
    
    
        简单函数  CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END: 枚举这个字段所有可能的值*
        SELECT
            NAME '英雄',
            CASE NAME
                WHEN '德莱文' THEN
                    '斧子'
                WHEN '德玛西亚-盖伦' THEN
                    '大宝剑'
                WHEN '暗夜猎手-VN' THEN
                    '弩'
                ELSE
                    '无'
            END '装备'
        FROM
            user_info;
    
        查询结果:
        英雄                装备
        --------------------------
        德莱文                斧子
        德玛西亚-盖伦        大宝剑
        暗夜猎手-VN            弩
        --------------------------
    
        解释:如果'NAME'是'德莱文',就把'装备'列改为'斧子',如果为其他'ELSE',就把'装备'列改为'无'。
    
    
        搜索函数 CASE WHEN [expr] THEN [result1]…ELSE [default] END:搜索函数可以写判断,并且搜索函数只会返回第一个符合条件的值,其他case被忽略
        when 表达式中可以使用 and 连接条件
        SELECT
            NAME '英雄',
            age '年龄',
            CASE
                WHEN age < 18 THEN
                    '少年'
                WHEN age < 30 THEN
                    '青年'
                WHEN age >= 30
                AND age < 50 THEN
                    '中年'
                ELSE
                    '老年'
            END '状态'
        FROM
            user_info;
    
        查询结果:
        英雄            年龄    状态
        -----------------------------
        德莱文            33        中年
        德玛西亚-盖伦    17        少年
        暗夜猎手-VN        19        青年
        -----------------------------
    
    
    ----------------------------------------------------------------------------
    
    
    DLL (create drop alter)
    
    1、创建表
        建表语句的语法格式:
            create table 表名{
                字段名1 数据类型,
                字段名2 数据类型,
                字段名3 数据类型,
                ...
            };
    
        MySQL中字段的数据类型?以下只说常见的
            int            整数型(java中的int)
            bigint        长整型(java中的long)
            float        浮点型(java中的float double)
            char        定长字符串(String)
            varchar        可变长字符串 (StringBuffer/StringBuilder)
            date        日期类型 (对应java中的java.sql.Date类型)
            BLOB        二进制大对象(存储图片、视频等流媒体信息)Binary Large Object (对应java中的Object)
            CLOB        字符大对象(存储较大文本,比如,可以存储4G的字符串)Character Large Object (对应java中的Object)
    
        char和varchar怎么选择?
            在实际开发中,当某个字段中的数据长度不会发生改变的时候,是定长的,例如:性别、生日等都是采用的char
            当一个字段的数据长度不确定,例如:简介、姓名等都是采用的varchar。
    
    
        BLOD和CLOB类型的使用
    
            电影表:t_movie
            id(int)        name(varchar)     playtime(date/char)     posters(BLOB)     history(CLOB) 
            ---------------------------------------------------------------------------------
            1            杀破狼
            2            战狼
            3            蜘蛛侠
    
        表名在数据库中一般建议以:t_或者tbl_开始
    
        创建学生表:
            学生信息包括:
                学号、姓名、性别、班级编号、生日
                学号:bigint
                姓名:varchar
                性别: char
                班级编号:int
                生日: date/char
        
        create table t_student(
        no bigint,
        name varchar(255),
        sex char(11),
        classno varchar(255),
        birth char(10)
        );
    
    ----------------------------------------------------------------------------
    2、insert语句插入数据
        语法格式:
            insert into 表名(字段名1,字段名2,字段名3,...) values(值1,值2,值3,...)
    
        要求:字段的数量和值的数量相同,并且数据类型要对应相同。
        INSERT INTO t_student (NO, NAME, sex, classno, birth)
        VALUES
            (
                1,
                'danny',
                '男',
                13311020335,
                '1999-12-18'
            ),(....),(....)
    
        drop table if exists t_student;  //如果表存在就删除
    
        创建带有默认值:
        create table t_student(
        no bigint,
        name varchar(255),
        sex char(11) default '男',
        classno varchar(255),
        birth char(10)
        );
    ----------------------------------------------------------------------------
    
    3、表的复制
        语法:
            create table 表名 as select语句;  //但是不复制结构,只复制数据
    
            CREATE TABLE emp1 AS SELECT
                *
            FROM
                emp;
        
        只复制表的结构:
            create table A like B;
    
    ----------------------------------------------------------------------------
    
    4、表的批量插入-->将表的查询结果插入到一张表中
        语法:
            insert into 表名 select语句;
    
            INSERT INTO dept1 SELECT
                *
            FROM
                dept
    
    ----------------------------------------------------------------------------
    
    5、修改表的数据(update)
        语法格式:
            update 表名 set 字段名1=值1,字段名2=值2... where 条件;
        
        注意:没有条件整张表数据全部更新
        
        案例1:将部门10的LOC修改为Shanghai,将部门名称修改为RENSHIBU
        UPDATE dept1
        SET loc = 'Shanghai',
         dname = 'RENSHIBU'
        WHERE
            deptno = 10;
    
    ----------------------------------------------------------------------------
    
    6、删除数据
        语法格式:
            delete from 表名 where 条件;  //删除小表
        注意:没有条件全部删除(危险)
    
        怎么删除大表(重点)-->比delete效率高很多
        truncate table emp1;   //截断表,就保留一个表头,注意:这是全部删除,要再三确认
    
    
    
    ----------------------------------------------------------------------------
    
    7、修改表结构(alter)--->最方便的方法就是用工具Navicat
    
    ----------------------------------------------------------------------------
    
    8、约束
    8.1、什么是约束?常见的约束有哪些呢?
        表格
        id        username(唯一性约束)    password(非空约束)
        --------------------------------------------------
        在创建表的时候,可以给表的字段添加相应的约束,添加约束的目的是为了保证表中数据的
        合法性、有效性、完整性。
    
        常见的约束有:
            非空约束(not null):约束字段不能为NULL
            唯一约束(unique):字段不能重复,但可以为NULL
            主键约束(primary key):字段既不能为NULL,也不能重复(简称PK)
            外键约束(foreign key):字段既不能为NULL,也不能重复(简称FK)
    
            检查约束(Check):注意Oracle数据库有check约束,但是mysql没有,目前mysql不支持改约束。
        
    8.2、非空约束 not null
        drop table if exists t_user;
        create table t_user(
            id int,
            username varchar(255) not null,
            password varchar(255)
        );
    
    8.3、唯一约束 unique
        drop table if exists t_user;
        create table t_user(
            id int,
            username varchar(255) unique, //[列级约束]
            password varchar(255)
        );
    
        案例:给两列或者多列添加unique
        drop table if exists t_user;
        create table t_user(
            id int,
            username varchar(255),
            password varchar(255),
            unique(username,password)  //联合唯一 [表级约束]
        );
    
        案例:给两列加两个不同的唯一约束(注意:和上面的联合唯一不一样)
        drop table if exists t_user;
        create table t_user(
            id int,
            username varchar(255) unique,  //[列级约束]
            password varchar(255) unique   //[列级约束]
        );
    
    
    
    8.4、主键约束 primary key
        
        一张表只能有一个主键
        
        主键有什么作用?
            - 表的设计三范式中有要求,第一范式就要求任何一张表都应该有主键。
            - 主键的作用:主键值是这行记录在这张表当中的唯一标识。
        
        主键的分类
            根据主键字段的字段数量来划分:
                单一主键(推荐的,常用的)
                复合主键(多个字段联合起来添加一个主键,不建议使用,因为复合主键违背三范式)
            根据主键性质来划分
                自然主键:主键值是一个和业务没有任何关系的自然数
                业务主键:主键值和系统的业务挂钩,例如:拿着银行卡的卡号做主键,拿着身份证号码作为主键(不推荐用)
    
        drop table if exists t_user;
        create table t_user(
            id int primary key,
            username varchar(255) ,
            password varchar(255)
        );
    
        
        使用表级约束方式定义主键
        drop table if exists t_user;
        create table t_user(
            id int ,
            username varchar(255),
            password varchar(255),
            primary key(id)
        );
        
    
        添加复合主键
        drop table if exists t_user;
        create table t_user(
            id int ,
            username varchar(255),
            password varchar(255),
            primary key(id,username)
        );
    
        mysql提供了主键值自增(非常重要,基本都用的这个)
        drop table if exists t_user;
        create table t_user(
            id int primary key auto_increment,
            username varchar(255),
            password varchar(255),
        );
        insert into t_user(username,password) values('A','123');
        insert into t_user(username,password) values('B','456');
        主键自动增加,自增。
    
    ----------------------------------------------------------------------------
    
    8.5、外键约束
    
        关于外键约束的相关术语:
            外键约束:foreign key
            外键字段:添加有外键约束的字段
            外键值:  外键字段中的每一个值    
    
        业务背景:
            请设计数据库表,用来维护学生和班级的信息。
                第一种方案:一张表存储所有的数据(学生信息表)
                no        name        classno            classname
                ------------------------------------------------
                1        zs1            101                二中高三一班
                2        zs2            101                二中高三一班
                3        zs3            102                二中高三二班
                4        zs4            102                二中高三二班
                5        zs5            102                二中高三二班
    
                缺点:冗余[不推荐]
    
    
    
                第二种方案:两张表(班级表和学生表)
                t_class        班级表
                cno            cname
                ------------------------
                101            二中高三一班
                102            二中高三二班
        
                
                t_student    学生表
                sno            sname            classno(该字段添加外键约束fk)
                ---------------------------------------------------------
                1            zs1                101
                2            zs2                101
                3            zs3                102
                4            zs4                102
                5            zs5                102
    
            将以上表的建表语句写出来:
                t_students中的classno字段引用t_class表中的cno字段,此时t_student表叫子表,
                t_class表叫父表。
    
                顺序要求:
                删除数据的时候,先删除子表,再删除父表。
                删除表的时候,先删除子表,再删除父表。
    
                添加数据的时候,先添加父表,再添加子表。
                创建数据的时候,先创建父表,再创建子表。
    
            drop table if exists t_student;
            drop table if exists t_class;
    
    
            create table t_class(
                cno int,
                cname varchar(255),
                primary key(cno)
            );
    
            create table t_student(
                sno    int,
                sname    varchar(255),
                classno int,
                primary key(sno),
                foreign key(classno) references t_class(cno)
            );
    
    
            insert into t_class values(101,'二中高三一班');
            insert into t_class values(102,'二中高三二班');
    
            insert into t_student values(1,'zs1',101);
            insert into t_student values(2,'zs2',101);
            insert into t_student values(3,'zs3',102);
            insert into t_student values(4,'zs4',102);
            insert into t_student values(5,'zs5',102);
    
            //插入insert into t_student values(6,'zs6',103);就会报错,因为103不是t_class中的数据
            外键约束后的字段不能随便写,必须符合父表数据
    
            
            注意1:外键值可以为NULL
            注意2:外键字段被引用的字段不一定是主键,但至少具有unique约束
    
    ----------------------------------------------------------------------------
    
    
    存储引擎
    
    1.1、完整的建表语句
    create table t_x (
        id int(11) default null,
        name varchar(255) not null
    ) engine=innodb default charset=utf8;
    
    mysql默认使用的存储引擎是Innodb方式。
    默认采用的字符集是UTF8
    
    
    1.2、什么是存储引擎
        存储引擎这个名字只有在mysql中存在。(Oracle中有对应的机制,但是不叫做存储引擎,就叫存储方式)
    
        mysql支持很多存储引擎,每一个存储引擎都对应了一种不同的存储方式。
        每个存储引擎都有自己的优缺点,需要在合适的时机选择合适的存储引擎。
    
    1.3、查看存储引擎
        show engines;
    
    
    -----------------------------------------------------------------------------------------------
    
    2、事务(Transaction)
    
        2.1、什么是事务?
            一个事务是一个完整的业务逻辑单元,不可再分。
            比如:银行账户转账,从A账户向B账户转账1000元,需要执行两条update语句。
                update t_act set balance = balance - 1000 where actno = 'act-01';
                update t_act set balance = balance + 1000 where actno = 'act-02';
            以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败。
            此时就需要使用数据库的"事务机制"。
    
        2.2、和事务相关的语句只有:DML语句(insert delete update)
            因为它们这三个语句都是和数据库表中的"数据"相关的。
            事务的存在是为了保证数据的完整性,安全性。
            通常一个"事儿"(事务[业务])需要多天DML语句共同联合完成。
    
        2.3、TCL 事务
            commit        提交
            rollback    回滚
    
        2.4、事务的特性
            事务包括四大特性:ACID
            A:原子性:事务是最小的工作单元,不可再分。  
            C:一致性:事务必须保证多余DML语句同时成功或者同时失败。
            I:隔离性:事务A和事务B之间具有隔离。
            D:持久性:持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束。
    
        2.5、关于事务之间的隔离性
            事务隔离性存在隔离级别,理论上隔离级别包括4个:
                第一级别:读未提交(read uncommitted)
                    对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
                    读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据(不稳定数据)。
    
                第二级别:读已提交(read committed)
                    对方事务提交之后的数据我方可以读取到。
                    读已提交存在的问题是:不可重复读。
                    这种隔离级别解决了:脏读现象
                
                第三级别:可重复读(repeatable read)
                    这种隔离级别解决了:不可重复读问题。
                    这种隔离级别存在的问题是:读取到的数据是幻象。
                
                第四级别:序列化读/串行化读
                    解决了所有问题。
                    效率低,需要事务排队。
    
                
                oracle数据库默认的隔离级别是:读已提交
                mysql数据库默认的隔离级别是:可重复读
    
        2.6、演示事务
            Mysql事务默认情况下是自动提交的。(只要执行任意一条DML语句就提交一次)
    
            怎么关闭自动提交?
                start transaction;
            
            准备表:
                drop table if exists t_user;
                create table t_user(
                    id int(11) primary key auto_increment,
                    username varchar(255)
                );
    
            演示:(mysql中的事务默认是自动提交的)
                mysql> insert into t_user(username) values('zs');
                Query OK, 1 row affected (0.10 sec)
    
                mysql> rollback;
                Query OK, 0 rows affected (0.01 sec)
    
                mysql> select * from t_user;   //回滚后还是一条记录
                +----+----------+
                | id | username |
                +----+----------+
                |  1 | zs       |
                +----+----------+
                1 row in set (0.03 sec)
    
            演示:(关闭自动提交)
                mysql> start transaction;
                Query OK, 0 rows affected (0.00 sec)
    
                mysql> select * from t_user;
                +----+----------+
                | id | username |
                +----+----------+
                |  1 | zs       |
                +----+----------+
                2 rows in set (0.00 sec)
    
                mysql> insert into t_user(username) values('ls');
                Query OK, 1 row affected (0.00 sec)
    
                mysql> insert into t_user(username) values('zl');
                Query OK, 1 row affected (0.00 sec)
    
                mysql> select * from t_user;
                +----+----------+
                | id | username |
                +----+----------+
                |  1 | zs       |
                |  2 | ls       |
                |  3 | zl       |
                +----+----------+
                3 rows in set (0.00 sec)
    
                mysql> rollback;
                Query OK, 0 rows affected (0.02 sec)
    
                mysql> select * from t_user;    //回滚后只有一条记录    
                +----+----------+
                | id | username |
                +----+----------+
                |  1 | zs       |
                +----+----------+
                1 row in set (0.00 sec)
    
            演示:(提交)
                mysql> start transaction;
                Query OK, 0 rows affected (0.00 sec)
    
                mysql> select * from t_user;
                +----+----------+
                | id | username |
                +----+----------+
                |  1 | zs       |
                +----+----------+
                1 row in set (0.00 sec)
    
                mysql> insert into t_user(username) values('danny');
                Query OK, 1 row affected (0.00 sec)
    
                mysql> insert into t_user(username) values('jack');
                Query OK, 1 row affected (0.00 sec)
    
                mysql> insert into t_user(username) values('nancy');
                Query OK, 1 row affected (0.00 sec)
    
                mysql> commit;
                Query OK, 0 rows affected (0.00 sec)
    
                mysql> select * from t_user;
                +----+----------+
                | id | username |
                +----+----------+
                |  1 | zs       |
                |  4 | danny    |
                |  5 | jack     |
                |  6 | nancy    |
                +----+----------+
                4 rows in set (0.00 sec)
    
                mysql> rollback;
                Query OK, 0 rows affected (0.00 sec)
    
                mysql> select * from t_user;  //提交之后,持久化到硬盘了,就算回滚结果还是不变。
                +----+----------+
                | id | username |
                +----+----------+
                |  1 | zs       |
                |  4 | danny    |
                |  5 | jack     |
                |  6 | nancy    |
                +----+----------+
                4 rows in set (0.00 sec)
    
    -----------------------------------------------------------------------------------------------    
    
    
    3、索引
        索引的作用:
            快速找到(检索到)指定的行记录。
            如果没有索引,mysql会遍历整张表,直到找到要查询的记录,这个时间代价太大。
        
        添加索引是给某一个字段,或者说某些字段添加索引。
    
        不能随意的添加索引,因为索引也是数据库中的对象,
        也需要数据库不断的维护,是有维护成本的。比如:表
        中的数据经常被修改,这样就不适合添加索引,因为数据
        一旦修改,索引需要重新排序,进行维护。
    
        注意:主键和具有unique约束的字段会自动添加索引
            所以根据主键查询的效率高,尽量使用主键检索。
    
    3.1、创建索引
        添加索引:创建表的时候,直接定义哪一个列为索引列
        mysql> create index index_id on T4;
        mysql> create table T4 (id int primary key,name char(30));  //此处的主键就是一个索引
    
        追加索引:没指定过索引列,以后再去加上索引
        mysql> alter table DB1.T3 add key index_id(id);(给id列加上索引,索引名为index_id)
        mysql> alter table DB1.T3 add key id; (索引不使用别名,默认及列名,此处索引名就为id)
    
        复合索引创建:
        mysql> alter table DB1.T3 add index(id,no,xxx...);
    
    3.2、查看索引
        mysql> show index from T3;
    
    3.3、删除索引
        mysql> drop index index_id on T4;
        mysql> alter table T4 drop index index_id;
        mysql> alter table T4 drop primary key;
    
    3.4、满足什么条件给字段添加索引?
        1) 数据量庞大
        2) 该字段很少的DML操作
    
    3.5、索引什么时候失效
        select ename from emp where ename like '%xxx%';
        模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的。
    
    
    -----------------------------------------------------------------------------------------------    
    
    4、视图(view)---用的不多
        4.1、什么是视图
            站在不同的角度去看到数据(同一张表的数据,通过不同的角度去看待)。
        
        4.2、怎么创建视图?怎么删除视图?
        create view myview as select empno,ename from emp;
        drop view myview;
    
        注意:只有DQL语句才能以视图对象的方式创建出来。
    
        4.3、对视图进行增删改查,会影响到原表数据。(通过视图影响原表数据的,不是直接操作的原表)
        可以对视图进行CRUD操作。
    
        4.4、面向视图操作。
    
        增:
            create view myview1 as select empno,ename,sal from emp1;
        
        删:(修改视图会修改原表)
            delete from myview1 where empno = 7369;//通过视图删除原表数据
        
        改:(修改视图会修改原表)
            update myview1 set ename='danny',sal=1 where empno=7369; //通过视图修改原表数据
    
        查:
            select * from myview1;
    
        4.5、视图的作用?
            视图可以隐藏表的实现细节。保密级别较高的系统,数据库只对外提供相应的视图,java程序员
            只对视图对象进行CRUD。
        
    -----------------------------------------------------------------------------------------------    
    
    5、DBA命令(运维或者DBA使用多)
        
        5.1、新建用户
            create user 'danny'@'192.168.1.1' identified by '123456';
    
            设置(修改)密码:
            mysql> set password for 'danny'@localhost = password('123');
    
            删除用户:
            mysql> drop user 'danny'@localhost;
    
    
        5.2、授权
            使用create创建的用户只有一个登陆权限(usage),裸权限
    
            查看用户权限:
            mysql> show grants for danny@192.168.1.1;
    
            添加用户+密码+赋权 ---> grant
            mysql> grant all on *.* to 'danny'@'192.168.1.1';(已有用户赋权)
            mysql> grant all on *.* to 'danny'@'localhost' identified by '123';(赋权同时创建用户)
            mysql> grant select on *.* to 'danny'@'localhost'; //赋予select权限
            mysql> grant select on *.* to 'danny'@'localhost' identified by '123'; //赋予select权限并设置密码
    
    
        5.3、收回权限
            mysql> revoke all privileges ,grant option on *.* from 'danny'@localhost; //收回权限
    
    
        5.4、导入导出
            mysqldump ...省略
    
    -----------------------------------------------------------------------------------------------
    
    6、数据库设置三范式(重点内容)
        6.1、设计表的依据,按照这个三范式设计的表不会出现数据冗余。
    
        6.2、三范式都是哪些?
            第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分。
    
            第二范式:建立在第一范式的基础之上,所有非主键字段完全依赖于主键,不能产生部分依赖。
                (所以不建议用复合主键,会产生大量的数据冗余,相同数据出现多次,浪费空间)
                
                修改前:(虽然确定了主键,但此表会出现大量的冗余,一个字段出现多次)
                sno(pk)        tno(pk)        sname        tname
                -------------------------------------------
                1001        001            张三        王老师
                1002        002            李四        李老师
                1003        001            王五        王老师
                1001        002            张三        李老师
            
                修改后 “多对多,三张表,关系表两个外键”---背住(一个学生对应多个讲师,一个讲师对应多个学生)
                只要是多对多,都这样设计
                t_student 学生表
                sno(pk)        sname
                --------------------
                1            张三
                2            李四
                3            王五
                
                t_teacher 讲师表
                tno(pk)        tname
                --------------------
                1            王老师
                2            李老师
                3            张老师
    
                t_student_teacher_relation 学生讲师关系表
                id(pk)       sno(fk)        tno(fk)
                -------------------------------
                1            1            3
                2            1            1
                3            2            2    
                4            2            2
                5            3            3
                6            3            2    
    
            第三范式:建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖。
            sno(pk)        sname     classno    classname
            ------------------------------------------
            见第三范式截图
    
            “一对多,两张表,多的表加外键”---背住  (一个班级对应多个学生)
            t_class 班级表
            cno(pk)            cname
            ----------------------
            1                班级A
            2                班级B
    
    
            t_student 学生表
            sno(pk)            sname        classno(fk)
            ---------------------------------------
            101                张1                1
            102                张2                1
            103                张3                2
            104                张4                2
            105                张5                2
            106                张6                2
    
        提醒:在实际的开发过程中,以满足客户的需求为主,有的时候,会拿冗余换执行速度。(表越多,连接查询速度越慢)
    
    
        6.3、一对一怎么设计?(重要,也需要记住)
            一对一设计有两种方案:1、主键共享  2、外键唯一
    
            t_user_login 用户登录表
            u_id(pk)        username        password
            ------------------------------------
            1               zs              123
            2               ls              456    
    
            t_user_detail 用户详细信息表(1、主键共享)
            t_id(pk+fk)        realname        tel
            -----------------------------------
            1                zs            123...
            2                ls            123...
    
    
            t_user_detail 用户详细信息表(2、外键唯一)
            t_id(pk)        realname        tel            u_id(fk+unique)
            ---------------------------------------------------------
            1                zs            123...            1
            2                ls            123...            2
    
    
    
    */

     

    好记性不如烂笔头,最难不过坚持
  • 相关阅读:
    元素定位不到的问题,Timeout,nosuch element,unable locate等
    webpack的安装
    Mysql修改表
    Mysq表的创建和l数据类型
    Mysql的库操作
    面向对象的序列化和反序列化
    类的关键字:final、const
    面向对象接口以及和继承的混合案例
    DOM创建移除替换元素
    抽象类
  • 原文地址:https://www.cnblogs.com/dannylinux/p/15625017.html
Copyright © 2011-2022 走看看