数据库--mysql

一.数据库
1.数据库(database,DB)
是指长期存储在计算机内的,有组织,可共享的数据的集合,存储数据的仓库。
2.数据库管理系统软件
(1)数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称DBMS。
(2)数据库管理系统对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。用户通过DBMS访问数据库中的数据,数据库管理员也通过dbms进行数据库的维护工作。它可使多个应用程序和用户用不同的方法在同时或不同时刻去建立,修改和询问数据库。大部分DBMS提供数据定义语言DDL(Data Definition Language)和数据操作语言DML(Data Manipulation Language),供用户定义数据库的模式结构与权限约束,实现对数据的追加、删除等操作。
(3)数据库管理系统是数据库系统的核心,是管理数据库的软件。数据库管理系统就是实现把用户意义下抽象的逻辑数据处理,转换成为计算机中具体的物理数据处理的软件。有了数据库管理系统,用户就可以在抽象意义下处理数据,而不必顾及这些数据在计算机中的布局和物理位置。
(4)常见的数据库管理软件:甲骨文的oracle,IBM的db2,sql server, Access,Mysql(开源,免费,跨平台)
3.数据库系统DBS(Data Base System,简称DBS)
通常由软件、数据库和数据管理员组成。其软件主要包括操作系统、各种宿主语言、实用程序以及数据库管理系统。数据库由数据库管理系统统一管理,数据的插入、修改和检索均要通过数据库管理系统进行。数据管理员负责创建、监控和维护整个数据库,使数据能被任何有权使用的人有效使用。
二.mysql数据库管理软件
1.sql及其规范
(1)sql:是Structured Query Language(结构化查询语言)的缩写。SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言。
<1>在数据库系统中,SQL语句不区分大小写(建议用大写) 。但字符串常量区分大小写。建议命令大写,表名库名小写;
<2>SQL语句可单行或多行书写,以“;”结尾。关键词不能跨多行或简写。
<3>用空格和缩进来提高语句的可读性。子句通常位于独立行,便于编辑,提高可读性。
<4>注释:单行注释:--   多行注释:/*......*/
<5>sql语句可以折行操作
<6>sql语句包含:DDL定义语言,DML操作语言和DCL控制语言
2.数据库操作(DDL)
(1)创建数据库(在磁盘上创建一个对应的文件夹)
语法:create database 数据库名字;
语句:

create database db_name;

(2)查看数据库
<1>查看所有数据库

show databases;

<2>查看数据库的创建方式

show create database db_name; 

+----------+------------------------------------------------------------------+
| Database | Create Database                                                  |
+----------+------------------------------------------------------------------+
| boss_ui  | CREATE DATABASE `db_name` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+------------------------------------------------------------------+
1 row in set
(3)修改数据库编码
语法:alter database 库名 character set utf8;
(4)删除数据库
语法:drop database 库名;  
(5)切换数据库
语法:use 库名;   
注意:进入到某个数据库后没办法再退回之前状态,但可以通过use进行切换查看当前使用的数据库 select database();
3.mysql数据类型,MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。
(1)数值类型
<1>TINYINT(及小型),年龄,包含在0-255之间
<2>SMALLINT(小型),端口号,包含在0-65535之间
<3>MEDIUMINT(中型),中小型网站注册会员,1600万够用
<4>INT(普通型),身份证编号,42亿可以用很久
<5>BIGINT(大型),微博量,几百亿
注意:由于mysql中不存在布尔型,所以一般来说我们可以使用TINYINT(1)来创建字段,用0表示false,1表示true
(2)日期/时间类型分别为:DATE,DATETIME,TIME,YEAR,TIMESTAMP。
<1>YEAR类型:包含1个字节,最小值1901,最大值2155
YEAR占用1个字节,包含年份,长度默认为4位,无法设置
<2>TIME类型:包含3个字节,最小值-838:59:89,最大值838:59:59
TIME占用3个字节,包含时分秒,长度0到6之间,用于设置微秒。对于TIME的范围是-838到838的原因,是印伟TIME类型不但可以保存一天的时,还可以包含时间之间的间隔。
<3>DATE类型:包含4个字节,最小值1000-01-01,最大值9999-12-31
DATE占用3个字节,包含年月日,范围和DATETIME一样。DATE长度是0,无法设置。
<4>TIMESTAMP类型:包含4个字节,最小值1970-01-01 00:00:00,最大值2038-01-19 03:14:07
TIMESTAMP占4个字节,可以包含完整的年月日时分秒,无法指定长度,不能存储微秒。范围只能存储1970年至2038年,对于想存储前后久远的时间就无法满足了。比较合适存储经常插入或者更新日期为当前系统时间的环境,比如注册时间或者登录时间的存储,由于TIMESTAMP固定为19个字符,且范围比DATETIME小,所以所占空间就小。
TIMESTAMP有几个特点:
①当更新一条数据的时候,设置此类型根据当前系统更新可以自动更新时间
②如果插入一条NULL,也会自动插入当前系统时间。
③创建字段时,系统会给一个默认值
④会根据当前时区来存储和查询时间,存储时对当前时区进行转换,查询时再转换为当前的时区。
查看当前时区:默认是东八区
语句:

SHOW VARIABLES LIKE '%time_zone%';

+------------------+--------------+
| Variable_name    | Value  |
+------------------+--------------+
| system_time_zone | CST |
| time_zone        | SYSTEM|
+------------------+--------------+
设置时区:设置为东九区,查询时间就会加一小时

SET time_zone='+9:00';

<5>DATETIME类型:包含8个字节,最小值1000-01-01 00:00:00,最大值9999-12-31 23:59:59
DATETIME占用8个字节,可以包含完整的年月日时分秒,范围很大不必考虑。当创建类型的时候,可以设置它的长度0到6位之间,如果是0,只包含年月日时分秒;如果是1-6之间,就包含M为的微秒。DATETIME类型直接保存日期时间格式,取值赋值也比较方便,并且没有时区的问题,问题是占用空间最大。
注意:对于日期格式要求相对宽松,主要有以下几种:
①2017-10-10 10:10:10
②2017/10/10 10+10+10
③20171010101010
④17/10/10 10@10@10
(3)字符串(字符)类型
(1)CHAR字节M(0-255)字节,设置M为固定长度的字符
(2)VARCHAR字节M(0-N)字符,设置M为最大长度的字符,最大的字节为65535,在UTF8下,N最大是21844
CHAR是保存定长字符串,而VARCHAR则是保存变长字符串。CHAR(5)表示必须保存5个字符,而VARCHAR(5)则表示最大保存字符为5。
创建CHAR(5)和VARCHAR(5),分别输入一个字符:“a”。通过查询语句来查看他们的长度
查看CHAR的长度
SELECT LENGTH(char1) FROM think_test;
+---------------+
| LENGTH(char1) |
+---------------+
|             1 |
+---------------+
1 row in set
查看varchar的长度
SELECT LENGTH(varchar1) FROM think_test;
+------------------+
| LENGTH(varchar1) |
+------------------+
|                1 |
+------------------+
1 row in set
这里的char和varchar的长度俩个结果都为1,单位是字节,也就是说"a"字符插入到CHAR和VARCHAR中所占的空间为1个字节,而实际上CHAR占了5个字节,VARCHAR为1+1=2个字节
虽然在SELECT语句自动删除了空白,但CHAR类型内部还是存储了5个字符。可以通过SQL_MODE设置为PAD_CHAR_TO_FULL_LENGTH来查看完整的长度。
SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected
设置完整的长度后查看CHAR的长度
SELECT LENGTH(char1) FROM think_test;
+---------------+
| LENGTH(char1) |
+---------------+
|             5 |
+---------------+
1 row in set
如果是UTF8编码下,长度为5的CHAR类型,最多插入5个字符,最多可以存储15字节,也就是5个汉子的内容。因为一个汉子占3个字节。
由于CHAR类型是定长,MYSQL会根据定义的长度进行分配空间,在处理速度上比VARCHAR快的多,所以适合存储如手机,身份证这种定长的字符,否则就会造成浪费。、
那么CHAR类型最大可以插入255个字符,最多可以存储765个字节。
对于VARCHAR变长类型,适合存储不定长度的字符串。不管设置了多长的字符,它会按需求分配字节存储空间,不会浪费,当然,在插入0-255字节时,会占用额外1个字节用于计算长度,大于255的则需要2个字节,那么其实真正有效存储的字节数为65533。而对于UTF8编码下,一个字符最大占用3个字节,那么其实VARCHAR(M)中的M最大21844个字符。
注意:虽然VARCHAR理论上最大长度是21844字符,当这个表还包含其他字段时,还要减去其他字段所占的字符数。
在变长VARCHAR(5)和VARCHAR(1000)中,保存童颜的一条数据"a",所占用的空间是一样的,但问题是,长度设置越大,在分配内存处理的时候会消耗更多。所以,我们最好的策略是设置一个最恰当的长度。
(3)BINARY字节M(0-255)字节,存储固定长度的二进制字符串
(4)VARBINARY字节M(0-65535)字节,存储最大长度的字节,最大是65533
BINARY和VARBINARY是采用二进制存储的,没有字符集概念,意义在于防止字符集的问题导致数据丢失,存储中文会占用俩个字符,会乱码,半截会问号。因为是蚕蛹二进制存储,在比较字符和排序的时候,都是二进制进行的,所以只有需要操作二进制时才需要使用。
上面四个了解定长和变长的字符类型,这四种类型都适合短字符存储。那么还有八种适合文本内容的大数据类型:TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT,TINYBLOG,BLOB,MEDIUMTEXT,LONGTEXT。这里比较主要的就是TEXT类型和BLOB类型,一个是普通文本类型,一个是二进制存储的文本类型。
(5)TINYTEXT范围:0-255所占空间是本身长度+2
(6)TEXT范围:0-65535所占空间是本身长度+2
(7)MEDIUMTEXTf范围:0-167772150所占空间是本身长度+3
(8)LONGTEXT范围:0-4294967295所占空间是本身长度+4
一般我们把TEXT等类型理解为数据超大的VARCHAR类型,当我们输入的字符长度超过VARCHAR本身最大长度,就会自动换成MEDIUMTEXT或LONGTEXT俩种类型。
(9)TINYBLOG范围:0-255所占空间是本身长度+2
(10)BLOB范围:0-65535所占空间是本身长度+2
(11)MEDIUMTEXT范围:0-16777215所占空间是本身长度+3
(12)LONGTEXT范围:0-4294967295所占空间是本身长度+4
注意:我们把短小定长的字符存储在CHAR类型,把短小变长的字符存VARCHAR,把内容较多的文本或各种内容存TEXT以及更大的类型中,另外,CHAR和VARCHAR在创建时可以设置默认值,而TEXT没有默认值,且TEXT不需要设置长度。
TEXT一组文本类型可以保存文章文字内容,而BLOB是二进制存储,可以保存比如图片之类的信息。
TEXT的范围和存储空间,我们可以用TINYEXT做测试。它的范围是(0-255)字节,那么我们通过村满发现,可以存85个汉子,即255字节,最终占用空间还要+2,其他三种以此类推。
(13)ENUM最大支持65535个成员
(14)SET最大支持64个成员
ENUM类型成为枚举类型,创建此类型一般用于单选操作,比如性别,最大支持65535个成员。1-255占1个字节,大于255占2个字节,用于单选。
SET和ENUM相对,创建此类型一般用于多选操作,比如兴趣爱好。1-8占1个字节,9-16占2个字节,17-24占3个字节,25-32占4个字节,33-64占8个字节,用于多选。
虽然显示的字符串,但存储的是int整型
<1>CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
<2>BINARY和VARBINARY类类似于CHAR和VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。
<3>BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。
<4>有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型,有相同的最大长度和存储需求。
4.数据表操作
(1)完整性约束条件之主键约束
<1>单字段主键特点:非空且唯一
<2>多字段联合主键:
1)一张表只能有一个主键
2)主键类型不一定非是整型
(2)创建表:
<1>语法:
create table 表名(
            id 类型 primary key(非空且唯一,能够唯一区分出当前记录的字段称为主键) auto_increment(自增,主键字段必须是数字类型)
            字段名 类型[完整性约束条件],
            字段名 类型,
            ...
            字段名 类型
        );
<2>创建一个员工表xixi语句:

create table xixi(
            id int primary key auto_increment,  
            name varchar(20)
          );

(3)查看表信息
<1>查看表结构语句:desc xixi;  
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
<2>查看当前数据库中的所有的表语句:show tables;
+----------------+
| Tables_in_xixi |
+----------------+
| xixi           |
+----------------+
<3>查看当前数据库表建表语句:show create table xixi;
(4)修改表结构
<1>增加列(字段)
1)增加一个字段:
语法:alter table 表名 add [column] 列名 类型[完整性约束条件][first|after 字段名];

alter table xixi add entry_date date not null;

+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| name       | varchar(20) | YES  |     | NULL    |                |
| entry_date | date        | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
2)增加多个字段语句:

alter table xixi
            add addr varchar(20),
            add age  int first,
            add birth varchar(20) after name;

+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| age        | int(11)     | YES  |     | NULL    |                |
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| name       | varchar(20) | YES  |     | NULL    |                |
| birth      | varchar(20) | YES  |     | NULL    |                |
| entry_date | date        | NO   |     | NULL    |                |
| addr       | varchar(20) | YES  |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
<2>删除列
1)删除一列
语法:alter table 表名 DROP [column] 列名;

alter table xixi DROP resume;

+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| age        | int(11)     | YES  |     | NULL    |                |
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| name       | varchar(20) | YES  |     | NULL    |                |
| birth      | varchar(20) | YES  |     | NULL    |                |
| entry_date | date        | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
2)删除多列语句:

alter table xixi DROP birth,DROP entry_date;

+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| age   | int(11)     | YES  |     | NULL    |                |
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
<3>修改一列类型
语法:alter table tab_name modify 列名 类型 [完整性约束条件][first|after 字段名];
修改xixi表里的age列的Type改成smallint,Null不能为空,Default默认值18移动到id的后面

alter table xixi modify age smallint not null default 18 after id;

+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| age   | smallint(6) | NO   |     | 18      |                |
| name  | varchar(20) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
<4>修改列名    
语法:alter table 表名 change [column] 列名 新列名 类型 [完整性约束条件][first|after 字段名];
修改xixi表里的age改为Age,类型还是smallint放到name后面
语句:

alter table xixi change age Age smallint after name;

+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20) | YES  |     | NULL    |                |
| Age   | smallint(6) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
<5>修改表名
语法:rename table 旧表名 to 新表名;

rename table xixi to wangxixi;

+----------------+
| Tables_in_xixi |
+----------------+
| wangxixi       |
+----------------+
(5)删除表
语法:drop table 表名;
5.表纪录操作之增,删,改
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| name     | varchar(20) | NO   | UNI | NULL    |                |
| birthday | varchar(20) | YES  |     | NULL    |                |
| salary   | float(7,2)  | YES  |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
(1)增加记录
<1>增加一条记录
方式一:
语法:insert [into] 表名 (字段1,字段2,.......) values (值1,值2,.......);
语句:

insert into xixi (id,name,birthday,salary) values (1,'xixi','2000-20-20',2000);

+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2000-20-20 | 2000.00 |
+----+------+------------+---------+
方式二:
语句:

insert into xixi (name,salary) values ('wang',1000);

+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2000-20-20 | 2000.00 |
|  2 | wang | NULL       | 1000.00 |
+----+------+------------+---------+
<2>插入多条数据
方式一:

insert into xixi values
       (4,'shi','2001-20-21',3000),
       (5,'yao','2002-20-22',5000);

+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2000-20-20 | 2000.00 |
|  2 | wang | NULL       | 1000.00 |
|  4 | shi  | 2001-20-21 | 3000.00 |
|  5 | yao  | 2002-20-22 | 5000.00 |
+----+------+------------+---------+
方式二:

INSERT INTO xixi (name,salary) VALUES ('chi',6000),
    ('he',9000);

+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2000-20-20 | 2000.00 |
|  2 | wang | NULL       | 1000.00 |
|  4 | shi  | 2001-20-21 | 3000.00 |
|  5 | yao  | 2002-20-22 | 5000.00 |
|  6 | chi  | NULL       | 6000.00 |
|  7 | he   | NULL       | 9000.00 |
+----+------+------------+---------+
方式三:
语法:set插入: insert [into] 表名 set 字段名=值

insert into xixi set id=8,name="wan";

+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2000-20-20 | 2000.00 |
|  2 | wang | NULL       | 1000.00 |
|  4 | shi  | 2001-20-21 | 3000.00 |
|  5 | yao  | 2002-20-22 | 5000.00 |
|  6 | chi  | NULL       | 6000.00 |
|  7 | he   | NULL       | 9000.00 |
|  8 | wan  | NULL       |    NULL |
+----+------+------------+---------+
(2)修改数据:
语法:update 表名 set 字段=修改的值,字段2=修改的值,......[where 语句]
UPDATE语法可以用新值更新原有表行中的各列。
SET子句指示要修改哪些列和要给予哪些值。
WHERE子句指定应更新哪些行。如没有WHERE子句,则更新所有的行。

update xixi set birthday="2018-12-24" WHERE id=1;

修改id=1的birthday改为2018-12-24
+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2018-12-24 | 2000.00 |
|  2 | wang | NULL       | 1000.00 |
|  4 | shi  | 2001-20-21 | 3000.00 |
|  5 | yao  | 2002-20-22 | 5000.00 |
|  6 | chi  | NULL       | 6000.00 |
|  7 | he   | NULL       | 9000.00 |
|  8 | wan  | NULL       |    NULL |
+----+------+------------+---------+
(3)删除表纪录
语法:delete from 表名 [where ....]
如果不跟where语句则删除整张表中的数据,delete只能用来删除一行记录,delete语句只能删除表中的内容,不能删除表本身,想要删除表,用drop TRUNCATE TABLE也可以删除表中的所有数据,词语句首先摧毁表,再新建表。此种方式删除的数据不能在事务中恢复
<1>删除一条语句:删除表中名称为’chi’的记录。

delete from xixi where name='chi';

+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2018-12-24 | 2000.00 |
|  2 | wang | NULL       | 1000.00 |
|  4 | shi  | 2001-20-21 | 3000.00 |
|  5 | yao  | 2002-20-22 | 5000.00 |
|  7 | he   | NULL       | 9000.00 |
|  8 | wan  | NULL       |    NULL |
+----+------+------------+---------+
<2>删除多条语句:删除表中名称为’he’和'wan'的记录。

delete from xixi where name='he' OR name='wan';

+----+------+------------+---------+
| id | name | birthday   | salary  |
+----+------+------------+---------+
|  1 | xixi | 2018-12-24 | 2000.00 |
|  2 | wang | NULL       | 1000.00 |
|  4 | shi  | 2001-20-21 | 3000.00 |
|  5 | yao  | 2002-20-22 | 5000.00 |
+----+------+------------+---------+
<3>删除所有记录
方式一:删除方式是一条一条删
语法:delete from 表名;  --注意auto_increment没有被重置:alter table employee auto_increment=1;

DELETE FROM xixi;

方式二:是把表删掉在创建一个一样的表
truncate table 表名;

truncate table xixi;

6.表纪录操作之查(单表查询)
<1>查找表内容
1)查询表里所有内容
语法:select * from 表名     --其中from指定从哪张表筛选,*表示查找所有列

select * from ExamResult;

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  1 | xixi |   98 |     98 |        98 |
|  2 | wang |   35 |     98 |        67 |
|  3 | shi  |   59 |     59 |        62 |
|  4 | yao  |   88 |     89 |        82 |
|  5 | chi  |   88 |     98 |        67 |
|  6 | wan  |   86 |    100 |        55 |
+----+------+------+--------+-----------+
2)查询表中单独俩列:所有学生的name和对应的JS成绩
语法:select 字段1,字段2,......  from 表名   --可以指定一个列。表明确指定要查找的列

select name,JS from ExamResult;

+------+------+
| name | JS   |
+------+------+
| xixi |   98 |
| wang |   35 |
| shi  |   59 |
| yao  |   88 |
| chi  |   88 |
| wan  |   86 |
+------+------+
3)过滤表中重复数据
语法:select [distinct] 字段1,字段2,..... from 表名  --distinct用来剔除重复行。

select distinct JS from ExamResult;

+------+
| JS   |
+------+
|   98 |
|   35 |
|   59 |
|   88 |
|   86 |
+------+
<2>使用表达式查询
1)在所有学生分数上加10分特长分显示。

select name,JS+10,Django+10,OpenStack+10 from ExamResult;

+------+-------+-----------+--------------+
| name | JS+10 | Django+10 | OpenStack+10 |
+------+-------+-----------+--------------+
| xixi |   108 |       108 |          108 |
| wang |    45 |       108 |           77 |
| shi  |    69 |        69 |           72 |
| yao  |    98 |        99 |           92 |
| chi  |    98 |       108 |           77 |
| wan  |    96 |       110 |           65 |
+------+-------+-----------+--------------+
2)统计每个学生的总分显示

select name,JS+Django+OpenStack from ExamResult;

+------+---------------------+
| name | JS+Django+OpenStack |
+------+---------------------+
| xixi |                 294 |
| wang |                 200 |
| shi  |                 180 |
| yao  |                 259 |
| chi  |                 253 |
| wan  |                 241 |
+------+---------------------+
3)使用别名显示学生总分
语法:select 字段1 as 别名,字段2 as 别名 from 表名;

select name as 姓名,JS+Django+OpenStack as 总成绩 from ExamResult;

+--------+-----------+
| 姓名   | 总成绩    |
+--------+-----------+
| xixi   |       294 |
| wang   |       200 |
| shi    |       180 |
| yao    |       259 |
| chi    |       253 |
| wan    |       241 |
+--------+-----------+
<3>使用where子句,进行过滤查询
1)比较运算符:> < >= <= <> !=
查询姓名为xixi的学生成绩

select * from ExamResult where name='xixi';

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  1 | xixi |   98 |     98 |        98 |
+----+------+------+--------+-----------+
查询JS成绩大于80分的同学

select id,name,JS from ExamResult where JS>80;

+----+------+------+
| id | name | JS   |
+----+------+------+
|  1 | xixi |   98 |
|  4 | yao  |   88 |
|  5 | chi  |   88 |
|  6 | wan  |   86 |
+----+------+------+
查询总分大于250分的所有同学

select name,JS+Django+OpenStack as 总成绩 from ExamResult where JS+Django+OpenStack>250 ;

+------+-----------+
| name | 总成绩    |
+------+-----------+
| xixi |       294 |
| yao  |       259 |
| chi  |       253 |
+------+-----------+
2)between 80 and 100:值在80到100之间
查询JS分数在80-100之间的同学

select name ,JS from ExamResult where JS between 80 and 100;

+------+------+
| name | JS   |
+------+------+
| xixi |   98 |
| yao  |   88 |
| chi  |   88 |
| wan  |   86 |
+------+------+
3)in(80,90,100):值是80或90或100
查询Django分数为59,89,100的同学。

select name ,Django from ExamResult where Django in (59,89,100);

+------+--------+
| name | Django |
+------+--------+
| shi  |     59 |
| yao  |     89 |
| wan  |    100 |
+------+--------+
4)like 'xixi%':pattern可以是%或者_,如果是%则表示任意多字符,此例如唐僧,唐国强,如果是_则表示一个字符唐_,只有唐僧符合。两个_则表示两个字符:__逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not
查询所有名字xi开头的学生成绩。

select * from ExamResult where name like 'xi%';

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  1 | xixi |   98 |     98 |        98 |
+----+------+------+--------+-----------+
5)查找缺考Django的学生的姓名

select name from ExamResult where Django is null;

<4>Order by指定排序的列,排序的列即可是表中的列名,也可以是select语句后指定的别名。
语法:select *|field1,field2... from tab_name order by field [Asc|Desc]   ---Asc升序、Desc 降序,其中asc为默认值ORDER BY子句应位于SELECT语句的结尾。
1)对JS成绩排序后输出(默认从小到大)。

select name,JS from ExamResult order by JS;

+------+------+
| name | JS   |
+------+------+
| wang |   35 |
| shi  |   59 |
| wan  |   86 |
| yao  |   88 |
| chi  |   88 |
| xixi |   98 |
+------+------+
2)对总分排序按从高到低的顺序输出
语法:select name,总成绩 from 表名 order by 总成绩 desc;

select name,(ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0)) 总成绩 from ExamResult order by 总成绩 desc;

+------+-----------+
| name | 总成绩    |
+------+-----------+
| xixi |       294 |
| yao  |       259 |
| chi  |       253 |
| wan  |       241 |
| wang |       200 |
| shi  |       180 |
+------+-----------+
3)对姓w开头的学生成绩从高到底排序输出
语法:select name,总成绩 from 表名 where like 'w开头' order by 总成绩 desc;

select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))总成绩 from ExamResult where name like 'w%' order by 总成绩 desc;

+------+-----------+
| name | 总成绩    |
+------+-----------+
| wan  |       241 |
| wang |       200 |
+------+-----------+
<5>group by分组查询:按分组条件分组后每一组只会显示第一条记录
+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  1 | xixi |   98 |     98 |        98 |
|  2 | wang |   35 |     98 |        67 |
|  3 | shi  |   59 |     59 |        62 |
|  4 | yao  |   88 |     89 |        82 |
|  5 | chi  |   88 |     98 |        67 |
|  6 | wan  |   86 |    100 |        55 |
|  7 | xixi |   88 |     68 |        99 |
|  8 | xixi |   55 |     64 |        78 |
+----+------+------+--------+-----------+
1)按照字段名字筛选
按照name分类

select * from ExamResult group by name;

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  5 | chi  |   88 |     98 |        67 |
|  3 | shi  |   59 |     59 |        62 |
|  6 | wan  |   86 |    100 |        55 |
|  2 | wang |   35 |     98 |        67 |
|  1 | xixi |   98 |     98 |        98 |
|  4 | yao  |   88 |     89 |        82 |
+----+------+------+--------+-----------+
2)按照位置字段筛选by 1等于第一列
按照name分类

select * from ExamResult group by 1;

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  1 | xixi |   98 |     98 |        98 |
|  2 | wang |   35 |     98 |        67 |
|  3 | shi  |   59 |     59 |        62 |
|  4 | yao  |   88 |     89 |        82 |
|  5 | chi  |   88 |     98 |        67 |
|  6 | wan  |   86 |    100 |        55 |
|  7 | xixi |   88 |     68 |        99 |
|  8 | xixi |   55 |     64 |        78 |
+----+------+------+--------+-----------+
3)对成绩表按name类名分组后显示JS类成绩的总和

select name, sum(JS) from ExamResult group by name;

+------+---------+
| name | sum(JS) |
+------+---------+
| chi  |      88 |
| shi  |      59 |
| wan  |      86 |
| wang |      35 |
| xixi |     241 |
| yao  |      88 |
+------+---------+
4)对成绩表按name类名分组后,显示每一类名字的Django的分数总和>150的类的名字和django总分

select name, SUM(Django) from ExamResult group by name HAVING SUM(Django)>150;

+------+-------------+
| name | SUM(Django) |
+------+-------------+
| xixi |         230 |
+------+-------------+
having和where两者都可以对查询结果进行进一步的过滤,差别有:
-where语句只能用在分组之前的筛选,having可以用在分组之后的筛选;
-使用where语句的地方都可以用having进行替换
-having中可以用聚合函数,where中就不行。
<5>聚合函数: 把要求的内容查出来再包上聚合函数即可。(一般和分组查询配合使用)
1)COUNT(列名):count(*)统计所有行,count(字段)不统计null值
统计一个班级共有多少学生?先查出所有的学生,再用count包上

select count(*) from ExamResult;

+----------+
| count(*) |
+----------+
|        8 |
+----------+
统计JS成绩大于70的学生有多少个

select count(JS) from ExamResult where JS>70;

+-----------+
| count(JS) |
+-----------+
|         5 |
+-----------+
统计一个班级共有多少学生?先查出所有的学生,再用count包上

select count(name) from ExamResult where (ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))>280;

+-------------+
| count(name) |
+-------------+
|           1 |
+-------------+
2)AVG(列名):
求一个班级JS平均分?先查出所有的JS分,然后用avg包上。

select avg(ifnull(JS,0)) from ExamResult;

+-------------------+
| avg(ifnull(JS,0)) |
+-------------------+
|            74.625 |
+-------------------+
求一个班级总分平均分:null和所有的数计算都是null,所以需要用ifnull将null转换为0

select avg((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))) from ExamResult;

+----------------------------------------------------------+
| avg((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))) |
+----------------------------------------------------------+
|                                                  234.875 |
+----------------------------------------------------------+
3) Max、Min
求班级所有成绩总和的最高分(数值范围在统计中特别有用)

select Max((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))) 最高分 from ExamResult;

+-----------+
| 最高分    |
+-----------+
|       294 |
+-----------+
求班级所有成绩总和的最低分

select Min((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))) 最低分 from ExamResult;

+-----------+
| 最低分    |
+-----------+
|       180 |
+-----------+
<6>limit
显示第一条

SELECT * from ExamResult limit 1;

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  1 | xixi |   98 |     98 |        98 |
+----+------+------+--------+-----------+
显示二到四条

SELECT * from ExamResult limit 2,4;

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  3 | shi  |   59 |     59 |        62 |
|  4 | yao  |   88 |     89 |        82 |
|  5 | chi  |   88 |     98 |        67 |
|  6 | wan  |   86 |    100 |        55 |
+----+------+------+--------+-----------+
<7>使用正则表达式查询
ExamResult表里name字段xi开头的所有名字

SELECT * FROM ExamResult WHERE name REGEXP '^xi';

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  1 | xixi |   98 |     98 |        98 |
|  7 | xixi |   88 |     68 |        99 |
|  8 | xixi |   55 |     64 |        78 |
+----+------+------+--------+-----------+
ExamResult表里name字段g结尾的所有名字

SELECT * FROM ExamResult WHERE name REGEXP 'g$';

+----+------+------+--------+-----------+
| id | name | JS   | Django | OpenStack |
+----+------+------+--------+-----------+
|  2 | wang |   35 |     98 |        67 |
+----+------+------+--------+-----------+
7.外键约束
(1)每一个老师会对应多个学生,而每个学生只能对应一个老师
主表:被绑定的表
CREATE TABLE Teacher(
       id TINYINT PRIMARY KEY auto_increment,
       name VARCHAR (20),
       age INT ,
       is_marriged boolean
);
插入内容:
INSERT INTO Teacher (name,age,is_marriged) VALUES ("xixi",18,0),
                                                       ("dongdong",16,0),
                                                       ("beibei",32,0),
                                                       ("nannan",21,0),
                                                       ("baibai",25,0);
显示内容:
+----+----------+------+-------------+
| id | name     | age  | is_marriged |
+----+----------+------+-------------+
|  1 | xixi     |   18 |           0 |
|  2 | dongdong |   16 |           0 |
|  3 | beibei   |   32 |           0 |
|  4 | nannan   |   21 |           0 |
|  5 | baibai   |   25 |           0 |
+----+----------+------+-------------+
子表创建外键:
语法:FOREIGN KEY (teacher_id) REFERENCES 主表(id)
注意:teacher_id作为外键一定要和关联主键的id数据类型保持一致
CREATE TABLE Student(
       id INT PRIMARY KEY auto_increment,
       name VARCHAR (20),
       teacher_id TINYINT,
       FOREIGN KEY (teacher_id) REFERENCES Teacher(id)
)ENGINE=INNODB;
插入内容:
INSERT INTO Student(name,teacher_id) VALUES ("alvin1",2),
                                            ("alvin2",4),
                                            ("alvin3",1),
                                            ("alvin4",3),
                                            ("alvin5",1),
                                            ("alvin6",3),
                                            ("alvin7",2);
显示内容:
+----+--------+------------+
| id | name   | teacher_id |
+----+--------+------------+
|  1 | alvin1 |          2 |
|  2 | alvin2 |          4 |
|  3 | alvin3 |          1 |
|  4 | alvin4 |          3 |
|  5 | alvin5 |          1 |
|  6 | alvin6 |          3 |
|  7 | alvin7 |          2 |
+----+--------+------------+
主表从表关联后:执行删除name=dongdong
语句:DELETE FROM Teacher WHERE name="dongdong";
会报关联后不可以删除
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`xixi`.`Student`, CONSTRAINT `Student_ibfk_1` FOREIGN KEY (`teacher_id`) REFERENCES `Teacher` (`id`))
外键约束对子表的含义:如果在父表中找不到候选键,则不允许在子表上进行insert/update
外键约束对父表的含义:在父表上进行update/delete以更新或删除在子表中有一条或多条对应匹配行的候选键时,父表的行为取决于:在定义子表的外键时指定的on update/on delete子句
(2)增加外键和删除外键
<1>增加外键
语法:ALTER TABLE 从表名  ADD CONSTRAINT 外键名字 FOREIGN KEY(teacher_id) REFERENCES  主表名(id);
<2>删除外键
语法:ALTER TABLE 从表名 DROP FOREIGN KEY 外键名字;

8.INNODB支持的ON语句(四种方式)
<1>级联删除:
主表:
+----+--------+------+-------------+
| id | name   | age  | is_marriged |
+----+--------+------+-------------+
|  1 | xixi   |   18 |           0 |
|  2 | beibei |   18 |           0 |
|  4 | nannan |   21 |           0 |
|  5 | baibai |   25 |           0 |
+----+--------+------+-------------+
cascade方式在父表上update/delete记录时,同步update/delete掉子表的匹配记录
外键的级联删除:如果父表中的记录被删除,则子表中对应的记录自动被删除
语法:FOREIGN KEY (charger_id) REFERENCES 主表(id) ON DELETE CASCADE
级联子表创建外键:
CREATE TABLE Student2(
       id INT PRIMARY KEY auto_increment,
       name VARCHAR (20),
       teacher_id TINYINT,
       FOREIGN KEY (teacher_id) REFERENCES Teacher(id) ON DELETE CASCADE
)ENGINE=INNODB;
子表插入内容:
INSERT INTO Student2(name,teacher_id) VALUES ("alvin1",1),
                                            ("alvin2",4),
                                            ("alvin3",1),
                                            ("alvin4",2),
                                            ("alvin5",1),
                                            ("alvin6",2),
                                            ("alvin7",4);
当前子表数据:
+----+--------+------------+
| id | name   | teacher_id |
+----+--------+------------+
| 15 | alvin1 |          1 |
| 16 | alvin2 |          4 |
| 17 | alvin3 |          1 |
| 18 | alvin4 |          2 |
| 19 | alvin5 |          1 |
| 20 | alvin6 |          2 |
| 21 | alvin7 |          4 |
+----+--------+------------+                                    
删除主表里的name="beibei"
delete from Teacher where name="beibei";
删除后子表数据内容:
+----+--------+------------+
| id | name   | teacher_id |
+----+--------+------------+
| 15 | alvin1 |          1 |
| 16 | alvin2 |          4 |
| 17 | alvin3 |          1 |
| 19 | alvin5 |          1 |
| 21 | alvin7 |          4 |
+----+--------+------------+
<2>set null方式
在父表上update/delete记录时,将子表上匹配记录的列设为null,要注意子表的外键列不能为not null
语法:FOREIGN KEY (charger_id) REFERENCES 主表(id) ON DELETE SET NULL
级联子表创建外键:
CREATE TABLE Student3(
       id INT PRIMARY KEY auto_increment,
       name VARCHAR (20),
       teacher_id TINYINT,
       FOREIGN KEY (teacher_id) REFERENCES Teacher(id) ON DELETE SET NULL
)ENGINE=INNODB;
子表插入内容:
INSERT INTO Student3(name,teacher_id) VALUES ("alvin1",1),
                                            ("alvin2",4),
                                            ("alvin3",1),
                                            ("alvin4",2),
                                            ("alvin5",1),
                                            ("alvin6",2),
                                            ("alvin7",4);
当前子表内容
+----+--------+------------+
| id | name   | teacher_id |
+----+--------+------------+
|  1 | alvin1 |          1 |
|  2 | alvin2 |          4 |
|  3 | alvin3 |          1 |
|  4 | alvin4 |          2 |
|  5 | alvin5 |          1 |
|  6 | alvin6 |          2 |
|  7 | alvin7 |          4 |
+----+--------+------------+
删除主表里的name="beibei"
delete from Teacher where name="beibei";
删除后子表数据内容:
+----+--------+------------+
| id | name   | teacher_id |
+----+--------+------------+
|  1 | alvin1 |          1 |
|  2 | alvin2 |          4 |
|  3 | alvin3 |          1 |
|  4 | alvin4 |       NULL |
|  5 | alvin5 |          1 |
|  6 | alvin6 |       NULL |
|  7 | alvin7 |          4 |
+----+--------+------------+
<3>Restrict方式
拒绝对父表进行删除更新操作(了解)
<4>No action方式
在mysql中同Restrict,如果子表中有匹配的记录,则不允许对父表对应候选键,进行update/delete操作(了解)

9.多表查询
准备两张表
创建A表:
create table A(
       id int primary key,
       name varchar(100)
      );
给B表插入数据
insert into A values
      (1,'dongdong'),
      (2,'nannan'),
      (3,'xixi'),
      (4,'beibei');
显示A表数据:
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | nannan   |
|  3 | xixi     |
|  4 | beibei   |
+----+----------+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
创建B表:
create table B(
      id int primary key,
      name varchar(50),
      tableA_id int
      );
给B表插入数据
insert into B(id,name,tableA_id) values
        (1,'A',1),
        (2,'B',1),
        (3,'C',2),
        (4,'D',2),
        (5,'E',4);      
显示B表数据:
+----+------+-----------+
| id | name | tableA_id |
+----+------+-----------+
|  1 | A    |         1 |
|  2 | B    |         1 |
|  3 | C    |         2 |
|  4 | D    |         2 |
|  5 | E    |         4 |
+----+------+-----------+
(1)多表查询之连接查询
<1>笛卡尔积查询:俩张表中一条一条对应记录,m条记录和n条记录查询,最后得到m*n条记录,其中很多错误数据。
语法:SELECT * FROM 表1,表2;
语句:SELECT * FROM A,B;
+----+----------+----+------+-----------+
| id | name     | id | name | tableA_id |
+----+----------+----+------+-----------+
|  1 | dongdong |  1 | A    |         1 |
|  2 | nannan   |  1 | A    |         1 |
|  3 | xixi     |  1 | A    |         1 |
|  4 | beibei   |  1 | A    |         1 |
|  1 | dongdong |  2 | B    |         1 |
|  2 | nannan   |  2 | B    |         1 |
|  3 | xixi     |  2 | B    |         1 |
|  4 | beibei   |  2 | B    |         1 |
|  1 | dongdong |  3 | C    |         2 |
|  2 | nannan   |  3 | C    |         2 |
|  3 | xixi     |  3 | C    |         2 |
|  4 | beibei   |  3 | C    |         2 |
|  1 | dongdong |  4 | D    |         2 |
|  2 | nannan   |  4 | D    |         2 |
|  3 | xixi     |  4 | D    |         2 |
|  4 | beibei   |  4 | D    |         2 |
|  1 | dongdong |  5 | E    |         4 |
|  2 | nannan   |  5 | E    |         4 |
|  3 | xixi     |  5 | E    |         4 |
|  4 | beibei   |  5 | E    |         4 |
+----+----------+----+------+-----------+
<2>内连接查询:
方式一:
语法:select * from 表1 inner join 表2 on 表1.id = 表2.tableA_id;
语句:select * from A inner join B on A.id = B.tableA_id;
+----+----------+----+------+-----------+
| id | name     | id | name | tableA_id |
+----+----------+----+------+-----------+
|  1 | dongdong |  1 | A    |         1 |
|  1 | dongdong |  2 | B    |         1 |
|  2 | nannan   |  3 | C    |         2 |
|  2 | nannan   |  4 | D    |         2 |
|  4 | beibei   |  5 | E    |         4 |
+----+----------+----+------+-----------+
方式二:两张表中都有的关联数据,相当于利用条件从笛卡尔积结果中筛选出了正确的结果。
语法:select * from 表1,表2 where 表1.id = 表2.tableA_id;
语句:select * from A,B where A.id = B.tableA_id;
+----+----------+----+------+-----------+
| id | name     | id | name | tableA_id |
+----+----------+----+------+-----------+
|  1 | dongdong |  1 | A    |         1 |
|  1 | dongdong |  2 | B    |         1 |
|  2 | nannan   |  3 | C    |         2 |
|  2 | nannan   |  4 | D    |         2 |
|  4 | beibei   |  5 | E    |         4 |
+----+----------+----+------+-----------+
查询A表的id和name以及他对应B表的name
语法:select 表1.id,表1.name,表2.name from 表1,表2 where 表1.id = 表2.tableA_id;
语句:select A.id,A.name,B.name from A,B where A.id = B.tableA_id;
+----+----------+------+
| id | name     | name |
+----+----------+------+
|  1 | dongdong | A    |
|  1 | dongdong | B    |
|  2 | nannan   | C    |
|  2 | nannan   | D    |
|  4 | beibei   | E    |
+----+----------+------+
查询A表name=dongdong以及他对应B表的name
语法:select 表1.name,表2.name from 表1,表2 where 表1.id = 表2.tableA_id AND A表.name="条件";
语句:SELECT A.name,B.name FROM A,B WHERE A.id = B.tableA_id AND A.name= "dongdong";
+----------+------+
| name     | name |
+----------+------+
| dongdong | A    |
| dongdong | B    |
+----------+------+
<3>外连接:
1)左外连接:在内连接的基础上增加左边有右边没有的结果
语句:select * from A left join B on A.id = B.tableA_id;
+----+----------+------+------+-----------+
| id | name     | id   | name | tableA_id |
+----+----------+------+------+-----------+
|  1 | dongdong |    1 | A    |         1 |
|  1 | dongdong |    2 | B    |         1 |
|  2 | nannan   |    3 | C    |         2 |
|  2 | nannan   |    4 | D    |         2 |
|  4 | beibei   |    5 | E    |         4 |
|  3 | xixi     | NULL | NULL |      NULL |
+----+----------+------+------+-----------+
2)右外连接:在内连接的基础上增加右边有左边没有的结果
语句:select * from A RIGHT JOIN B on A.id = B.tableA_id;
+------+----------+----+------+-----------+
| id   | name     | id | name | tableA_id |
+------+----------+----+------+-----------+
|    1 | dongdong |  1 | A    |         1 |
|    1 | dongdong |  2 | B    |         1 |
|    2 | nannan   |  3 | C    |         2 |
|    2 | nannan   |  4 | D    |         2 |
|    4 | beibei   |  5 | E    |         4 |
+------+----------+----+------+-----------+
3)全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
mysql不支持全外连接 full JOIN
mysql可以使用UNION此种方式间接实现全外连接
语句:select * from A RIGHT JOIN B on A.id = B.tableA_id UNION select * from A LEFT JOIN B on A.id = B.tableA_id;
+------+----------+------+------+-----------+
| id   | name     | id   | name | tableA_id |
+------+----------+------+------+-----------+
|    1 | dongdong |    1 | A    |         1 |
|    1 | dongdong |    2 | B    |         1 |
|    2 | nannan   |    3 | C    |         2 |
|    2 | nannan   |    4 | D    |         2 |
|    4 | beibei   |    5 | E    |         4 |
|    3 | xixi     | NULL | NULL |      NULL |
+------+----------+------+------+-----------+
注意:union与union all的区别:union会去掉相同的纪录

9.多表查询之复合条件连接查询:
当前A表:
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | nannan   |
|  3 | xixi     |
|  4 | beibei   |
+----+----------+
当前B表:
+----+------+-----------+------+
| id | name | tableA_id | age  |
+----+------+-----------+------+
|  1 | A    |         1 |   15 |
|  2 | B    |         1 |   26 |
|  3 | C    |         2 |   27 |
|  4 | D    |         2 |   23 |
|  5 | E    |         4 |   33 |
+----+------+-----------+------+
查询B表年龄大于等于25岁的对应A表名字
语句:SELECT A.name FROM A,B where A.id = B.tableA_id AND B.age > 25;
+----------+
| name     |
+----------+
| dongdong |
| nannan   |
| beibei   |
+----------+

10.多表查询之子查询:
子查询是将一个查询语句嵌套在另一个查询语句中。
内层查询语句的查询结果,可以为外层查询语句提供查询条件。
子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
当前A表:
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | nannan   |
|  3 | xixi     |
|  4 | beibei   |
+----+----------+
当前B表:
+----+------+-----------+------+
| id | name | tableA_id | age  |
+----+------+-----------+------+
|  1 | A    |         1 |   15 |
|  2 | B    |         1 |   26 |
|  3 | C    |         2 |   27 |
|  4 | D    |         2 |   23 |
|  5 | E    |         4 |   33 |
+----+------+-----------+------+
<1>带IN关键字的子查询
查询A表的名字name,但必须包含在B表对应的tableA_id
语句:select * from A where id IN (select tableA_id from B);
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | nannan   |
|  4 | beibei   |
+----+----------+
<2>带比较运算符的子查询,包含比较运算符:= 、 !=、> 、<的子查询
查询A表的名字name,但必须包含在B表对应的tableA_id且age年龄大于等于27
语句:select * from A where id IN (select tableA_id from B where age>=27);
<3>带EXISTS关键字的子查询
EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。
而是返回一个真假值。Ture或False
当返回Ture时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询

三.mysql索引
1.索引简介
(1)索引在mysql中也叫做"键",是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能影响愈发重要。
(2)索引特点:创建与维护索引会消耗很多时间与磁盘空间,但查询速度大大提高。
2.索引语法
create table 表名(
       字段1 数据类型 [完整性约束条件...],
       字段2 数据类型 [完整性约束条件...],
       [UNIQUE(唯一索引) | FULITEXT(全局索引) | SPATIAL(空间索引)] INDEX(创建普通索引) | KEY(创建普通索引) [索引名] (字段名[长度]) (ASC | DESC)
      );
3.创建索引:
(1)创建普通索引
通过INDEX给name创建普通索引,索引名index_name
语句:
create table emp(
       id INT,
       name varchar(20),
       INDEX index_name (name)
      );
索引结果:KEY `index_name` (`name`)
(2)创建唯一索引(字段不能重复)
通过UNIQUE(唯一索引) INDEX给name创建普通索引,索引名index_name
语句:
    create table emp1(
       id INT,
       name varchar(20),
       UNIQUE INDEX index_name (name)
      );  
索引结果:UNIQUE KEY `index_name` (`name`)
(3)创建全文索引:
(4)创建多列索引:
4.添加索引:
语法:CREATE [UNIQUE(唯一索引) | FULITEXT(全局索引) | SPATIAL(空间索引)] INDEX(创建普通索引) [索引名] ON 表名 (字段名[长度]) (ASC | DESC);
5.删除索引
语法:DROP INDEX 索引名 on 表名

四.mysql事务
1.事务:指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。
+------+--------+---------+
| id   | name   | balance |
+------+--------+---------+
|    1 | xixi   |   10000 |
|    2 | beibei |   10000 |
+------+--------+---------+
2.数据库开启事务命令     
(1)开启事务
语法:start transaction;
给xixi减去5000修改语句:UPDATE account set balance=balance-5000 WHERE name="xixi";
当前查看:
+------+--------+---------+
| id   | name   | balance |
+------+--------+---------+
|    1 | xixi   |    5000 |
|    2 | beibei |   10000 |
+------+--------+---------+
(2)回滚事务(即撤销指定的sql语句[只能回退insert delete update语句],回滚到上一次commit的位置)
语法:Rollback;
执行回滚事务后查询:
+------+--------+---------+
| id   | name   | balance |
+------+--------+---------+
|    1 | xixi   |   10000 |
|    2 | beibei |   10000 |
+------+--------+---------+
(3)提交事务,提交未存储的事务
语法:Commit;
给xixi减去5000修改语句:UPDATE account set balance=balance-5000 WHERE name="xixi";
给beibei加5000修改语句:UPDATE account set balance=balance+5000 WHERE name="beibei";
提交事务语句:Commit;
查看:
+------+--------+---------+
| id   | name   | balance |
+------+--------+---------+
|    1 | xixi   |    5000 |
|    2 | beibei |   15000 |
+------+--------+---------+
(4)保留点,事务处理中设置的临时占位符 你可以对它发布回退(与整个事务回退不同)
语法:savepoint 名字;
当前test表:
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | xixi     |
|  3 | nannan   |
+----+----------+
开启事务:start transaction;
插入一条数据:insert into test (name)values('beibei');
查看当前test表:
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | xixi     |
|  3 | nannan   |
|  4 | beibei   |
+----+----------+
设置保留点:
语句:savepoint insert1;
再插入一条数据:insert into test (name)values('yeye');
再设置保留点:
语句:savepoint insert2;
当前表结构:
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | xixi     |
|  3 | nannan   |
|  4 | beibei   |
|  5 | yeye     |
+----+----------+
删除三条语句:
delete from test where id=1;
delete from test where id=3;
delete from test where id=4;
当前表结构:
+----+------+
| id | name |
+----+------+
|  2 | xixi |
|  5 | yeye |
+----+------+
返回insert1节点语句:rollback to insert1;
查看当前表结构:
+----+----------+
| id | name     |
+----+----------+
|  1 | dongdong |
|  2 | xixi     |
|  3 | nannan   |
|  4 | beibei   |
+----+----------+

猜你喜欢

转载自www.cnblogs.com/xixi18/p/10115202.html