日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)
1.mysql数据库的登录的服务:
1.用户登录:mysql -u 用户名 -p 密码
可选参数:(默认连接本地服务器,可以省略下面两个参数)
-h hostNameIP地址
-P port端口号
2.格式:mysql -u账户 -p密码 -h数据库服务器安装的主机 -P数据库端口
mysql -uroot -padmin -h127.0.0.1 -P3306
若连接的数据库服务器在本机上,并且端口是3306。
则可以简写: mysql -uroot -padmin
3.启动/停止MySQL服务:
2.SQL语句:
1.SQL语句的分类:(关键字不区分大小写)
1.DDL、DCL、DML、DQL:
1.DDL:数据定义语句,用来定义数据库对象:数据库,表,列等。关键字:create,alter,drop等
2.DCL:数据控制语句,用来定义数据库的访问权限和安全级别,及创建用户。
3.DML:数据操作语句,用来对数据库中表的记录进行更新。关键字:insert,delete,update等
4.DQL:数据查询语句,用来查询数据库中表的记录。关键字:select,from,where等
2.SQL包含6个部分:
1.数据查询语言(DQL):
其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。
保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。
这些DQL保留字常与其他类型的SQL语句一起使用。
2.数据操作语言(DML):
其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。
3.事务处理语言(TPL):
它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。
4.数据控制语言(DCL):
它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。
某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
5.数据定义语言(DDL):
其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);
为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。
6.指针控制语言(CCL):
它的语句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用于对一个或多个表单独行的操作。
3.书写规则:
1.在数据库中,SQL语句大小写不敏感,SELECT/select/SeLeCt
2.SQL语句可单行或多行书写
3.在SQL语句中,关键字不能跨多行或缩写
4.为了提高可读性,一般关键字大写,其他小写.
5.空格和缩进使程序易读
2.SQL对数据库进行操作:
1.创建数据库:
1.create database 数据库名;
2.create database 数据库名 character set 字符集;
3.create database 数据库名 character set 字符集 collate 字符集的校对规则;
4.例子:create database test character set utf8 collate utf8_general_ci;
5.一种拷贝 表结构 和 表数据的语句:(不会拷贝 表的索引)
CREATE TABLE emp_copy AS SELECT * FROM emp
CREATE TABLE emp_copy AS SELECT * FROM emp WHERE 1=2
6.一种拷贝 表结构 和 表数据的语句:(不会拷贝外键)
CREATE TABLE emp_bak LIKE emp
2.查看数据库:
1.查看所有数据库:show databases;
2.查看 “用于创建数据库的”SQL语句:show create database 数据库名;
3.修改数据库:
1.修改数据库的字符集/字符集的校对规则:
alter database 数据库名 character set 字符集;
alter database 数据库名 character set 字符集 collate 字符集的校对规则;
2.例子:alter database test character set utf8 collate utf8_general_ci;
4.删除数据库:
1.drop database 数据库名;
5.切换/使用 数据库:
1.use 数据库名;
6.查看正在使用的数据库:
1.select database();
3.SQL对表进行操作:
注意:and、or、not 的优先级 就是 and --> or --> not
1.创建表:
1.creaet table 表名(字段名称 字段类型(长度) 约束,
字段名称 字段类型(长度) 约束, ......);
例子:
creaet table test(id int primary key auto_increment,
userName varchar(20) unique,
passWord varchar(20) not null);
注意:
最后一行没有逗号;
若在建表中使用到了数据库的关键字,比如新建一张订单表order,但是order是数据库中的关键字用来排序使用的;
若非要使用order这个单词,此时可以使用反引号 括起来:`order`
2.查看表:
1.查看当前使用的数据库中所有的表:show tables;
2.查看该表的结构:desc 表名;
3.删除表:
drop table 表名;
4.修改表:
1.添加列(字段):
alter table 表名 add 字段名称 字段类型(长度);
alter table 表名 add 字段名称 字段类型(长度) 约束;
2.修改列(字段)的类型、长度、约束:
alter table 表名 modify 列名 类型(长度);
alter table 表名 modify 列名 类型(长度) 约束;
3.删除列(字段):
alter table 表名 drop 列名/字段名
4.修改列名(字段名):
alter table 表名 change 旧列名 新列名 旧列名的类型(长度);
alter table 表名 change 旧列名 新列名 旧列名的类型(长度) 约束;
5.修改表名:
rename table 旧表名 to 新表名;
6.修改表的字符集:
alter table 表名 character set 字符集;
4.MySQL常用字段类型:
1.Java中的字段类型 MySQL中的字段类型
byte/short tinyint/smallint
int/Integer INT/INTEGER
long/Long BIGINT
---------------------------------------------------------------------------------------------
float/Float FLOAT
double/Double DOUBLE
BigDecimal DECIMAL
FLOAT[(s,p)]、DOUBLE[(s,p)]:小数类型,可存放 实型、整型、精度(p)、范围(s);
double(5,2):整数和小数一共占5位,其中小数占2位,最大值 999.99,最小 -999.99;但都不够精准;
DECIMAL:定点数据类型,高精度类型,金额货币优先选择;
---------------------------------------------------------------------------------------------
boolean bit
char/String char/varchar
BIT:我们一般存储0或1,存储是Java中的boolean/Boolean类型的值。
char(size):定长字符,0 - 255字节,size指N个字符数,若插入字符数超过设定长度,会被截取并警告。
varchar(size):变长字符,0 - 255字节,从MySQL5开始支持65535个字节,若插入字符数超过设定长度,会被截取并警告。
varchar 相当于 Java中字符串(String / StringBuilder / StringBuffer)
一般存储大量的字符串,比如文章的纯文本,可以选用TEXT系列类型。
注意:在MySQL中,char字符 使用 '单引号' 引起来。
---------------------------------------------------------------------------------------------
Date date/time/datetime/timestamp
日期和时间类型为DATETIME(日期+时间)、DATE(日期)、TIMESTAMP(日期+时间)、TIME(时间)、YEAR,相当于Java中Date / Calender。
注意:在MySQL中,日期时间值使用 '单引号' 引起来。
---------------------------------------------------------------------------------------------
File BLOB/TEXT
BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB:存放图形、声音和影像,二进制对象,0-4GB。
但是,在开发中,我们一般把 二进制文件的路径 存储在 数据库中。
---------------------------------------------------------------------------------------------
2.MySQL中的字段类型中的 char(长度) 和 varchar(长度) 的区别:
1.char(长度):
1.固定长度的字符 或 固定长度的字符串
2.存储的数据不满固定长度的话,则额外空格补齐,大于固定长度则报错无法插入
2.varchar(长度):
1.可变长度的字符串
2.存储的数据不满固定长度的话,也不会额外空格补齐,不会有任何额外操作,大于固定长度则报错无法插入
3. MySQL中的字段类型中的 date/time/datetime/timestamp:
1.date:只有日期;
date的用途:可用于 记录生日日期
2.time:只有时间
3.datetime:既有日期又有时间,如果不往这个字段存值的话,则MySQL会默认使用null值存入到这个字段中
4.timestamp:既有日期又有时间,如果不往这个字段存值的话,则MySQL会默认使用当前的系统时间存入到这个字段中
timestamp的用途:可用于 记录用户注册时间
4.MySQL中的字段类型中的 BLOB/TEXT
1.一般不会直接把文件数据存到数据库中,而是一般都是把上传的文件保存到服务器本地,
然后可以使用varchar 记录该文件的路径
5.MySQL 以一个可选的显示宽度指示器的形式对 SQL 标准进行扩展,这样当从数据库检索一个值时,可以把这个值加长到指定的长度。
例如,指定一个字段的类型为 INT(6),就可以保证所包含数字少于 6 个的值从数据库中检索出来时能够自动地用空格填充。
需要注意的是,使用一个宽度指示器不会影响字段的大小和它可以存储的值的范围。一般不用指定位宽。
age int(2):并不是代表age最多存储99,查询age值的时候 使用两个0来占位;
5.约束:
1.约束的作用:保证数据的完整性;
2.单表约束
1.主键约束:使用 primary key 修饰,如id;
主键约束 并且默认自带 唯一约束 和 非空约束的;
2.唯一约束:使用 unique 修饰
3.非空约束:使用 not null 修饰
3.多表约束:外键约束,用于多表之间保证数据的完整性;
4.删除约束(索引):alter table 表名 drop index 字段名
5.表的约束(针对于某一列):
1.非空约束:NOT NULL,不允许某列的内容为空。
2.设置列的默认值:DEFAULT。
3.唯一约束:UNIQUE,在该表中,该列的内容必须唯一。
4.主键约束:PRIMARY KEY, 非空且唯一。
5.主键自增长:AUTO_INCREMENT,从1开始,步长为1。
6.外键约束:FOREIGN KEY,A表中的外键列的值必须参照于B表中的某一列(B表主键)。
6.主键设计,唯一标识某一行数据的:
1.单字段主键:单列作为主键,建议使用。
复合主键:使用多列充当主键,不建议。
2.主键分为两种:
1.自然主键:使用有业务含义的列作为主键(不推荐使用),比如身份证号码;
2.代理主键:使用没有业务含义的列作为主键(推荐使用);
6.SQL对数据库表中的数据进行操作:
1.添加/插入 表数据:
1.insert / insert into 表名 (列名1, 列名2, ......) values (值1, 值2, ......):插入一行 全部字段 / 部分字段 的数据
2.insert / insert into 表名 values (值1, 值2, ......):插入一行 全部字段 的数据,比如有字段存入的是空值的话 必须使用null值代替
3.insert / insert into 表名 values (null, 值2, ......):因为id是从0开始自动增长的,所以可以不指定id的值;
如果不存入指定的id值的话,必须改为使用null值代替;
3.注意:
1.表名 和 后面的括号 之间、values 和 后面的括号 之间 都需要空格隔开,可有空格也可没有空格隔开,但推荐有空格隔开;
原因:当批处理中values 和 后面的括号 之间 如果没有使用空格隔开的话,那么性能会慢几倍,
所以values 和 后面的括号 之间需要空格隔开,满足格式要求;
2.插入的值的类型和顺序 都要和 列名(字段名) 的类型和顺序 要一致
3.插入的值的最大长度不能超过列名(字段名) 设置的长度
4.插入的值是字符串/日期时间,那么使用 单引号/双引号 引起来
4.一般语法:INSERT INTO table_name [(column [, column...])] VALUES (value [, value...]);
5.一般来说,一条INSERT只能插入一条数据,因为MYSQL没有batch操作,所以,MYSQL也支持在一条INSERT中插入多条数据:
INSERT INTO table [(column [, column...])] VALUES (value [, value...]),(value [, value...]),...
当然,一条SQL的长度是有限的,可以通过调整max_allowed_packet参数;
2.添加/插入 中文数据时,出现乱码的原因:
1.原因一:当前使用的字符集不支持中文;
解决方法:必须设置数据库/表的字符集为 character set utf8
2.原因二:使用的是window的(黑窗口)命令提示符窗口中 进行SQL语句操作中文数据时,出现中文乱码并且无法把中文乱码
添加/插入到数据库 ;
window下安装mysql服务器时,设置了使用的是utf-8字符集,那么MySQL数据库服务器中的客户端和服务器
都是默认使用utf-8字符集,而window平台使用的字符集是gbk,所以在window的(黑窗口)命令提示符窗口中
操作中文数据也是gbk编码,因此把该gbk编码的中文数据传给MySQL数据库服务器中的客户端时,
使用的默认utf-8编码无法对 gbk编码的中文数据 进行正常解码识别,因此导致最终的乱码并且无法把该乱码数据
存入到数据库中;
解决方法:1.通过 show variables like '%character%'; 语句可以查看得知到 数据库服务器中的 客户端和服务器 使用的
字符集编码的相关参数;
2.到MySQL安装目录下的my.ini文件中,把 数据库服务器中的 客户端 使用的 字符集编码 修改为 gbk编码;
3.重启MySQL服务:可以打开系统服务进行重启MySQL服务
3.修改表数据:
1.update 表名 set 字段名1 = 字段值, 字段名2 = 字段值:把该列上的 所有每行数据 都修改为新的值
2.update 表名 set 字段名 = 字段值 where 条件语句:按条件 只修改 该列上的某行数据 为新的值
3.注意:
1.修改的值的类型 要和 列名(字段名) 的类型 要一致
2.修改的值的最大长度不能超过列名(字段名) 设置的长度
3.修改的值是字符串/日期时间,那么使用 单引号/双引号 引起来
4.语法:UPDATE table_name SET columnName = value [, column = value] … [WHERE condition];
UPDATE语句也可以使用表连接,子查询等多种方式执行;
5.注意事项:
1.可以多表更新:(sqlserver不允许多表更新)
1.UPDATE table1, table2 SET columnName = value [, column = value] … [WHERE condition]
2.UPDATE table1, (select ... from ...) 别名 SET columnName = value [, column = value] … [WHERE condition]
“select ... from ...”可以作为临时表,使用上别名
2.(mysql是不允许)update更新的表,不能用于 set子句 或 where子句的 子查询中,
即子查询中用到的表 不能和 update更新的表 是一样;
4.删除表数据:
1.delete from 表名 where 条件语句:删除表中某行数据
2.delete from 表名:删除表中所有数据
3.delete 和 truncate 的区别:
1.delete 和 truncate 都为删除表中数据
2.delete from 表名:属于DML(数据操作语句),逐条记录删除,事务可以作用在DML(数据操作语句)上,
意思即为可通过 roolback; 命令语句 回滚之前的删除操作,恢复被删除的数据;
3.truncate table 表名:属于DDL(数据定义语句),会先把表删除了,然后重新创建一个结构一样的空的表,
事务无法作用在DDL(数据操作语句)上,意思即为无法通过 roolback; 命令语句 进行回滚
之前的删除操作,无法恢复被删除的数据;
4.开启事务/回滚事务:
1.指的是逻辑上的一组操作,组成这组操作的各个逻辑单元,要么全都成功,要么全都失败。
回滚(Rollback)指的是程序或数据处理错误,将程序或数据恢复到上一次正确状态的行为。
2.开启事物:START TRANSACTION / BEGIN TRANSACTION
3.提交事务:COMMIT
4.回滚事物:ROLLBACK
4.语法:DELETE FROM table_name [WHERE condition];
在delete语句中,where子句是可选的部分,如果使用了where子句,则删除的数据是符合where条件的所有记录;
如果省略了where子句,则全表的数据都会被删除,delete语句的where条件也同样支持子查询,但是一定注意,
删除语句中的where条件不能是要删除的数据表中的数据;
所以,在涉及到 删除的数据 是需要通过要删除的表中的数据查询出来的时候,
那么便需要把查询结果临时保存到另一张表,再通过delete语句删除;
5.查询表数据:(like、group by ... having、group_concat、order by、ifnull、limit [offset,] row)
1.基本查询:select [distinct] *|列名 from 表名 where 条件语句
1.select * from 表名:查询所有每行数据
2.select 列名1, 列名2, ...... from 表名:查询某列上的所有每行数据
3.select distinct 列名 from 表名:查询并对某列上的所有每行数据进行去重
4.select 列名1 + 列名2 + ...... from 表名:查询并计算多列字段数据的和
select (列名1 + 列名2 + ......) / n from 表名:查询并计算多列字段数据的平均值
5.select 列名 [as] otherName from 表名:(as可以省略)查询并对列名 取 别名
2.条件查询:
1.可用于条件查询的 运算符、关键字
1.可以使用 比较运算符:>、<、=、>=、<=、<>
2.模糊查询:like '_值%'
select * from 表名 where 列名1 like '_值%':% 和 _ 都为占位符
like '_值%':该值的前面可以包含任意一个字符,该值的后面可以包含示一个或任意多个字符
like '%值%':% 表示一个或任意多个字符,该值的前后都可以包含示一个或任意多个字符
like '_值_':_ 表示任意一个字符,该值的前后都可以包含任意一个字符
例子:
like ‘李_’:名字中必须是两个字,而且是姓李的。
like ‘李%’:名字中姓李的学生,李子后可以是1个或任意个字符。
like ‘%四’:名字中以四结尾的。
like ‘%王%’:只要名称中包含这个字就可以。
3.范围查询:in、between ... and ...
select * from 表名 where 列名 in (值1, 值2, ......):该列名的值可以是该多个值中任意一个值
select * from 表名 where 列名 between 值1 and 值2:该列名的值在值1和值2范围之间任意一个值
select * from 表名 where 列名 > 值1 and 列名 < 值2:该列名的值在值1和值2范围之间任意一个值
4.条件关联:and、or、not
select * from 表名 where 列名1 = 值 and 列名2 = 值:多列字段 并列条件查询
3.排序查询:order by 字段名 asc / desc
1.单个字段 升序/降序:
order by 字段名 asc:升序,即位置从上到下的方向上,值按小到大排序
order by 字段名 desc:降序,即位置从上到下的方向上,值按大到小排序
order by 字段名:默认升序
2.多个字段 升序/降序:(如果第一个字段值相同,则按照第二个字段值进行排序)
order by 字段名1 asc, 字段名2 desc:
先按照 字段名1 进行升序排序,如果同时多个字段名1 的值相同,则按照 字段名2 进行降序排序;
例子:
查询学生信息,先按照语文成绩进行倒序排序,如果成绩相同再按照英语成绩升序排序
select * from 表名 order by chinese desc, english asc;
4.分组统计查询:聚合函数、ifnull函数、if函数、分页查询函数、分组查询group by ...... having ......
1.聚合函数:sum():求和;count()、count(distinct 字段名):统计个数;max():获取最大值;min():获取最小值;avg():求平均值;
select avg(字段名1), sum(字段名1) from 表名:查询该字段名1上的所有每行数据的 平均值 和 总和
select count(*) from 表名:统计个数
注意:
1.select、group by ... having ...、order by 后面都可以使用 聚合函数,就只有where 后面不能使用 聚合函数,
因为聚合函数本身只能得出一个结果数据,即查询的结果只有一行数据,
并且where本身是对全局数据进行条件查询的,因为是先执行from再执行where,
所以如果where后面可以使用聚合函数的话,就会对全部数据进行聚合函数查询,
最终的查询结果就只有一行数据,是无法获取多行的数据的,因此也是where 后面不能使用 聚合函数的原因;
2.在having后面可以使用聚合函数 可以代替 where后面无法使用聚合函数 的作用:
group by......having......:having不能单独使用,having必须和group by才能一起使用;
having本身是对分组数据进行条件查询的,而where本身是对全局数据进行条件查询的;
group by 字段名 having 聚合函数:
having 后面可以使用 聚合函数,因此 正好可以 替代 where后面无法使用聚合函数 的作用;
对分组数据进行进行聚合函数查询,每个分组都是有一条数据,所以最终查询结果是多条数据;
3.where 和 having 的区别:
1.共同点:两者都可用于对数据进行条件过滤筛选
2.不同点:
1.where是执行在from之后,所以where是对表中所有的数据进行全局条件过滤,得出查询结果集;
2.group by ... having ...:
1.having不能单独使用,必须和 group by 一起使用;
2.group by ... having ... 是执行在where之后,因此group by是对查询结果集进行分组的,
而having 是执行在group by之后,所以having 是对分组数据进行条件过滤筛选的;
3.having 后面要使用 聚合函数 的话,必须在 select 中写出该聚合函数 ;
3.聚合函数可以用在select、group by、having、order by 的后面,唯独不能用在where的后面;
因为聚合函数是 对查询结果集/分组数据 的基础上进行 条件查询的,
而执行where对表中所有数据进行条件过滤筛选之后,才能得出查询结果集,
所以聚合函数无法用在where的条件查询中;
4.例子:
按商品名称统计,统计每类商品花费的总金额在5000元以上的商品,
并且按照总金额升序排序
select product, sum(price) from orderitem group by product having sum(price) > 5000
order by sum(price) asc;
2.ifnull函数、if函数:
ifnull(字段名, 0) null值和任意值相加都会变为null,所以必须判断遇到null值时要变为使用0值来代替使用
1.sum( ifnull(字段名1, 0) + ifnull(字段名2, 0) ):先计算每行数据的和,然后再把每行数据之和 进行相加
2.sum( ifnull(字段名1, 0) ) + sum( ifnull(字段名2, 0) ):先计算每列数据的和,然后再把每列数据之和 进行相加
3.IFNULL(expression_1,expression_2):
如果expression_1不为NULL,则IFNULL函数返回expression_1;
如果expression_1为NULL,返回expression_2的结果
SELECT IFNULL(NULL,"11"); 结果为 11
SELECT IFNULL("00","11"); 结果为 00
if(true,a,b) 和 if(false,a,b):第一个参数如果是true,就返回a;第一个参数如果是false,就返回b,像三元表达式
把salary表中的女改成男,男改成女:update salary set sex = if( sex = '男','女','男');
3.分页查询函数:limit [offset,] row
1.limit [offset,] row:从哪行开始取多少行,意思即从offset行开始取row行
[offset,]:表示可写可不写,不写offset的话,offset默认为0,意思即初始行为0,表示第一行开始取
offset:从哪一行数据开始,初始行是从0开始
row:取多少行数据
2.select * from 表名 limit 0, 5:同下,从第一行开始,取5行数据;
select * from 表名 limit 5:同上,从第一行开始,取5行数据;
SELECT * FROM exam LIMIT 3, 1:只取第4条数据
SELECT * FROM exam LIMIT 3, 3:取出第4条到第6条的数据
4.分组查询group by ...... having ...... :
1.select sum(字段名2) from 表名 group by 字段名1 having sum(字段名2) > 值 order by sum(字段名2) asc;
2.在having后面可以使用聚合函数 可以代替 where后面无法使用聚合函数 的作用:
group by......having......:having不能单独使用,having必须和group by才能一起使用;
having本身是对分组数据进行条件查询的,而where本身是对全局数据进行条件查询的;
group by 字段名 having 聚合函数:
having 后面可以使用 聚合函数,因此 正好可以 替代 where后面无法使用聚合函数 的作用;
对分组数据进行进行聚合函数查询,每个分组都是有一条数据,所以最终查询结果是多条数据;
3.where 和 having 的区别:
1.共同点:两者都可用于对数据进行条件过滤筛选
2.不同点:
1.where是执行在from之后,所以where是对表中所有的数据进行全局条件过滤,得出查询结果集;
2.group by ... having ...:
1.having不能单独使用,必须和 group by 一起使用;
2.group by ... having ... 是执行在where之后,因此group by是对查询结果集进行分组的,
而having 是执行在group by之后,所以having 是对分组数据进行条件过滤筛选的;
3.having 后面要使用 聚合函数 的话,必须在 select 中写出该聚合函数 ;
3.聚合函数可以用在select、group by ... having ...、order by 的后面,唯独不能用在where的后面;
因为聚合函数是 对查询结果集/分组数据 的基础上进行 条件查询的,
而执行where对表中所有数据进行条件过滤筛选之后,才能得出查询结果集,
所以聚合函数无法用在where的条件查询中;
4.例子:
按商品名称统计,统计每类商品花费的总金额在5000元以上的商品,
并且按照总金额升序排序
select product, sum(price) from orderitem group by product having sum(price) > 5000
order by sum(price) asc;
5.分组查询语法:
SELECT [DISTINCT] *|分组字段1 [别名] [,分组字段2 [别名] ,…] | 聚合函数
FROM 表名称 [别名], [表名称 [别名] ,…]
[WHERE 条件(s)]
[GROUP BY 分组字段1 [,分组字段2 ,…] ]
[HAVING 条件 | [,聚合函数] ]
[ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC] | [,聚合函数ASC | DESC] ] ;
1.写法顺序:select...from...where...group by...having...order by...limit start count
2.执行顺序:from ---> where ---> group by ---> select ---> having ---> order by ---> limit start count
3.where、group by、having 、聚合函数:
1.where 后面不能使用 聚合函数
2.having 后面要使用 聚合函数 的话,必须在 select 中写出该聚合函数
1.select、group by ... having ...、order by 后面都可以使用 聚合函数,就只有where 后面不能使用 聚合函数
2.需要忽略NULL值时,需要使用ifnull函数:
ifnull(字段名, 0) null值和任意值相加都会变为null,所以必须判断遇到null值时要变为使用0值来代替使用
3.分组:group by 字段名(把只要 该字段的字段值 都为同一个值 的多行数据 都会被 分到 同一组)
select 字段名1 from table group by 字段名1
1.按某字段的值进行分组查询;
该某字段的值首先会被去重,然后按照“只要该字段为该分组的字段值的”行数据都会被分为这一组;
2.使用GROUP BY的 正确写法:
1.group by 后面进行分组的字段 出不出现在 select 后面的查询字段中 都可以;
2.select 后面出现的 单独使用的 查询字段 都必须出现在 group by 后面进行分组的字段中;
3.如果 select 后面的查询字段中 要使用 “不是group by的”分组字段的话,那么便要在select 后面,
把该“不是group by的分组字段的” select 查询字段 放到聚合函数(sum()等)中 或 group_concat()中;
原因:因为首先聚合函数只会得出一个结果数据,即一行数据,
而SELECT后面单独使用的字段是可能存在多行数据的,所以不符合要求并且毫无意义,
虽然不会报错;
4.sum() / count() / 聚合函数() / group_concat() / concat() 都可以把 “不是group by的分组字段的”
select 查询字段 作为参数;
group_concat():可以把多个“不是group by的分组字段的” select 查询字段 拼接为 一个字符串,并且每个字段值的默认分隔符是逗号;
例子:select concat(字段,字段,字段) as 别名 from 表名 where 字段=xx group by concat(字段,字段,字段);
3.使用GROUP BY的 错误写法:
select 后面出现的 单独使用的 查询字段 如果没有出现在 group by 后面进行分组的字段中 是错误的;
4.使用GROUP BY要注意的点:
1.使用GROUP BY之后,出现在SELECT后面的字段不能单独使用,SELECT中的字段 要么是出现在
select后面的聚合函数中(如:select count(name)),要么出现在GROUP BY中;
原因:因为首先聚合函数只会得出一个结果数据,即一行数据,
而SELECT后面单独使用的字段是可能存在多行数据的,所以不符合要求并且毫无意义,
虽然不会报错;
2.在GROUP BY 子句中出现的字段,可以不出现在SELECT列表中
3.例子:
1.聚合函数单独使用:SELECT COUNT(name) FROM table;
2.错误的使用,出现了单独使用的字段:SELECT name, COUNT(name) FROM table;
3.如果使用GROUP BY 进行分组的话,则SELECT子句中,
只能出现分组的字段(GROUP BY子句中出现的字段) 或 聚合函数,
其他单独使用的字段不能出现:
1.正确做法:
SELECT job, COUNT(empno), AVG(sal)
FROM emp
GROUP BY job;
2.错误的做法:(SELECT子句中单独使用了字段deptno)
SELECT deptno, job, COUNT(empno), AVG(sal)
FROM emp
GROUP BY job;
5.group_concat(字段名):可以把多个“不是group by的分组字段的” select 查询字段 拼接为 一个字符串;
1.select 字段名1 , group_concat(字段名2) from table group by 字段名1
2.select 字段名1 , group_concat(字段名1 , 字段名2 , ......) from table group by 字段名1
3.select 字段名1 , group_concat(字段名1 , “-” , 字段名2 , “-” , ......) from table group by 字段名1
使用 “-” 作为分隔符,那么使用group_concat拼接多个字段为一个字符串时,
该字符串中的每个字段之间都带有“-”,
那么便可以使用正则表达式根据“-”从该字符串中取出每个字段值;
4.group by 后面的字段 可以不需要出现在 select 和 from之间,但 select 和 from之间不能单独使用
group by 后面不存在的字段,
但可以在select 和 from之间 使用 聚合(集合)函数 或 group_concat() 带上 group by 后面不存在的字段;
7.SQL中select、from、where、group by、having、order by、limit [offset,] row 的定义顺序 和 执行顺序:
1.定义顺序:select ... from ... where ... group by ... having ... order by ... limit [offset,] row
其中select和from是必须的,其他关键词是可选的;
例子:select ... from ... where ... group by 字段1, 字段2 having 字段1=xx and 字段2 =xx order by 字段1 asc, 字段2 desc limit [offset,] row
2.执行顺序:from ... where ... group by ... having ... select ... order by ... limit [offset,] row
3.每个关键字的意义:(按照执行顺序来排列)
from:从哪个数据表中 检索数据
where:对表中所有数据 进行条件过滤,根据条件 过滤表中所有数据
group by:将where条件过滤过滤出来的数据进行分组查询
having:对group by已经分组好的数据 进行 条件过滤
select:通过where、group by、having等进行多重条件查询后 得出查询结果集,然后使用select获取出查询结果集中的某列数据
order by:按照升序/降序来对 “从结果集中取出的” 列数据 进行排序
limit [offset,] row:分页每次取出部分数据
8.开启事务/回滚事务:
1.指的是逻辑上的一组操作,组成这组操作的各个逻辑单元,要么全都成功,要么全都失败。
回滚(Rollback)指的是程序或数据处理错误,将程序或数据恢复到上一次正确状态的行为。
2.事务的作用:从事务开启之后 到 事务提交之前这一段时间里面,如果程序出现异常错误等导致程序崩溃停止的话,
即使没有手动回滚,事务开启之后的全部操作也照样不会提交到数据库中执行保存;
也可以使用手动回滚 对出现的异常错误情况 进行处理回滚事务;
3.开启事物:START TRANSACTION / BEGIN TRANSACTION
4.提交事务:COMMIT
5.回滚事物:ROLLBACK
6.delete 和 truncate 的区别:
1.delete 和 truncate 都为删除表中数据
2.delete from 表名:属于DML(数据操作语句),逐条记录删除,事务可以作用在DML(数据操作语句)上,
意思即为可通过 roolback; 命令语句 回滚之前的删除操作,恢复被删除的数据;
3.truncate table 表名:属于DDL(数据定义语句),会先把表删除了,然后重新创建一个结构一样的空的表,
事务无法作用在DDL(数据操作语句)上,意思即为无法通过 roolback; 命令语句 进行回滚
之前的删除操作,无法恢复被删除的数据;
3.数据库、存储引擎:
1.数据库对象:存储,管理和使用数据的不同结构形式,如:表、视图、存储过程、函数、触发器、事件、索引等。
2.数据库:存储数据库对象的容器。
3.数据库分两种:
1.系统数据库(系统自带的数据库):不能修改
information_schema:存储数据库对象信息,如:用户表信息,列信息,权限,字符,分区等信息。
performance_schema:存储数据库服务器性能参数信息。
mysql:存储数据库用户权限信息。
2.用户数据库(用户自定义的数据库):一般的,一个项目一个用户数据库。
4.MySQL的存储引擎:
1.MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、
锁定水平并且最终提供不同的功能和能力。
通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能。
2.MyISAM:拥有较高的插入,查询速度,但不支持事务,不支持外键。
3.InnoDB:支持事务,支持外键,支持行级锁定,性能较低。
InnoDB 存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。
但对比MyISAM,处理效率差,且会占用更多的磁盘空间以保留数据和索引。
4.数据库对象:
1.数据库对象:包括 表、索引、视图、图表、缺省值、规则、触发器、语法、函数等。
2.数据库对象名称必须以字母开头
3.有效的字符包括数字、字母和三个特殊字符(# _ $)
4.不要使用保留字作为数据库对象名称
5.同一用户下的数据库对象不能同名,即使是不同的对象类型
5.索引:
1.索引为 一个数据库对象,用来加速对表的查询,通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O ;
索引 与 表独立存放,由数据库自动维护;
2.创建索引:
自动创建索引:当在表上定义一个PRIMARY KEY时,自动创建一个对应的唯一索引;
当在表上定义一个外键时,自动创建一个普通索引;
手动创建索引:用户可以创建索引以加速查询;可以在一列或者多列上创建索引;
3.创建索引语法:CREATE INDEX 索引名 ON table (column[, column]...);
4.复合索引:多列在一起作为一个索引,就叫做复合索引;
在很多情况下,复合索引比单个索引更好(理解原理即可);
5.哪些值可以创建索引?
1.外键一般要创建索引
2.经常使用的查询条件要创建索引。如果使用like ‘%’操作,不会使用索引。
3.索引不是越多越好
4.不要在可选值很少的属性上面创建索引
5.MySQL索引的使用,并不是所有情况下都会使用索引,只有当MySQL认为索引足够能够提升查询性能时才会使用;
6.视图:
1.视图也就是虚表,实际上视图就是一个命名的查询,用于改变基表数据的显示。
2.视图的作用:
1.可以限制对数据的访问
2.可以使复杂的查询变的简单
3.提供了数据的独立性
4.提供了对相同数据的不同显示
3.语法:
在CREATE VIEW语句后加入子查询:
CREATE [OR REPLACE] VIEW view
[(alias[, alias]...)]
AS subquery
[WITH READ ONLY];
4.创建视图:
CREATE OR REPLACE VIEW 视图名emp_v_30
AS SELECT empno, ename, sal
FROM emp
WHERE deptno =30;
CREATE VIEW 视图名sal_v_10
AS SELECT employee_id ID, last_name NAME, salary*12 ANN_SALARY
FROM employees
WHERE department_id = 10;
5.使用视图:
在查询时,不需要再写完全的Select查询语句,只需要简单的写上从视图中查询的语句就可以了;
例如:SELECT * FROM 视图名sal_v_10;
默认情况下,可以直接通过对视图的DML操作去修改视图对应表中的内容(前提是视图中没有通过公式导出的列);
6.删除视图:
删掉视图不会导致数据的丢失,因为视图是基于数据库的表之上的一个查询定义.
例如:DROP VIEW 视图名view_name;
安装、卸载MySQL
MySQL的安装
1.这两个路径是可以改的,但是需要记住他的位置
MySQL Server mysql服务器的安装位置
Server data files 数据存放的位置
2.勾选standard configuration(手动配置)my服务器
3.standard Charater 默认的不支持中文 需要 选择第3个选择 手动选择 UTF-8
4.Include BIn directory Windows Path 一定要勾选 否则用不了命令行
5.modify security setting 输入mysql最高管理员 root密码
6.验证是否安装成功:打开命令行 输入 mysql -u root -p 输入密码 显示 welcom to the MySQL
存储引擎选用第一个(Multifunction DataBase):多功能存储引擎,支持多种存储引擎;
1.InnoDB:支持事务,支持外键,但是性能相对较低,开发中;
2.MyISAM:不支持事务,不支持外键,但是性能相对较高;
数据库安装常见错误
1.安装时忘了勾选 Include BIn directory Windows Path:
在登入MySQL服务器的时候不能直接输入mysql登入命令,
因为我们没有把MySQl的bin目录添加到系统的环境变量里面。
每次输入”cd F:\Program Files\MySQL\MySQL Server 5.7\bin“才能使用登入,
这样显得比较麻烦,下面就介绍怎样手动配置Path变量。
1. 打开左面右击【我的电脑】图标,在弹出的快捷菜单中选择【属性命令】。
2. 选择【高级系统设置】,弹出对话框,选择【环境变量】
3. 单击【环境变量】按钮,打开【环境变量】对话框,在系统变量列表中选择【Path】变量
4.单击【编辑】按钮,在编辑系统变量对话框中,将MySQL的bin目录添加到变量值中,用分号将其与其它路径分隔开
5.添加完成后,单击【确定】按钮,这样就完成了配置Path变量的路径,然后就可以直接输入mysql命令来登入数据库了
2.数据库安装1045错误:
提示: 1045 access denied for user 'root'@'localhost' using password yes错误
解决:
1. 开始 --> cmd --> net stop mysql (停用MySQL服务 没启动的可以省略)
2. 找到安装路径 MySQL Server 5.1下的my.ini
3. 打开 my.ini 找到 [mysqld] 然后在下面加上
这句: skip_grant_tables (意思好像是 启动MySQL服务的时候跳过权限表认证 )
4. 然后就启动数据库修改密码了
开始 --> cmd --> net start mysql (启动MySQL服务)---> mysql 回车 ( 如果成功,将出现MySQL提示符)
5. 输入use mysql; (连接权限数据库)。
6. 改密码:update user set password=password("123") where user="root";(别忘了最后加分号) 。
7. 刷新权限(必须步骤):flush privileges; 。
8. 退出 quit。
9. 将第3 步的 my.ini里的 skip_grant_tables 去掉(启动MySQL服务的时候不能让他跳过权限表认证 )
10. 重启MySQL ,再进入,使用用户名root和刚才设置的新密码123就可以登录了。
3.数据库安装2503错误:
方法一:
1、按WIN+R,在运行框中输入“gpedit.msc” 确认;
2、打开本地策略组编辑器后依次展开 :“计算机配置”-》“管理模板”-》“windows组件”-》“windows installer”,
并找到“始终以提升的权限进行安装”;
3、双击该选项,设置为“已启用”,并应用;
4、最后我们还要在【用户配置】中进行同样的操作;
5、就可以安装了。
方法二:
1、鼠标移到桌面左下角->右键(或者直接: WIN+X键),命令提示符(管理员);
2、输入:msiexec /package +‘msi文件路径’(输入的时候注意半角字符且路径不能为中文名)
方法三:
先执行 方法一,再执行方法二
注意:gpedit.msc 这个命令(针对win10 家庭版)可能找不到,需要升级系统到专业版,不然安装不成功
concat() 和 group_concat()
一、CONCAT()函数
CONCAT()函数用于将多个字符串连接成一个字符串。
使用数据表Info作为示例,其中SELECT id,name FROM info LIMIT 1;的返回结果为
+----+--------+
| id | name |
+----+--------+
| 1 | BioCyc |
+----+--------+
1、语法及使用特点:
CONCAT(str1,str2,…)
返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。可以有一个或多个参数。
2、使用示例:
SELECT CONCAT(id, ‘,’, name) AS con FROM info LIMIT 1;返回结果为
+----------+
| con |
+----------+
| 1,BioCyc |
+----------+
SELECT CONCAT(‘My’, NULL, ‘QL’);返回结果为
+--------------------------+
| CONCAT('My', NULL, 'QL') |
+--------------------------+
| NULL |
+--------------------------+
3、如何指定参数之间的分隔符
使用函数CONCAT_WS()。使用语法为:CONCAT_WS(separator,str1,str2,…)
CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的 NULL 值。但是CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。
如SELECT CONCAT_WS('_',id,name) AS con_ws FROM info LIMIT 1;返回结果为
+----------+
| con_ws |
+----------+
| 1_BioCyc |
+----------+
SELECT CONCAT_WS(',','First name',NULL,'Last Name');返回结果为
+----------------------------------------------+
| CONCAT_WS(',','First name',NULL,'Last Name') |
+----------------------------------------------+
| First name,Last Name |
+----------------------------------------------+
二、GROUP_CONCAT()函数
GROUP_CONCAT函数返回一个字符串结果,该结果由分组中的值连接组合而成。
使用表info作为示例,其中语句SELECT locus,id,journal FROM info WHERE locus IN('AB086827','AF040764');的返回结果为
+----------+----+--------------------------+
| locus | id | journal |
+----------+----+--------------------------+
| AB086827 | 1 | Unpublished |
| AB086827 | 2 | Submitted (20-JUN-2002) |
| AF040764 | 23 | Unpublished |
| AF040764 | 24 | Submitted (31-DEC-1997) |
+----------+----+--------------------------+
1、使用语法及特点:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] [,col ...]]
[SEPARATOR str_val])
在 MySQL 中,你可以得到表达式结合体的连结值。通过使用 DISTINCT 可以排除重复值。如果希望对结果中的值进行排序,可以使用 ORDER BY 子句。
SEPARATOR 是一个字符串值,它被用于插入到结果值中。缺省为一个逗号 (","),可以通过指定 SEPARATOR "" 完全地移除这个分隔符。
可以通过变量 group_concat_max_len 设置一个最大的长度。在运行时执行的句法如下: SET [SESSION | GLOBAL] group_concat_max_len = unsigned_integer;
如果最大长度被设置,结果值被剪切到这个最大长度。如果分组的字符过长,可以对系统参数进行设置:SET @@global.group_concat_max_len=40000;
2、使用示例:
语句 SELECT locus,GROUP_CONCAT(id) FROM info WHERE locus IN('AB086827','AF040764') GROUP BY locus; 的返回结果为
+----------+------------------+
| locus | GROUP_CONCAT(id) |
+----------+------------------+
| AB086827 | 1,2 |
| AF040764 | 23,24 |
+----------+------------------+
语句 SELECT locus,GROUP_CONCAT(distinct id ORDER BY id DESC SEPARATOR '_') FROM info WHERE locus IN('AB086827','AF040764') GROUP BY locus;的返回结果为
+----------+----------------------------------------------------------+
| locus | GROUP_CONCAT(distinct id ORDER BY id DESC SEPARATOR '_') |
+----------+----------------------------------------------------------+
| AB086827 | 2_1 |
| AF040764 | 24_23 |
+----------+----------------------------------------------------------+
语句SELECT locus,GROUP_CONCAT(concat_ws(', ',id,journal) ORDER BY id DESC SEPARATOR '. ') FROM info WHERE locus IN('AB086827','AF040764') GROUP BY locus;的返回结果为
+----------+--------------------------------------------------------------------------+
| locus | GROUP_CONCAT(concat_ws(', ',id,journal) ORDER BY id DESC SEPARATOR '. ') |
+----------+--------------------------------------------------------------------------+
| AB086827 | 2, Submitted (20-JUN-2002). 1, Unpublished |
| AF040764 | 24, Submitted (31-DEC-1997) . 23, Unpublished |
+----------+--------------------------------------------------------------------------+
1.允许对数据库进行指定IP的远程访问连接:
1.问题:无法对数据库进行指定IP的远程连接,只能使用localhost进行连接数据库
2.解决方法一:
1.在系统自带的 叫做mysql名称的数据库下的 user表,把host字段的值localhost 修改为 %,意思即 允许任何IP地址访问
2.重启MySQL服务
3.解决方法二:修改root用户的登录权限,允许任何IP地址访问
1.可以使用mysql -uroot -p密码进入mysql数据库的情况下:
mysql> use mysql
mysql> update user set host = '%' where user = 'root';
mysql> flush privileges
然后重新启动mysql服务就可以了
(在管理员模式下的命令提示符窗口中 先执行 net stop mysql,然后执行 net start mysql)
2.不能使用mysql -uroot -p密码进入mysql数据库的情况下:
需要先停止mysql服务,这里分两种情况,一种可以用service mysqld stop,另外一种是/etc/init.d/mysqld stop
当提示mysql已停止后进行下一步操作
在终端命令行输入:mysqld_safe --skip-grant-tables &
(其中 –skip-grant-tables 的意思是跳过授权表,通过此参数来跳过输入密码,后面跟得 & 符号是表示设置)
输入:mysql,也可以回车之后在输入命令: mysql (登录mysql系统)
进入 mysql数据库,然后通过语句修改密码:
mysql> use mysql
mysql> update user set host = '%' where user = 'root';
mysql> flush privileges
mysql> exit;
然后重新启动mysql服务就可以了
(在管理员模式下的命令提示符窗口中 先执行 net stop mysql,然后执行 net start mysql)
2.外键:
1.多表约束:外键约束,用于多表之间保证数据的完整性
2.外键:指向另外一张表的主键,外键的值一般也不能为空,外键的值应为 not null 非空约束;
外键之所以要关联主键,因为主键是唯一并且非空的,根据主键就能确定一条唯一的记录;
主表:被引入外键的表;
从表:引入外键的表;
注意:在MySQL中,存储引擎InnoDB才支持事务和外键,因此需要保证存储引擎为InnoDB;
修改表的存储引擎为InnDB:ALTER TABLE 表名 ENGINE='InnoDB';
3.添加外键约束的写法:
例子:
1.A表 通过外键关联 B表的主键:alter table A表 add foreign key(外键字段名) references B表(主键字段名)
不创建外键约束名的话,底层会自动创建一个外键约束名,也可以自定义一个任意名字的外键约束名
2.修改外键为not null 非空约束:alter table A表 modify 外键字段名 int not null
3.一对一关系、一对多关系、多对多关系:
1.一对一关系:一般会把两张表合并为一张表,需要情况下才会分拆为两张表的一对一关系;
1.第一种创建方式:唯一外键对应
两张表中 其中一张表 设置外键,关联指向另外一张表的主键,并且该外键必须设置为 unique 唯一约束
2.第二种创建方式:主键对应
不需要创建外键,两张表各自的主键 对应 对方的 主键,那么要求 双方的主键值 一一对应并且主键值相同
3.一对一关系的优点和用处:
可用于数据库的优化:分表;
在一张表中,把不常用的字段分离出来放到另外一张表中,此时这两张表就是一对一的关系;
可以达到减少正常查询时的数据负担,提高效率;
2.一对多关系:在多的一方的表中 创建外键字段 指向 一的一方的表中的 主键字段
3.多对多关系:应使用 中间表(第三张表) 来存储指向 多对多的两张表的主键字段,中间表中会创建两个字段均作为外键,
两个外键分别指向 多对多的两张表各自的主键字段;
4.多表查询之连接查询:交叉连接、外连接、内连接、自关联(自连接)、union、union all
1.多表查询,如果没有连接条件,则会产生笛卡尔积:
数学中定义:假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。
实际运行环境下,应避免使用全笛卡尔集。
2.连接条件:
在 on / where 子句中 写入连接条件。
当多个表中有重名列时,必须在列的名字前加上表名作为前缀/或使用表的别名为前缀。
等值连接是连接操作中最常见的一种,通常是在存在主外键约束条件的多表上建立的,连接条件中的两个字段通过等号建立等值关系。
使用表的别名简化了查询,提高了查询的性能。
连接 n张表,至少需要 n-1个连接条件。
2.交叉连接:查询到的结果集数据是带有笛卡尔积,因为没有使用连接条件进行关联再进行条件查询,所以才会出现笛卡尔积的结果集数据
1.select * from 表1 cross join 表2
2.select * from 表1, 表2
3.外连接:
1.左外连接:left outer join ... on ... (outer 可以省略)
1.查的是左边表的全部和两张表的交集;
查询出JOIN左边表的全部数据查询出来,JOIN右边的表不匹配的数据使用NULL来填充数据;
2.select * from 表1 left outer join 表2 on 连接条件
首先获取左边表的全部数据,以左边表为标准,获取两张表的共有(交集)的数据;
如果左边表中的 某数据没有对应的 右表数据的话,那么以NULL代替显示为 “左边表中该数据对应的” 右表数据
2.右外连接:right outer join ... on ... (outer 可以省略)
1.查的是右边表的全部和两张表的交集;
查询出JOIN右边表的全部数据查询出来,JOIN左边的表不匹配的数据使用NULL来填充数据;
2.select * from 表1 right outer join 表2 on 连接条件
首先获取右边表的全部数据,以右边表为标准,获取两张表的共有(交集)的数据;
如果右边表中的 某数据没有对应的 左表数据的话,那么以NULL代替显示为 “右边表中该数据对应的” 左表数据
4.内连接:
内连接只获取出两张表的共有(交集)的数据,也即查的是两张表的交集 ;
连接条件:表1.字段名1 = 表2.字段名2;
显式内连接 和 隐式内连接 查询出的结果都是一样的,仅是写法不一样;
1.显式内连接:使用了 inner join ... on ... (inner 可以省略)
select * from 表1 inner join 表2 on 连接条件
注意:
1.ON table1.name = table1.name 相当于 USING(name)
2.例子:
SELECT e.empno, e.ename, d.dname FROM emp e JOIN dept d ON e.deptno = d.deptno
SELECT e.empno, e.ename, d.dname FROM emp e JOIN dept d USING(deptno)
2.隐式内连接:没有使用 inner join ... on ...,而是改为使用 where
select * from 表1, 表2 where 连接条件
5.自关联(自连接):(自关联(自连接) 可以使用 内连接 / 左外连接 / 右外连接)
select parent.字段, son.字段 from table1 as parent inner join table1 as son on parent.id = son.parent_id
select parent.字段, son.字段 from table1 as parent right outer join table1 as son on parent.id = son.parent_id
select parent.字段, son.字段 from table1 as parent left outer join join table1 as son on parent.id = son.parent_id
把多张表 的数据放到同一张表中,可以使用 自关联;
下面的需求都可以用到 自关联:
1.把 省表、市表、区表 都放到同一张表中:
省数据的parent_id为NULL,而表示市数据的parent_id等于表示省数据的id,以此类推。
2.把 一级菜单、二级菜单、三级菜单 都放到同一张表中;
一级菜单 的parent_id为NULL,而二级菜单的parent_id 等于 一级菜单的id,以此类推。
3.需求:查询员工名称和其对应经理的名称
SELECT e.empno, e.ename, m.ename FROM emp e LEFT JOIN emp m ON e.mgr = m.empno;
6.UNION / UNION ALL:
1.UNION / UNION ALL:
JOIN是用于把表横向连接,UNION/UNION ALL是用于把表纵向连接(一般用于做查询的临时表)
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
2.使用注意:
1.UNION 内部的 SELECT 语句必须拥有相同数量的列。
2.列也必须拥有兼容的数据类型。
3.每条 SELECT 语句中的列的顺序必须相同。
4.UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名
5.UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL(性能高)
3.语法:
SELECT column_name(s) FROM table_name1
UNION|UNION ALL
SELECT column_name(s) FROM table_name2
4.在MYSQL 中实现FULL JOIN全连接,MYSQL中暂时不支持全连接,可以使用 “union + 左外连接 和 右外连接” 来完成 全连接的效果;
例子:查询员工的编号,名称和部门名称
SELECT empno,ename,dname FROM emp LEFT JOIN dept USING (deptno)
UNION
SELECT empno,ename,dname FROM emp RIGHT JOIN dept USING (deptno)
上面的写法 等同于 下面的写法:ON table1.name = table1.name 相当于 USING(name)
SELECT empno,ename,dname FROM emp LEFT JOIN dept ON emp.deptno= dept.deptno
UNION
SELECT empno,ename,dname FROM emp RIGHT JOIN dept ON emp.deptno= dept.deptno
5.多表查询之子查询:
1.子查询的意思:
一条sql语句的查询结果 作为 另外一条sql语句 中的查询条件,也即一个查询语句条件需要依赖另一个查询语句的结果;
子查询指的就是在一个查询之中嵌套了其他的若干查询,在使用select语句查询数据时,有时候会遇到这样的情况,
在where查询条件中的限制条件不是一个确定的值,而是一个来自于另一个查询的结果。
2.子查询的用法:
1.子查询一般出现在FROM/JOIN子句中 或 WHERE子句中,即子查询 可以作为表数据 使用在 from / join后面,
或子查询作为 条件查询数据 使用在where 后面;
2.使用子查询的注意事项:
1.子查询要用括号括起来
2.将子查询放在比较运算符的右边(增强可读性)
3.对单行子查询使用单行运算符
4.对多行子查询使用多行运算符
3.子查询的分类,根据子查询的结果分为以下情况:
1.单行单列的 子查询 结果数据:只包含一个字段的查询,返回的查询结果也只包含一行数据, 看做是一个值,使用在WHERE之后
2.多行单列的 子查询 结果数据:只包含了一个字段,返回多行查询结果数据,看做是多个值,使用在WHERE之后
3.单行多列的 / 多行多列的 子查询 结果数据:
包含多个字段的返回,返回的查询结果数据可能是单行或者多行,看做是临时表,使用在FROM/JOIN之后
4.单行单列的 子查询 结果数据:
1.子查询返回一行一列记录,看做是一个值,使用在WHERE之后;
2.使用单行记录比较运算符:=;>;>=;<;<=;<>
3.例子:
查询大于公司平均工资的员工姓名
SELECT ename,sal FROM emp WHERE sal >(SELECT AVG(sal) FROM emp)
查询出工资比MARTIN还要高的全部雇员信息
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename = 'MARTIN')
5.多行单列的 子查询 结果数据:
1.返回多行查询结果数据,看做是多个值
2.使用多行比较运算符
1.IN:与列表中的任意一个值相等 ;where 字段名 IN (子查询SQL)
2. ANY:与子查询返回的任意一个值比较
1.where 字段名 = ANY:此时和IN操作符相同
2.where 字段名 > ANY:大于子查询中最小的数据
3.where 字段名 < ANY:大于子查询中最大的数据
3.ALL:与子查询返回的每一个值比较
1.where 字段名 > ALL:大于子查询中最大的数据
2.where 字段名 < ALL:小于子查询中最小的数据
4.带 in 的 子查询:
select * from 表1 where 字段名1 in (select 查询出 多个字段值)
例子:
select * from Class where id in (select 外键class_id from Student where ......)
获取出Student表中多个 “关联Class表id的” 外键class_id,
然后范围查询 “Class表的id in 外键class_id” 获取出 多行Class表数据;
5.带 any 的 子查询:
select * from Class where id > any (select 查询出 多个字段值):大于任意一个值,即大于最小值
表示只要Class 表中的id 大于 子查询中多个值中的 任意一个值,那么便成立,便可查询出对应的数据;
也即只要Class 表中的id 大于 子查询中多个值中的 最小值,那么便成立,便可查询出对应的数据;
6.带 all 的 子查询:
select * from Class where id > all (select 查询出 多个字段值):大于全部多个值,即大于最大值
表示只要Class 表中的id 大于 子查询中全部的多个值,那么便成立,便可查询出对应的数据;
也即只要Class 表中的id 大于 子查询中多个值中的最大值,那么便成立,便可查询出对应的数据;
6.单行多列的 / 多行多列的 子查询 结果数据:
1.一般会把 单行多列的 / 多行多列的 子查询 结果数据 当成一个临时表,一般用在FROM/JOIN子句后面,
接着在临时表上继续查询或者连接查询;
注意:单行多列的 / 多行多列的 子查询 结果数据 必须要设置一个临时表名;
2.例子:查询出每个部门的编号、部门名称、部门人数、部门平均工资:
1.可以先把每一个部门的编号、部门总人数、部门平均工资先查询出来:
SELECT deptno dno,COUNT(empno) count ,AVG(sal) avg FROM emp GROUP BY dno
2.再和dept表联合查询部门名称:
SELECT dept.deptno,temp.count,temp.avg FROM dept JOIN
(SELECT deptno dno,COUNT(empno) count ,AVG(sal) avg FROM emp GROUP BY dno) temp
ON dept.deptno = temp.dno
7.带 exists 的 子查询:
1.select * from Class where exists (select 是否查询出数据)
只要子查询的sql语句查询出数据,那么exists就判断为true,那么就执行 子查询外的sql语句;
如果子查询的sql语句查询不出任何数据的话,那么exists就判断为false,那么就不会执行 子查询外的sql语句。
2.select * from Class where ...... and / or exists (select 是否查询出数据) group by ......
使用and:当exists 为true(子查询select 查询出数据) 时,才会执行 子查询外的sql语句;
使用or:不管exists 是否为true,即不管子查询select 是否查询出数据,只要or前面的条件为true,那么都会执行 子查询外的sql语句;
8.注意事项:
1.可以多表更新:(sqlserver不允许多表更新)
1.UPDATE table1, table2 SET columnName = value [, column = value] … [WHERE condition]
2.UPDATE table1, (select ... from ...) 别名 SET columnName = value [, column = value] … [WHERE condition]
“select ... from ...”可以作为临时表,使用上别名
2.(mysql是不允许)update更新的表,不能用于 set子句 或 where子句的 子查询中,
即子查询中用到的表 不能和 update更新的表 是一样;
6.事务:
1.数据库的事务并发问题:
1.存在五种问题:脏读、不可重复读、幻读、第一类丢失更新、第二类丢失更新。
为了解决上述的问题,我们提出了隔离级别的概念,不同的隔离级别可以处理的并发问题是不一样的;
使用不同的隔离级别就可以阻止自己所期望的并发问题;
2.使用锁机制来解决事务并发问题:
1.悲观锁:SELECT ....... FOR UPDATE;
2.乐观锁:使用版本控制
2.事务的 开启、提交、回滚:
1.开启事务:start transaction
2.提交事务:commit
3.回滚事务:rollback
4.MySQL的事务一旦提交之后是无法回滚的,而Oracle的事务在提交之后都还是可以回滚的,
因为Oracle提交的数据还会缓存一下后才会保存到本地;
3.事务的 特点:原子性、一致性、隔离性、持久性
1.原子性:事务的不可分割,组成事务的各个逻辑单元不可分割
2.一致性:事务执行的前后,数据完整性保持一致
3.隔离性:事务执行不应该受到其他事务的干扰
4.持久性:事务一旦结束,数据就持久化到数据库中
4.事务的隔离级别:
1.MySQL默认的隔离级别:repeatable read 避免 脏读、不可重复读,但是 虚读 有可能发生
1.修改更新、读取查询 操作都上锁了,因此在一个事务中 是无法读取到 别的事务 修改并提交之后的 新数据,
所以叫做避免了 不可重复读,即在一个事务中只能读取到当前事务中(修改/提交之后)的数据,
是无法读取到别的事务修改提交后的新数据,不同事务之间是完全隔离的;
2.即使修改更新、读取查询 操作都上锁了,不同事务之间依然可以并发修改同一数据,当一个事务修改了同一数据并提交之后,
另一事务也接着也修改 同一数据并提交,最终该同一数据照样可以被修改为最新的更新值。
2.Oracle默认的隔离级别:read committed 避免 脏读,但是 不可重复读、虚读是有可能发生
1.修改更新操作 上锁了,但是读取查询操作没有上锁,因此在一个事务中 是可以读取到 别的事务 修改并提交之后的 新数据,
所以叫做 没有避免 不可重复读,即在一个事务中可以读取到别的事务中修改/提交之后 的数据,
因为即使是不同事务之间的读取查询操作是没有上锁的,所以性能比较高;
2.即使修改更新上锁了,读取查询操作没有上锁,不同事务之间依然可以并发修改同一数据,
当一个事务修改了同一数据并提交之后,另一事务也接着也修改 同一数据并提交,
最终该同一数据照样可以被修改为最新的更新值。
3.最高的隔离级别serializable(串行化):
串行化:多个事务排成队列,排队执行,每个事务逐一执行,一个事务执行结束了,才轮到下一个事务开始执行;
serializable 不允许并发,每个事务都只能按顺序逐一执行,一个事务结束了才轮到下一个事务执行,因此效率也是最低;
比如说:有两个客户端 同时对同一张表 进行操作时 都开启了事务,那么客户端A 正在操作(插入/修改)该表中的数据时,
而客户端B 执行select查询时 会一直阻塞等待 客户端A 开启的事务 提交数据之后,客户端B 才能获取到查询数据;
也即说明事务不允许出现并发,客户端B 需要等待客户端A 的事务执行完成以后,才会执行客户端B 的事务,
当 客户端A的事务结束(提交或者回滚),那么客户端B 马上就会出现查询数据结果。
4.隔离级别的 安全性从高到低,但是效率从低到高:serializable ----> repeatable read ----> read committed ----> read uncommitted
1.read uncommitted:脏读、不可重复读、虚读 都有可能发生
2.read committed:避免 脏读,但是 不可重复读、虚读是有可能发生
3.repeatable read:避免 脏读、不可重复读,但是 虚读 有可能发生。
4.serializable:避免 脏读、不可重复读、虚读。
5.查看当前的隔离级别:select @@tx_isolation
6.设置事务的隔离级别:set session transaction isolation level 隔离级别的英文名
set session transaction isolation level serializable/ repeatable read/read committed/read uncommitted
7.脏读:一个事务 读到 别的事务 没有提交的数据;
不同之间的事务应该是完全隔离的,所以一个事务 不应该 读到 别的事务 没有提交的数据
8.不可重复读:一个事务 读到 别的事务 已经提交了的update的数据;
不同之间的事务应该是完全隔离的,所以一个事务 不应该 读到 别的事务 已经提交了的update的数据;
在同一个事务中,多次的查询结果都应是一致的;
9.虚读/幻读:一个事务 读到 别的事务 已经提交了的insert的数据;
不同之间的事务应该是完全隔离的,所以一个事务 不应该 读到 别的事务 已经提交了的insert的数据;
在同一个事务中,多次的查询结果都应是一致的;
5.在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。
1.为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:
当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,
所有从起始点以后的操作应全部回退到开始状态。
2.事务的操作:
先定义开始一个事务,然后对数据作修改操作,这时如果提交(COMMIT),这些修改就永久地保存下来,
如果回退(ROLLBACK),数据库管理系统将放弃您所作的所有修改而回到开始事务时的状态。
3.事务的ACID:
1. 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2. 一致性(Consistency):事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
3. 隔离性(Isolation):事务的隔离性是指一个事务的执行不能被其他事务干扰,
即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰,
每一个事务都存在一个事务空间,彼此不干扰。
4. 持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,
接下来的其他操作和数据库故障 不应该对其有任何影响。
4.事务控制的语言:
begin:开启一个事务,开启一个新的事务空间
commit:提交事务
rollback:回滚事务
5.COMMIT和 ROLLBACK可以显示的控制事务。
好处:
1.保证数据一致性,修改过的数据在没有提交之前是不能被其他用户看到的。
2.在数据永久性生效前重新查看修改的数据
3.将相关操作组织在一起,一个事务中相关的数据改变或者都成功,或者都失败。
7.重置MySQL的密码:
1.第一步:停止MySQL的服务:命令行 sevices.msc 启动服务界面 手动停止服务
2.第二步:在cmd下启动MySQL服务:输入 mysql --skip-grant-tables ,不需要权限认证的启动
3.第三步:重新开启cmd的命令行,然后登录MySQL,不需要输入密码
4.第四步:修改root的密码
use mysql;
update user set password = password('新密码') where user = 'root';
5.第五步:结束mysqld的进程:执行 net stop mysql
6.第六步:重新启动MySQL的服务:执行 net start mysql
8.数据库的备份和还原:
1.数据库的备份:
1.第一步:打开cmd的命令行窗口(一定要注意这个不是在mysql命令下,若命令位置不对,会报1064(42000)错误);
输入 mysqldump -u root -p 数据库名 > C:/数据库名.sql (表和表里面的信息反编译成sql语句)
2.数据库的还原:
2.第一种还原方式:
1.第一步:在数据库服务器内部创建数据库:create database 数据库名;
2.第二步:在命令行窗口输入mysql -u root -p 数据库名 < C:/数据库名.sql(一定要注意这个不是在mysql命令下)
3.第二种还原方式:
1.第一步:在数据库服务器内部创建数据库:create database 数据库名;
2.第二步:切换到该数据库使用,然后使用source命令还原数据库数据
use 数据库名;
source C:/数据库名.sql;
等值连接:SELECT * FROM 表A INNER JOIN 表B ON 表A.字段名 = 表B.字段名
SELECT * FROM 表A FULL [OUTER] JOIN 表B ON 表A.字段名 = 表B.字段名
SELECT * FROM 表A LEFT [OUTER] JOIN 表B ON 表A.字段名 = 表B.字段名
SELECT * FROM 表A RIGHT [OUTER] JOIN 表B ON 表A.字段名 = 表B.字段名
SELECT * FROM 表A RIGHT [OUTER] JOIN 表B ON 表A.字段名 = 表B.字段名
SELECT * FROM 表A RIGHT [OUTER] JOIN 表B ON 表A.字段名 = 表B.字段名 WHERE 表A.字段名 IS NULL
UNION 与 UNION ALL
笛卡尔乘积:cross join