mysql 安装配置使用、sql语法


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:不支持事务,不支持外键,但是性能相对较高;

卸载MySQL
停止MySQL
1添加删除程序中卸载MySQL
2到安装目录删除MySQL
3删除:C:\Documents and Settings\All Users\Application Data\MySQL
	C:\ProgramData\MySQL
4查看注册表:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services
搜索mysql,找到一律干掉!
============================

不需要重启电脑(win xp),直接重新安装即可


window下MySQL客户端连接Linux下MySQL服务器

查看mysql版本的方法:
	1.登陆mysql后即可查看到版本信息
	2.mysql -V
	3.进入mysql之后:select  version();
	4.进入mysql之后:status

 

 

 


数据库安装常见错误

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;


连接join

等值连接: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


MySQL 获取时间函数 

select now();
select date_format(now(),'%Y%m%d');

select DATE_SUB(curdate(),INTERVAL 1 DAY);
select date_format(DATE_SUB(curdate(),INTERVAL 1 DAY),'%Y%m%d');
select * from userConsumeProducts WHERE insert_update_date = date_format(DATE_SUB(curdate(),INTERVAL 1 DAY),'%Y%m%d');

MySQL设置时区

运行报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
解决:设置time zone的value值,实际是时区的错误,因此只要将时区设置为你当前系统时区即可。北京时区,因此在系统中设置后,再连接数据库运行。
操作:
	mysql -uroot -padmin
	show variables like 'time_zone';

    set time_zone='+8:00';


MYSQL索引类型+索引方法

MYSQL索引有四种:
	虽然索引提高了查询的速度,但是降低了INSERT、UPDATE、DELETE(DML)的速度,因为在插入、修改、删除数据时,还要同时操作一下索引文件。
	PRIMARY(唯一且不能为空;一张表只能有一个主键索引)、
	INDEX(普通索引)、
	UNIQUE(唯一性索引)、
	FULLTEXT(全文索引:用于搜索很长一篇文章的时候,效果最好。用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以)

例子:
	1.ALTER TABLE t_user ADD INDEX name_city_phone(USERNAME,CITY,PHONE)  //普通复合索引
	2.ALTER TABLE t_user ADD UNIQUE name_city_phone(USERNAME,CITY,PHONE) //唯一复合索引

分析:
	这样的组合索引,其实相当于分别建立了三个索引。
	三个索引如下:
  		1.USERANME,CITY,PHONE  
  		2.USERNAME,CITY  
  		3.USERNAME,PHONE

	为什么没有(CITY,PHONE)索引这是因为MYSQL组合查询只从最左边开始组合:始终包含username
  	并不是查询语句包含这三列就会用到该组合索引,而是要这样的查询语句才会用到创建的组合索引。
	如下:
		SELECT * FROM t_user where USERNAME="parry" and CITY="广州" and PHONE="180"
		SELECT * FROM t_user where USERNAME="parry" and CITY="广州"
		SELECT * FROM t_user where USERNAME="parry" and PHONE="180" 

	这样的查询语句是不会用到创建的组合索引。
	如下:
		SELECT * FROM t_user where CITY="广州" and PHONE="180"
		SELECT * FROM t_user where CITY="广州"

索引使用注意事项:
	1.索引会忽略null值,所以我们在设计数据库的时候设置为为NOT NULL;
	2.短索引(给索引设置长度)不仅能够提高查询速度,而且能节省I/O操作。
	3.Mysql在查询的时候只会使用一个索引
	4.不鼓励使用like对索引操作:like"%aaa%"不会使用索引;但like“aaa%”会使用索引。即可以对固定起始值模糊查询
	5.不适用于否地操作(not in , <>, !=,or)

mysql的两种索引方法:
	1.BTREE(用于对等比较,如"="和"<=>")   // "<=>" 表示安全的比对,用与对null值比较,语义类似is null()
	2.HASH(用于非对等比较,比如范围查询)>,>=,<,<=、BETWEEN、Like

MySQL主键、创建索引、UNION 和 UNION ALL

主键


索引

短索引的设置:
	创建表时:KEY `索引名称` (`字段名`(索引长度))
	修改索引时:ALTER TABLE 表名 ADD INDEX 索引名称 (字段名1(索引长度), 字段名2(索引长度),...);
	创建索引时:CREATE INDEX index_name ON table_name (column_name(length), clolumn_name(length),...);


MySQL数据库的使用索引来搜索

1.MySQL数据库中的索引:
	UNIQUE(唯一索引)
	PRIMARY KEY(主键索引),本质是名叫PRIMARY KEY 的UNIQUE索引
	INDEX(普通索引)
	INDEX(组合索引)
	FULLTEXT(全文索引),可替代模糊查询LIKE的使用,搜索引擎常用

2.MySQL数据库的模糊查询速度慢,效率不高。
  模糊查询的用法分析:
	1.模糊查询的用法:字段名 like “%搜索内容%”
   	2.对“已添加索引的字段”进行模糊查询的话,分以下情况:
		1.使用 字段名 like “%搜索内容%”或 字段名 like “%搜索内容”的话,即模糊查询LIKE中以“%”或“_”开头的话,
		  是无法使用到索引进行快速查询的。
		2.使用 字段名 like “搜索内容%”,是可以使用到索引进行快速查询的。
 
3.即使字段添加了索引,但是在SQL语句中使用了以下规则进行WHERE条件过滤的话,便不会使用上“字段中添加的索引”进行快速查询:
	1.NULL值判断:因为使用NULL值判断的话,则不会使用字段中的索引。
		      所以字段的默认值应改为使用 0 或 -1 或 空字符串,字段的默认值不应为NULL值。
 	2.使用 != 或 <> 操作符:!= 和 <> 都表示不等于操作,则不会使用字段中的索引。应改为尽量使用 >、<、= 才会使用上字段中的索引。
	3.模糊查询LIKE中以“%”或“_”开头:是不会使用字段中的索引的。但如果以“%”或“_”结尾的话,还是可以使用到索引的。
	  				    可改为使用FULLTEXT(全文索引),搜索引擎常用。
	4.在where子句中使用 or 来连接条件:应使用UNION 或 UNION ALL 
	5.in 和 not in:尽量控制in的范围(1000以内)
	6.在where子句中对字段进行表达式操作:在列上进行运算的话,则不会使用字段中的索引

在where子句中使用 or 来连接条件:应使用UNION 或 UNION ALL


SQL UNION 和 UNION ALL 操作符

1.UNION:
	1.合并两个或多个 SELECT 语句的结果集
	2.会对合并后的结果集进行去重

2.UNION ALL:
	1.合并两个或多个 SELECT 语句的结果集
	2.不会对合并后的结果集进行去重


设置mysql可存储4个字节的字符或处理emoji表情字符

使用utf-8 无法插入4个字节等非法字符时,改为使用utf8mb4 
	产生这种异常的原因在于,mysql中的utf8编码最多会用3个字节存储一个字符,如果一个字符的utf8 编码占用4个字节(最常见的就是ios中的emoji表情字符),
	那么在写入数据库时就会报错。
	mysql从5.5.3版本开始,才支持4字节的utf8编码,编码名称为utf8mb4(mb4的意思是max bytes 4),这种编码方式最多用4个字节存储一个字符。
	1.方案一:
		在mysql的安装目录下找到my.ini,作如下修改:
			[mysqld]
			character-set-server=utf8mb4
			[mysql]
			default-character-set=utf8mb4

		  修改后重启Mysql

	2.方案二:
		将已经建好的表也转换成utf8mb4
		1.更改数据库编码:ALTER DATABASE caitu99 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
		2.创建表语句:
			CREATE TABLE `user` (
  				`id` bigint(20) NOT NULL AUTO_INCREMENT,
  				`username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
  				PRIMARY KEY (`id`)
			) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
		3.更改表编码:alter table TABLE_NAME convert to character set utf8mb4 collate utf8mb4_general_ci; 
		         或者 alter table TABLE_NAME convert to character set utf8mb4 collate utf8mb4_bin;  
		  重点注意把“可能会存储4个字节等非法字符的”字段/列 设置为 utf8mb4_general_ci 或 utf8mb4_bin
		4.druid.properties 中配置 url=jdbc:mysql://localhost:3306/mongotomysql?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8mb4
		5.查看并修改数据库属性:
			show variables like '%char%';
			SET character_set_client = utf8mb4;
			SET character_set_results = utf8mb4;
			SET character_set_connection = utf8mb4;
			SET character_set_server = utf8mb4;
 		 	SET global character_set_filesystem=utf8mb4;

public class 特殊字符过滤处理 {

    // 过滤特殊字符
    public static String StringFilter(String str) throws PatternSyntaxException
    {
        // 只允许字母和数字 String regEx ="[^a-zA-Z0-9]";
        // 清除掉所有特殊字符
        String regEx = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]";
         Pattern p = Pattern.compile(regEx);

        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    @Test
    public void testStringFilter() throws PatternSyntaxException
    {
        String str = "*adCVs*34_a _09_b5*[/435^*&城池()^$$&*).{}+.|.)%%*(*.中国}34{45[]12.fd'*&999下面是中文的字符¥……{}【】。,;’“‘”?";
        System.out.println(str);
        System.out.println(StringFilter(str));
    }
}
处理emoji表情字符
    <dependency>
      <groupId>com.vdurmont</groupId>
      <artifactId>emoji-java</artifactId>
      <version>4.0.0</version>
    </dependency>

                    //使用 emoji-java库 对带有 emoji表情字符 的字符串进行处理
                    //经过转换之后的字符就可以存到数据库了, 那么从数据库中取出来后,将字符还原成emoji表情使用如下方法即可。
                    // parseToHtmlDecimal:把 emoji表情 转换为 普通字符,才可以存储到数据库中
                    String username_EmojiParser = EmojiParser.parseToHtmlDecimal(username);
                    // parseToUnicode:把 从数据库中 读取出来的 “被转为普通字符的”emoji表情 转换为 emoji表情,便可以用于页面上显示 正常的 emoji表情
//                    String s = EmojiParser.parseToUnicode(s);

一次查询中只能用到一个索引:单字段索引 或 多字段索引(复合索引)

1.如果经常需要同时对两个字段进行AND查询,那么使用两个单独索引不如建立一个复合索引,因为两个单独索引通常数据库只能使用其中一个,
  而使用复合索引因为索引本身就对应到两个字段上的,效率会有很大提高。

2.如果经常进行多字段的条件过滤查询的话,请使用复合索引:
	1.复合索引:多个字段列组成一个索引
	2.创建复合索引示例:KEY `索引名` (`字段1`,`字段2`,`字段3`)
	  根据最佳左前缀规则,实际会自动创建出(`字段1`)、(`字段1`,`字段2`)、(`字段1`,`字段2`,`字段3`) 一共3个索引
	3.查询示例:where后接多个字段一起进行过滤查询时,要按照所创建出复合索引的每个字段位置顺序进行查询。
	  如:复合索引是(`字段1`,`字段2`,`字段3`) ,必须按照索引中的字段顺序进行条件查询那么才可以使用上索引。
	      下面方式可以使用上索引:“where 字段1”、“where 字段1 and 字段2”、“where 字段1 and 字段2 and 字段3” 等方式。
	      下面方式无法使用上索引:“where 字段1 or 字段2” 或 “where 字段2”、“where 字段3”、“where 字段2 and 字段3”、“where 字段1 and 字段3”等方式。

3.与其说是“数据库查询只能用到一个索引”,倒不是说是 和全表扫描/只使用一个索引的速度比起来,去分析两个索引二叉树更加耗费时间,
  所以绝大多数情况下数据库都是是用一个索引。
  如这条语句:select count(1) from table1 where column1 = 1 and column2 = 'foo' and column3 = 'bar'
  我们来想象一下当数据库有N个索引并且查询中分别都要用上他们的情况:
	查询优化器(用大白话说就是生成执行计划的那个东西)需要进行N次主二叉树查找[这里主二叉树的意思是最外层的索引节点] 
	此处的查找流程大概如下:
		查出第一条column1主二叉树等于1的值,然后去第二条column2主二叉树查出foo的值并且当前行的coumn1必须等于1,
		最后去column主二叉树查找bar的值并且column1必须等于1和column2必须等于foo。
		如果这样的流程被查询优化器执行一遍,就算不死也半条命了,查询优化器可等不及把以上计划都执行一遍,贪婪算法(最近邻居算法)可不允许这种情况的发生,
		所以当遇到以下语句的时候,数据库只要用到第一个筛选列的索引(column1),就会直接去进行表扫描了。
  所以与其说是数据库只支持一条查询语句只使用一个索引,倒不如说N条独立索引同时在一条语句使用的消耗比只使用一个索引还要慢。
  所以如上条的情况,最佳推荐是使用index(column1,column2,column3) 这种联合索引,此联合索引可以把b+tree结构的优势发挥得淋漓尽致:
  一条主二叉树(column=1),查询到column=1节点后基于当前节点进行二级二叉树column2=foo的查询,在二级二叉树查询到column2=foo后,去三级二叉树column3=bar查找
复合索引(多列作为一个索引)代码如下:
CREATE TABLE test (  
    id         INT NOT NULL,  
    last_name  CHAR(30) NOT NULL,  
    first_name CHAR(30) NOT NULL,  
    PRIMARY KEY (id),  
    INDEX name (last_name,first_name)  
);  

多个列分别各自作为一个索引的代码如下:
CREATE TABLE test (  
    id         INT NOT NULL,  
    last_name  CHAR(30) NOT NULL,  
    first_name CHAR(30) NOT NULL,  
    PRIMARY KEY (id),  
    INDEX name (last_name),  
    INDEX_2 name (first_name)  
); 

1.一个复合索引(多列作为一个索引)索引可以认为是包含通过合并(concatenate)索引列值创建的值的一个排序数组。 
2.当查询语句的条件中包含last_name 和 first_name时,例如:SELECT * FROM test WHERE last_name='Kun' AND first_name='Li';
  sql会先过滤出last_name符合条件的记录,在其基础上在过滤first_name符合条件的记录。
3.那如果我们分别在last_name和first_name两个列上分别创建两个单列索引,同样进行WHERE last_name='Kun' AND first_name='Li' 条件查询时,
  mysql的处理方式就不一样了,它会选择一个最严格的索引来进行检索,可以理解为检索能力最强的那个索引来检索,另外一个利用不上了,这样效果就不如复合索引了。
4.但是复合索引的利用也是需要条件的,以下形式的查询语句能够利用上复合索引:
	SELECT * FROM test WHERE last_name='Widenius';  
	SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael';  
	SELECT * FROM test WHERE last_name='Widenius' AND (first_name='Michael' OR first_name='Monty');  
	SELECT * FROM test WHERE last_name='Widenius' AND first_name >='M' AND first_name < 'N';  
5.以下形式的查询语句利用不上多列索引:
	SELECT * FROM test WHERE first_name='Michael';  
	SELECT * FROM test WHERE last_name='Widenius' OR first_name='Michael';  

6.多列建索引比对每个列分别建索引更有优势,因为索引建立得越多就越占磁盘空间,在更新数据的时候速度会更慢。
  另外建立多列索引时,顺序也是需要注意的,应该将严格的索引放在前面,这样筛选的力度会更大,效率更高。

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

あずにゃん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值