MySQL5.7 基础之二 DCL DML

设计范式:

  第一范式:字段是原子性

  第二范式:存在可用主键

  第三范式:任何表都不应该有依赖于其它表非主键的字段

 

创建数据库、设计数据表

  字段:字段名、数据类型、约束(通过键来实现,而键其实可以当做索引来用)

 

获取程序默认使用的配置:

[root@localhost ~]# mysqld --print-defaults;

 

获取可用参数列表:mysqld --help  -verbose

获取运行中的mysql进程使用各个服务器参数及其值:    

  mysql> SHOW GLOBAL VARIABLES;
  mysql> SHOW [SESSION] VARIABLES;
注:其中有些参数支持运行时修改,会立即生效;有些参数不支持,且只能通过修改配置文件,并重启服务器程序生效;
  有些参数作用域是全局的,且不可改变;有些可以为每个用户提供单独的设置

 

修改服务器变量的值:

  mysql>help SET

  全局:mysql>SET  GLOBAL|@@global.   system_var_name=value;

  会话:mysql>SET [SESSION|@@session. | @@]  system_var_name=value;

状态变量:用于保存mysqld运行中的统计数据的变量 (不可修改)

  mysq> SET GLOBAL STATUS;

  mysq> SET [SESSION] STATUS;

 

=======================================================================================

DDL:CREATE、DROP、ALTER

DML:INSERT(REPLACE)、DELETE、UPDATE 、SELECT

DCL:GRANT、REVOKE

 

数据类型: datatype
    字符:
        定长字符:
            不区分大小写 char(#) 用或不用,给1个占10个
            区分大小写 binary(#)

        变长字符: 
            不区分大小写 varchar(#) 有结束符,占用一个, 给1个,占2个
            区分大小写 varbinary(#)

        对象存储:大文本存储
            TEXT 不区分大小写
            BLOB  区分----二进制的大对象
        内置类型:
            ENUM   枚举(给你几种,最多有几种选择)
            SET    集合
    数值:    
        精确:整型[int]、十进制[decimal]
            int
                tinyint   1byte
                smallint  2bytes
                mediumint 3bytes
                int       4bytes
                bigint       8bytes  范围: 0 - 2^64-1
        近似: 单精度浮点[float]、双精度浮点[double]
    日期时间型
       日期:DATE
       时间:TIME
       日期时间:TIMESTAMP
       年份:YEAR(2),YEAR(4)
修饰符:
 所有类型:   NOT NULL :非空约束   DEFAULT NULL :设定默认值
  
UNIQUE KEY
PRIMARY KEY
 数值型适用:
  UNSIGNED :(对整型和数值型)无符号---不能表示负数,仅用于表示正数
   AUTO_INCREMENT :自增长--整型
  

二、数据库基础应用:

2.1、DDL

2.1.1、创建表:

(1)直接创建
 CREATE  TABLE [IF NOT EXISTS] 'tbl_name' (col1 type1,col2 type2, ...)
  col1 type1:
     PRIMARY KEY(col1,...)
     INDEX(col1,...)
     UNIQUE KEY(col1,...)
(2)通过查询现存的表创建:新表会被直接插入查询而来的数据:

  CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    (create_definition,...)
    [table_options]
    [partition_options]

(3)通过复制现存的表的表结构创建:不复制数据 

   CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_tbl_name | (LIKE old_tbl_name) }
注:Storage Engine是指表类型,也即在表创建时指明其使用的存储引擎:
  同一个库中表要使用同一种存储引擎类型


查询默认引擎:
  mysql>SHOW ENGINES;
获取帮助:
  
mysql>HELP CREATE TABLE;

获取表创建命令:

 mysql> SHOW CREATE TABLE students;

查询表状态:
  mysql>SHOW TABLE STATUS LIKE 'tbl_name' \G; \G--把每一行数据竖排显示
删除表
  mysql> DROP TABLE [IF EXISTS] 'tbl_name';
查看表上的索引
  
mysql> SHOW INDEXES FROM [db_name.]tbl_name;
查看表结构
   mysql> DESC tbl_name;
查看某库中的表
   mysql> SHOW TABLES FROM database_name; 

mysql> SHOW GLOBAL VARIABLES LIKE '%default%';

 

E.G 

定义单字段的唯一键:

mysql> CREATE TABLE students (id int UNSIGNED NOT NULL PRIMARY KEY,name VARCHAR(20) NOT NULL,Age tinyint UNSIGGNED);

多字段组合式唯一键(两者联合起来不一样就可以):

mysql> CREATE TABLE tbl2 (id int UNSIGNED NOT NULL ,name VARCHAR(20) NOT NULL,Age tinyint UNSIGNED,PRIMARY KEY(id,name));

 

2.1.2、ALTER 修改表

  帮助:
    mysql>HELP ALTER TABLE;

ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}  设定默认值或移除默认值这两个属性

CHANGE [COLUMN] old_col_name new_col_name column_definition    修改字段名字和字段定义
  [FIRST|AFTER col_name]

MODIFY [COLUMN] col_name column_definition      只修改字段定义 或字段的排序
  [FIRST | AFTER col_name]

语法:
ALTER TABLE 'tb_name'

  a) 字段:

    添加字段:add        

  | ADD [COLUMN] col_name  column_definition [FIRST | AFTER col_name]
  e.g  mysql> ALTER TABLE students ADD gender ENUM('m','f')  AFTER name;

    删除字段:drop

      e.g  mysql> ALTER TABLE students drop  gender ;  

    修改字段:alter(删除字段默认值)、change(该字段名称)、modify(字段属性定义)

        注:该字段名字的时候,还必须把字段的属性定义出来,任何字段都有其字段定义
         类型修饰符必须紧跟在类型后面
         如果主键定义过,可以不需要重新定义。
e.g
修改字段名称
mysql
> ALTER TABLE students CHANGE id sid int UNSIGNED NOT NULL PRIMARY KEY;   ERROR 1068 (42000): Multiple primary key defined mysql> ALTER TABLE students CHANGE id sid int UNSIGNED NOT NULL ;   Query OK, 0 rows affected (0.01 sec)   Records: 0 Duplicates: 0 Warnings: 0

  b) 索引: 键都是索引,但索引不是键

    添加索引:add     

添加唯一键约束:
   | ADD [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] [index_name]
  e.g    mysql> ALTER TABLE students ADD UNIQUE KEY(name);
添加索引:
   | ADD {INDEX|KEY} [index_name]   
  e.g    mysql> ALTER TABLE students ADD INDEX(age); 

    删除索引:drop

  注:每个索引都有Key_name字段值,如果定义索引时没给索引名字,那么索引名字就是字段名字;如果索引在多键上,那么索引名字就是多键上的第一个字段名字

  c) 表选项 (副作用大一般不用)

2.1.3索引:是特殊数据结构;定义在查找时作为查找条件的字段;只用添加和删除

   索引类型:

      聚集索引、非聚集索引:数据是否与索引存储在一起;

      主键索引、辅助索引

      稠密索引、稀疏索引:是否索引了每一个数据项 

     优点:加速查询操作

   缺点:额外占用空间;插入数据时需要插入2次-----原表中插入一行的同时索引中也要插入一行,更重要的是索引是排序的

 管理索引的途径:

    创建索引:创建表时指定;

    创建或删除索引:修改表的命令

  Mysql 是左前缀索引

a)、帮助:

  mysql> HELP CREATE|DROP  INDEX;

b)、语法:

创建索引:
  CREATE INDEX index_name ON tbl_name (inde_col_name,...) 注:索引只要用不上了就立刻删除,否则会产生多余IO,影响性能

删除索引:
  
DROP INDEX index_name ON tbl_name

 查询索引:  

    SHOW INDEXES FROM tb_name;

EXPLAIN :分析这个查询语句过程当中是否用到索引以及如何实现数据获取

mysql> EXPLAIN SELECT * FROM students WHERE sid=1 \G;
*************************** 1. row ***************************

id: 1
select_type: SIMPLE
table: students
partitions: NULL
type: const
possible_keys: PRIMARY    #主键查询导致const类型(一对一查询结果)
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)



mysql> EXPLAIN SELECT * FROM students WHERE name='zhaoming' \G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: students partitions: NULL type: ALL possible_keys: NULL #NULL,类型为ALL 则是全表扫描然后对比WHERE 的条件一个一个过滤符合的显示出来 key: NULL key_len: NULL ref: NULL rows: 4 filtered: 25.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)

添加索引后:

mysql> EXPLAIN SELECT * FROM students WHERE name='zhaoming' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: students
partitions: NULL
type: ref
possible_keys: name      #类型ref:查询时还额外的消耗其它操作
key: name
key_len: 22
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

 e.g

  mysql> DROP INDEX name ON students;

 

三、DML: INSERT、DELETE、SELECT、UPDATE

3.1、INSERT:一次插入一行或多行数据

a)帮助信息:

  mysql> HELP INSERT;

b)语法:

INSERT [INTO] tbl_name [(col1_name,col2_name,...)] {VALUES | VALUE} (value1_list),(value2_list),(...),...

INSERT [INTO] tb_name SET coll_name='VALUE',coll_name='VALUE';

e.g  mysql> INSERT INTO students  VALUES(1,'yangguo','m'),(2,'guoxiang','F');

    mysql> INSERT INTO students  (sid,name)   VALUES (3,'zhangwuji'),(4,'zhaoming');

 

3.2、DELETE

3.2.1、语法:

DELETE  FROM tbl_name [WHERE clause] [ORDER BY 'col_name'[DESC]][LIMIT [m,]n] 
#只写到WHERE前面会清空整张表(慎)

e.g   mysql> DELETE FROM students WHERE sid=3;

 

3.3、SELECT 

 

  Query Cache :查询结果为确定性结果时才会缓存

  查询执行路径中的组件:

mysql> select now();  #显示当前系统时间
+---------------------+
| now()               |
+---------------------+
| 2020-06-20 16:33:54 |
+---------------------+
1 row in set (0.00 sec)

 

一个select语句在启动时判断流程:

  FROM Clause ---> WHERE Clause  ---->GROUP BY ----->having Clause ----->ORDER BY ----->SELECT----->LIMIT

3.3.1、语法


Syntax:
SELECT

[ALL | DISTINCT | DISTINCTROW ]
  [SQL_CACHE | SQL_NO_CACHE]
select_expr [, select_expr ...]
[FROM table_references
[PARTITION partition_list]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]

DISTINCT :数据去重
SQL_CACHE:显示指定存储查询结果与缓存之中
SQL_NO_CACHE:显示查询结构不予缓存
SELECT col1,col2,... FROM tbl_name [WHERE clause] [ ORDER BY 'col_name' [ASC|DESC] ] [LIMIT [m,]n]

                            #指定字段显示       [#指定字段并判断显示 ] [排序【升序|降序】]

DISTINCT
mysql> SELECT DISTINCT gender FROM students;
+--------+
| gender |
+--------+
| m      |
| f      |
+--------+

注:query_cache_type的值为“ON”时,查询缓存功能打开

    SELECT的结果符合缓存条件即会缓存,否则,不予缓存;

    显式指定SQL_NO_CACHE,不予缓存

  query_cache_type的值为“DEMAND”时,查询缓存功能按需进行

    显式指定SQL_CACHE的SELECT语句才会缓存,其它均不予缓存

mysql> SHOW GLOBAL VARIABLES LIKE 'query%';

 命中率=查询命中次数/查询次数

mysql> SHOW GLOBAL STATUS LIKE "Qcache%";   查询命中次数

mysql> SHOW GLOBAL STATUS LIKE "Com_se%";   查询次数  

mysql> SHOW GLOBAL STATUS LIKE "Qcache%";
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| Qcache_free_blocks      | 1       |
| Qcache_free_memory      | 1031832 |
| Qcache_hits             | 0       |
| Qcache_inserts          | 0       |
| Qcache_lowmem_prunes    | 0       |
| Qcache_not_cached       | 42      |
| Qcache_queries_in_cache | 0       |
| Qcache_total_blocks     | 1       |
+-------------------------+---------+
8 rows in set (0.00 sec)

mysql> SHOW GLOBAL STATUS LIKE "Com_se%";
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| Com_select     | 47    |
| Com_set_option | 0     |
+----------------+-------+
2 rows in set (0.00 sec)

LIMIT 

SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
 
LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。
LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,
第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数初始记录行的偏移量是
0(而不是 1):
为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。

3.3.2、字段表示法:

   *: 所有字段
  as: 字段别名    col1 AS alias1
    
    mysql> SELECT sid as stusid,name as stuname FROM students;

 

注:不允许一个经常拿来做查找条件字段出现空值

 

GROUP BY:根据指定的条件把查询结果进行“分组”以用于做“聚合”运算:
      avg(),max(), min(), count(), sum()
HAVING:对分组聚合运算后的结果指定过滤条件
ORDER BY:根据指定的字段对查询结果进行排序
    升序:ASC 默认
    降序:DESC
对查询结果中的数据请求施加“锁”:
  FOR UPDATE:写锁,排它锁
  LOCK IN SHARE MODE: 读锁,共享锁
函数聚合运算:   mysql
> SELECT avg(Age) as AAge,Gender FROM students GROUP BY gender HAVING AAge>20 ORDER BY ;

E.G

a)mysql> SELECT * FROM students WHERE sid>3;

b)mysql> SELECT * FROM students WHERE gender='m';

根据name字段排序 默认升序

c)mysql> SELECT * FROM students ORDER BY name;

d)降序排序

 mysql> SELECT * FROM students ORDER BY name DESC;

e)限制显示前2行:

 mysql> SELECT * FROM students ORDER BY name DESC LIMIT 2;

f)偏移量为1,最大数目是2行;

 mysql> SELECT * FROM students ORDER BY name DESC LIMIT 1,2;

3.3.3、WHERE clase 

    
  算数操作符:+、-、*、/、%
比较操作符:>、>=、<、 <= 、 = 、!=或<>、     
      BETWEEN .... AND ....       IN(element1,element2,...)
  基于字符串比较的      LIKE :模糊匹配         
%:任意长度的任意字符         _: 任意单个字符       RLIKE :基于正则表达式匹配 (能不用就不用---基于引擎查找)       IS NULL       IS NOT NULL   
条件逻辑操作: and 、or 、not
E.G

mysql> select * from students GROUP BY Age;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'testdb.students.sid' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by


找原因:查看mysql版本命令:select version(); 


查看sql_model参数命令: 
SELECT @@GLOBAL.sql_mode;

SELECT @@SESSION.sql_mode; 

解决方法: 
命令行输入 :
 set sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

only_full_group_by模式:在这个模式下,我们使用分组查询时,出现在select字段后面的只能是group by后面的分组字段,或使用聚合函数包裹着的字段。

E.G   

mysql> SELECT * FROM students WHERE  Age+30 >50;

mysql> SELECT * FROM students WHERE sid>=2 and sid <=4;

mysql> SELECT * FROM students WHERE sid BETWEEN 2 AND 4;

 

匹配 "z" 开头字段

  mysql> SELECT * FROM students WHERE name LIKE 'z%';

3.3.4 多表查询

    交叉连接:笛卡尔乘积

  内连接: 

   等值连接:让表之间的字段以“等值”建立连接关系(重点使用)

      mysql>SELECT * FROM students,teachers WHERE studenst.TeacherID=teachers.TID;

        mysql>SELECT s. Name AS StuName, t.Name AS TeaName  FROM students AS s ,teachers AS t  WHERE s.TeacherID=t.TID;

   自然连接关系

    不等值连接

   自连接

外连接:

   左外连接:以左边字段为准,不管右边显示的数据(无论是否为空,只需要保证有显示即可)

      FROM tb1 LEFT JOIN  tb2 ON tb1.col=tb2.col

   右外连接 : 

       FROM tb1 RIGHT JOIN  tb2 ON tb1.col=tb2.col

 mysql>SELECT s. Name , c.Class  FROM stduents AS s LEFT JOIN classes AS c ON s.Class=c.Class

子查询:在查询语句嵌套着查询语句

  基于某语句的查询结构再次进行查询,比如视图

  用在WHERE子句中的子查询:

    a.用于比较表达式中的子查询:子查询仅能返回单个值  

mysql> SELECT name,Age FROM testdb.students WHERE Age>(SELECT avg(Age) FROM testdb.students);

    b.用于IN中的子查询:子查询应该单键查询并返回一个或多个值构成列表

mysql> SELECT name,Age FROM students WHERE Age IN(SELECT Age FROM teachers);

    c.用于EXISTS

联合查询:UNION  

mysql>SELECT name,Age FROM students UNION SELECT Name,Age FROM teachers;

 

3.4、UPDATE

语法

UPDATE tbl_name SET col1_name=val1, col2_name=val2,... [WHERE clause] [ORDER BY 'col_name'[DESC]][LIMIT [m,]n]

e.g   mysql> UPDATE students SET gender='f' WHERE sid=4;

注:一定要有限制条件,否则将修改所有行的指定字段,限制条件:WHERE和LIMIT

注:5.7版本已经不再使用password来作为密码的字段了  而改成了authentication_string

mysql> SELECT User,Host,authentication_string FROM mysql.user;
mysql> update user set authentication_string=password('123') where user='root';
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

 

 

练习:导入hellodb.sql生成数据库

 

(1) 在students表中,查询年龄大于25岁,且为男性的同学的名字和年龄;

 

  MariaDB [hellodb]> select Name,Age from students where Age>25 and Gender='M';

 

(2) 以ClassID为分组依据,显示每组的平均年龄;

 

  MariaDB [hellodb]> select ClassID,avg(age) as avg_age from students group by ClassID;

 

(3) 显示第2题中平均年龄大于30的分组及平均年龄;

 

  MariaDB [hellodb]> select ClassID,avg(age) as avg_age from students group by ClassID having avg_age>30;

 

(4) 显示以L开头的名字的同学的信息;

 

  MariaDB [hellodb]> select * from students where Name like 'L%';

 

  MariaDB [hellodb]> select * from students where Name rlike '^L';

 

(5) 显示TeacherID非空的同学的相关信息;

 

  MariaDB [hellodb]> select * from students where TeacherID is NOT NULL;

 

(6) 以年龄排序后,显示年龄最大的前10位同学的信息;

 

  MariaDB [hellodb]> select * from students order by Age desc limit 10;

 

(7) 查询年龄大于等于20岁,小于等于25岁的同学的信息;用三种方法;

 

  MariaDB [hellodb]> select * from students where age>=20 and age<=25;

 

  MariaDB [hellodb]> select * from students where age between 20 and 25;

 

 

 

 

 

练习:导入hellodb.sql,以下操作在students表上执行

 

1、以ClassID分组,显示每班的同学的人数;

 

  MariaDB [hellodb]> select classid,count(name) from students group by classid;

 

2、以Gender分组,显示其年龄之和;

 

  MariaDB [hellodb]> select gender,sum(age) from students group by gender;

 

3、以ClassID分组,显示其平均年龄大于25的班级;

 

  select classid from students group by classid having avg(age) > 25;

 

4、以Gender分组,显示各组中年龄大于25的学员的年龄之和;

 

  MariaDB [hellodb]> select gender,sum(age) from (select age,gender from students where age>25) as t group by gender;

 

练习:导入hellodb.sql,完成以下题目:

 

1、显示前5位同学的姓名、课程及成绩;

 

  MariaDB [hellodb]> select name,course,score from (select * from students limit 5) as t,courses,scores where t.stuid=scores.stuid and scores.courseid=courses.courseid;

 

2、显示其成绩高于80的同学的名称及课程;

 

  select name,course,score from students,(select * from scores where score > 80) as s,courses where students.stuid=s.stuid and s.courseid=courses.courseid;

 

3、求前8位同学每位同学自己两门课的平均成绩,并按降序排列;

 

  select name,a from (select * from students limit 8) as s,(select stuid,avg(score) as a from scores group by stuid) as c where s.stuid=c.stuid order by a desc;

 

4、显示每门课程课程名称及学习了这门课的同学的个数;

 

  select course,count(name) from (select name,course from students,courses,scores where students.stuid=scores.stuid and scores.courseid=courses.courseid) as a group by course;

 

  select courses.course,count(stuid) from scores left join courses on scores.courseid=courses.courseid group by scores.courseid;

 

思考:

 

1、如何显示其年龄大于平均年龄的同学的名字?

 

  MariaDB [hellodb]> select name from students where age > (select avg(age) from students);

 

2、如何显示其学习的课程为第1、2,4或第7门课的同学的名字?

 

  MariaDB [hellodb]> select name from students,(select distinct stuid from (select * from scores where courseid in (1,2,4,7)) as a) as b where b.stuid=students.stuid;

 

  select students.name from students,(select distinct stuid from scores where courseid in (1,2,4,7))as s where s.stuid=students.stuid;

 

3、如何显示其成员数最少为3个的班级  的同学中年龄大于同班同学平均年龄的同学?

 

  MariaDB [hellodb]> select student.name,student.age,student.classid,second.avg_age from (select students.name as name ,students.age as age,students.classid as classid from students left join (select count(name) as num,classid as classid from students group by classid having num>=3) as first on first.classid=students.classid) as student,(select avg(age) as avg_age,classid as classid from students group by classid) as  second where student.age>second.avg_age and student.classid=second.classid;

 

4、统计各班级中年龄大于全校同学平均年龄的同学。

 

  select name,age,classid from students where age > (select avg(age) as a from students);

 

posted @ 2019-11-23 12:45  幻落之瞳  阅读(241)  评论(0编辑  收藏  举报