MySQL part2

日萌社

人工智能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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章