MySQL学习笔记
#######################################索引############################################
#INDEX和KEY参数用于指定字段索引,用户在选择时,只需要选择其中的一种即可
#普通索引,即不应用任何限制条件的索引,该索引可以在任何数据类型中创建。字段本身的约束
#条件可以判断其值是否为空或唯一。
#创建该类型索引后,用户在查询时,便可以通过索引进行查询。在某
#数据表的某一字段中,建立普通索引后,用户需要查询数据时,只需根据该索引进行查询即可。
#1.普通索引的创建
create table score(
id int(11) auto_increment primary key not null,
name varchar(50) not null,
math int(5) not null,
english int(5) not null,
chinese int(5) not null,
index(id));
#在命令提示符中使用SHOW CREATE TABLE 语句查看该表的结构
show create table score;
#显示结果如下:
#| score | CREATE TABLE `score` (
# `id` int(11) NOT NULL AUTO_INCREMENT,
# `name` varchar(50) NOT NULL,
# `math` int(5) NOT NULL,
# `english` int(5) NOT NULL,
# `chinese` int(5) NOT NULL,
# PRIMARY KEY (`id`),
# KEY `id` (`id`) 索引值
#) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
#2.创建唯一索引
#使用UNIQUE参数可以设置唯一索引。创建该索引时,索引的值必须唯一。
#通过唯一索引,用户可以快速定位某条记录。主键是一种特殊唯一索引。
create table address(
id int(11) auto_increment primary key not null,
name varchar(50),
address varchar(200),
UNIQUE INDEX address(id ASC));
#使用FULLTEXT参数可以设置全文索引。全文索引只能创建在CHAR、VARCHAR或者TEXT类型的
#字段上。查询数据量较大的字符串类型的字段时,使用全文索引可以提高查询速度。
#例如,查询带有文章回复内容的字段,可以应用全文索引方式.需要注意的是,在默认情况下
#应用全文搜索对大小下不敏感。如果索引的列使用二进制排序后,可以执行大小写敏感的全文索引。
#3.创建全文索引
create table cards(
id int(11) auto_increment primary key not null,
name varchar(50),
number bigint(11),
info varchar(50),
FULLTEXT KEY cards_number(number));
##注意##
#只有MyISAM类型的数据表支持全文索引,InnoDB或其他类型的数据表不支持
#全文索引。
#当用户在建立全文索引的时候,返回""的错误,则说明用户操作的当前的数据表不支持
#全文索引,即不为MyISAM类型的数据表。
#4.创建单列索引
create table telephone(
id int(11) primary key auto_increment not null,
name varchar(50) not null,
tel varchar(50) not null,
index tel_num(tel(20)));
#别名:tel_num(属性名tel(长度20)[ASC|DESC])
#5.创建多列索引
create table information(
id int(11) auto_increment primary key not null,
name varchar(50) not null,
sex varchar(50) not null,
brithday varchar(50) not null,
INDEX info(name,sex));
#| information | CREATE TABLE `information`
# `id` int(11) NOT NULL AUTO_INCREMENT,
# `name` varchar(50) NOT NULL,
# `sex` varchar(50) NOT NULL,
# `brithday` varchar(50) NOT NULL,
# PRIMARY KEY (`id`),
# KEY `info` (`name`,`sex`)
#) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
#+-------------+---------------------------
#注意#
#在多列索引中,只有查询条件中使用了这些字段中的第一个
#字段(即上面示例中的name字段),索引才会被使用.
#6.创建空间索引
#MySQL中只有MyISAM存储引擎支持空间检索,而且索引的字段不能为空值。
create table list(
id int(11) primary key auto_increment not null,
goods geometry not null,
SPATIAL INDEX listinfo(goods)
)engine=MyISAM;
#在已建立的数据表中创建索引
#CREATE[UNIQUE|FULLTEXT|SPATIAL] INDEX index_name ON table_name(属性:索引对应的字段名称[(length)][ASC|DESC]);
###########################################视图############################################
#视图的概念
#视图是一个从数据库中的一个或者多个表中导出来的虚拟表,其内容由查询定义。
#查询MySQL中root用户是否具有创建视图的权限
SELECT Select_priv,Create_view_priv FROM mysql.user WHERE user='root';
#############################################触发器########################################
#MySQL触发器
#创建MySQL触发器
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW 执行语句
create table studentinfo(
id int(11) primary key auto_increment not null,
name varchar(50));
#创建一个名称为timelog的表格,该表的结构非常简单。
create table timelog(
id int(11) primary key auto_increment not null,
savetime varchar(50) not null);
#创建名称为auto_save_time的触发器
#delimiter 定界符
create trigger auto_save_time before insert on studentinfo for each row
insert into timelog(savetime)values(now());
#auto_save_time 触发器创建成功,其具体的功能是当用户想studentinfo表中执行“INSERT”操作时,数据库系统会自动在插入语句执行之前想timelog表
#插入当前时间。
insert into studentinfo(name) values('charis');
select * from timelog;
#创建具有多个执行语句的触发器
CREATE TRIGGER 触发器名称 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW
BEGIN
执行语句列表
END
#多学两招:
#一般放在BEGIN与EN之间的多条执行语句必须用借书分隔符";"分开。
#在创建触发器过程中需要更改分隔符,这里应用上一章提到的DELIMITERT语句,
#将结束符号变为"//".当触发器完成后,读者同样可以应用该语句将结束符换回";"
#创建具有多个执行语句的触发器过程如下:
create table timeinfo(
id int(11) primary key auto_increment,
info varchar(50) not null
)//
#创建一个由DELETE触发多个执行语句的触发器delete_time_info,代码如下:
delimiter//
create trigger delete_time_info after delete
on studentinfo for each row
begin
insert into timelog(savetime)values(now());
insert into timeinfo(info)values('deleteract');
end
//
#执行删除代码如下:
DELETE FROM studentinfo where id=1;
#多学习两招
#在MySQL中,一个表在相同的时间和相同的触发时间只能创建一个触发器,
#如触发时间的INSERT,触发时间为AFTER的触发器只能有一个,但是可以定义一个BEFORE的触发器。
#查看触发器
show triggers;
#说明:
#information_schema是MySQL中默认存在的库,而information_schema.triggers是数据库
#中用于记录触发器信息的数据表。
#查看triggers表中触发器信息
SELECT * FROM information_schema.triggers;
#如果数据库中存在数量较多的触发器,建议使用以下这种查看触发器的方式,这样会在查找
#触发器过程中避免很多不必要的麻烦.
SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME='触发器的名称';
#应用触发器
#在MySQL中,触发器按以下顺序执行:BEFORE触发器、表操作、AFTER触发器操作,其中表操作
#包括常用的数据库操作命令如INSERT、UPDATE、DELETE。
#(1)首先,创建名称为before_in的BEFORE INSERT 触发器,其代码如下:
create trigger before_in before insert on studentinfo for each row
insert into timeinfo(info)values('before');
#(2)然后,创建名称为after_in的AFTER INSERT 触发器,其代码如下:
create trigger after_in after insert on
studentinfo for each row
insert into timeinfo(info)values('after');
#(3)触发器创建完毕后,向数据表studentinfo中插入一条记录。其代码如下:
insert into studentinfo(name)values('Nowitzki');
#执行成功后,通过SELECT语句查看timeinfo数据表的插入情况.其代码如下:
select * from timeinfo;
#查询结果显示BEFORE和AFTER触发器都被激活.BEFORE触发器首先被激活,然后AFTER触发器
#被激活。
#删除触发器
#语法格式如下:
DROP TRIGGER 触发器名称
#下面为delete_time_info的触发器删除,其执行代码如下:
DROP TRIGGER delete_time_info;
SHOW TRIGGERS;
##实战模拟
##应用触发器添加日志信息(java)
#触发器是一种特殊类型的存储过程,是为相应数据库操作语句DML事件
#或数据定义语言DDL事件而执行的存储过程。
#当用户对表进项相应的操作时,触发器启动执行。
#本实例应用INSERT触发器,在向用户表中插入信息时,同时该用户的登录时间
#添加到日志表(tb_info)中。
#(1)首先在数据库中创建触发器,当用户在用户表中添加数据时,系统会自动执行
#触发器,向日志表中添加信息。
#创建触发器代码如下:
delimiter//
create trigger triInfoInsert before insert on
tb_user for each row
insert into tb_info(ddate)values(now());
//
#(2)在项目中创建类UserUtil,在该类中定义executeUpdate()方法,实现向tb_user表
#中添加数据,当系统调用该方法时,会自动触发触发器。
#该方法的具体代码如下:
#public boolean executeUpdate(User user){
#conn = getConn();//获取数据库连接
#try{
# //定义添加数据的SQL语句
# PreparedStatement statement = conn
# .prepareStatement("insert into tb_ser(userName,passWord,age,sex,job)values(?,?,?,?,?)");
# statement.setString(1,user.getUserName());
# statement.setString(2,user.getPassWord());
# statement.setInt(3,user.getAge());
# statement.setString(4,user.getSex());
# statement.setString(5,user.getJob());
# statement.executeUpdate();
# return true;
#}catch(Exception e){
# e.printStackTrace();
# return false;
#}
#}
#查看MySQL触发器(PHP)
#在MySQL数据库中,创建触发器前应先查看数据库中的触发器。
#这样,既可以使开发人员对指定的数据库中的所有触发器及功能
#有一个直观的把握,又可以避免创建同名或类似功能的触发器。
#运行本例,如图,首先在文本框中输入要查看触发器的数据库,然后单击
#"查看"按钮即可将该数据库中所有的触发器的详细信息显示出来。
#其实现过程如下:
#(1)选择要查看的触发器的数据库,其代码如下:
#<?php
# $dbname = $_POST['name'];
# $conn = mysql_connect("localhost","root","你的mysql数据库密码");
# mysql_select_db($dbname,$conn);
# mysql_query("set names gb2312");
#(2)执行show trigger语句并显示所查找到的触发器的详细信息,其代码如下:
#<?php
# $sql = @mysql_query("show triggers",$conn);
# $info = @mysql_fetch_array($sql);//以数组的形式返回数据
# if($info==false){
# ?>
#<tr>
#<td height="25" cospan="5" bgcolor="#FFFFFF"> <div align="center">该数据库没有设置触发器!</div></td>
#</tr>
#<?php
# }esle{
# do{
#?>
# <tr>
# <td height="25" bgcolor="#FFFFFF"> <div align="center"><?php echo $info['Trigger'];?></div></td>
# <td height="25" bgcolor="#FFFFFF"> <div align="center"></div><?php echo $info['Table'];?></td>
# <td height="25" bgcolor="#FFFFFF"> <div align="center"></div><?php echo $info['Event'];?></td>
# <td height="25" bgcolor="#FFFFFF"> <div align="center"></div><?php echo $info['Timing'];?></td>
# <td height="25" bgcolor="#FFFFFF"> <div align="center"></div><?php echo $info['Statement'];?></td>
# </tr>
# <?php
# }while($info=mysql_fetch_array($sql));
# }
#
# ?>
#########################################事务#################################################
##MySQL事务
##在用户操作MySQL过程中,对于一般简单的业务逻辑或中小型程序而言
#无需考虑应用MySQL事务。但在比较复杂的情况下,往往用户在执行某些数据库操作过程中
#需要通过一组SQL语句执行多项并行业务逻辑或程序。
#这样,就必须保证所有命令执行的同步性,使执行序列中产生依靠关系的动作能够同时
#成功或同时返回初始状态。在此情况下,就需要用户优先考虑使用MySQL事务处理。
#学习摘要
#>>MySQL事务概述
#>>MySQL事务初始化、创建
#>>MySQL事务的查询、提交和事务回滚
#>>MySQL事务行为
#>>MySQL事务和性能
#>>MySQL伪事务
#在MySQL中,事务由单独单元的一个或多个SQL语句组成。
#在该单元中,每个MySQL语句是相互依赖的。而整个单独单元作为一个不可分割的整体
#如果单元中一旦某条SQL语句执行失败或产生错误,整个单元将会回滚。
#所有收到影响的数据将返回事务开始以前的状态;
#如果单元中所有的SQL语句均执行成功,则事务会被顺利执行。
#在现实生活中,事务处理数据的应用非常广泛,如网上交易、银行事务等。下面通过网上交易流程
#向读者展示事务的概念。
#相信大多数用户都有过网上购物的体验,即用户登录某个大型购物网站中,浏览
#该网站中所陈列的商品信息,用户将自己喜欢的商品放入购物车中,选购完毕后,用户需要
#对选购的商品进行在线支付,用户对所选商品付款完毕后,会通知商家发货。
#在此过程中,用户所付货款并未提交到商户手中,用户收到货物之后,确认收货,商家才收到商品货款
#整个交易过程才算完成。如果任何一步操作失败,则会导致双方陷入尴尬的境界。试想,
#当用户选购商品并付款操作完成后,用户选择在发货过程中取消订单,这是商家不会得到货款,
#如果不应用事务处理,用户在取消订单操作过程后,商家仍然继续将用户所订购的商品发送
#给用户,这会导致一些不愉快的争端。所以在整个交易过程中,必须采用事务来对网上交易进行回滚操作
#其流程图如图:
# |
# |<———————————|
# v |
# |用户选购商品| |
# | 失败 |
# |——————————> |
# v |
# |添加到购物车| |
# | 失败 |
# |——————————> |
# v |
# | 在线付款 | |
# | 失败 |
# |———————————>|
# v |
# | 商家发货 | |
# | 失败 |
# |———————————>|
# v |
# | 用户收货 | |
# | 失败 |
# |———————————>|
# v |
# | 确认收货 | |
# | 失败 |
# |———————————>|
# v
# | 交易完成 |
# 图 应用事务处理网上交易流程
#在网上交易流程过程中,商家与用户的交易可以被认为是一个事务处理的过程。
#其中整个事务过程中,如果在交易流程中存在任意一个环节失败,都可能导致双方交易失败。
#如前面事务定义所说,所有这些流程都应该被成功执行,在MySQL中,如果其中任何命令失败,都会
#导致所有操作命令被撤销,系统返回未操作前的状态,即回滚到初始状态。
#添加到购物车、在线付款、商家发货等构成一个基本的事务。整个交易流程可以被看作一个完整的单元,用于实现整体事务。
# 通过InnoDB 和 BDB类型表,MySQL事务能够完全满足事务安全的ACID测试,但是并不是所有表类型都支持事务,如MyISAM类型表就不能
#支持事务。只能通过伪事务对表实现事务处理。
#ACID支出每个事务型RDBMS必须遵守4个属性,即原子性、一致性、独立性和持久性。
#原子性
# 原子性意味着事物的整个整体性和不可分割性,这类似于化学中的原子,事务就具备这样的
#属性,它被认为是一个不可分割的单元。假设一个事务由多种任务组成,其中语句必须同时
#操作成功,才可以认为事务是成功的,否则将回滚到初始状态。
# 原子性的执行是一个全部发生或全部失败的整体过程。在一次操作中,如果事务中的任何一个语句
#失败,前面执行的语句都将返回,以保证数据的整体性不被破坏.
#这在常用的系统应用中,为保证数据的安全性起到了一定的作用。
#一致性
#
#
#孤立性
#独立性保证每个事务完整地在其各自的空间内被顺利执行,保证事务与实务之间
#不会相互冲突。
#
#
#持久性
# 在MySQL中,即便是数据库系统崩溃,一个提交事务仍然在坚持。
#当一个事务完成,数据库的日志已经被更新时,持久性即可发挥其特有功效。在
#MySQL中,如果系统崩溃或者存储介质被破坏,通过使用日志,系统能够恢复在重启之前
#进行的最后一次或功能更新,可以反应系统崩溃时处于执行过程的事务的变化。
# MySQL的持久性是通过一条记录事务过程中系统变化的二进制事务日志文件来实现
#的。如果遇到硬件损坏或者系统的异常关机,系统在下一次启动时,通过使用最后的备份
#和日志就可以恢复丢失的数据。
#默认情况下InnoDB表持久性最好,MyISAM表提供部分持久性。
#在创建事务的过程中,用户需要创建一个InnoDB或BDB类型的数据表,其基本命令结构如下:
CREATE TABLE table_name(field-defintions)TYPE=INNODB/BDB;
#table_name :表名
#field-defintions:为表内定义的字段等属性
#TYPE:指定数据表的类型
#用户如果希望已经存在的表支持事务处理,可以应用ALTER TABLE 命令指定数据表的类型。
ALTER TABLE table_name TYPE=INNODB/BDB;
#初始化事务
#初始化MySQL事务,首先声明初始化MySQL事务后所有的SQL语句为一个单元。
#在MySQL中,应用START TRANSCATION命令来标记一个事务的开始。
#初始化事务的结构如下:
START TRANSCATION;
#提交事务
#由事务的特性知,事务具有孤立性。当事务处在处理过程中时,MySQL并未将结果写入磁盘中。
#这样一来,这些正在处理的事务相对其他用户是不可见的。
#一旦数据被正确插入,用户可以使用COMMIT命令提交事务。
#提交事务的命令结构如下:
COMMIT
#撤销事务(事务回滚)
ROLLBACK
#关闭自动提交功能。
set autocommit=0;
#只有当用户输入COMMIT命令之后,MySQL才将数据表中的资料提交到数据库中。
#如果不提交事务,而终止MySQL会话,数据库将会自动执行回滚操作。
#事务的孤立级
#事务具有独立的空间。
#在MySQL服务器中,用户通过不同的会话执行不同的事务。
#在多用户环境中,许多RDBMS会话在任意指定时刻都是活动的。
#为了使事务互不影响,保证数据库性能不受影响,采用事务的孤立级是十分有必要的。
#
#孤立性,强制保持每个事务的独立性,以此来保证事务中看到一致的数据。
#基于ANSI/ISO SQL规范,MySQL提供4种孤立级:
SERIALIZABLE(序列化)
REPEATABLE READ (可重读)
READ COMMITTED(提交后读)
READ UNCOMMITTED(未提交读)
#序列化
#将对象的状态信息转换为可以存储或传输的形式的过程。
#在序列化期间,对象将其当前状态写入到临时或持久性存储区。
#以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
#序列化使其他代码可以查看或修改那些不序列化便无法访问的对象实例数据。
#确切的说,代码执行序列化需要特殊的权限:即指定了SerializationFormatter标志的
#SecurityPermission。
#目的:
#1.以某种存储形式使自定义对象持久化。
#2.将对象从一个地方传递到另一个地方。
#3.使程序更具有维护性。
#顾名思义,以序列的形式对食物进行处理。该独立级的特点是只有当事务提交后,用户
#才能从数据库中查看数据的变化。该独立级运行会影响MySQL的性能,因为需要占用大量的资源,以
#保证使大量事务在任意时间都不被用户看到。
#修改事务的孤立级
set global transaction isolation level read committed;
#获取当前事务孤立级变量的值,其命令如下:
SELECT @@tx_isolation;
#事务和性能
#应用小事务
#应用小事务的意义在于:保证每个事务不会在执行前等待很长时间,从而避免各个事务
#因为相互等待而导致系统的性能大幅度下降。
#用户在应用少数大事务的时候,可能无法看出因事务间相互等待而导致
#系统性能下降。
#MySQL伪事务
#MySQL的MyISAM类型数据表中,并不支持COMMIT(提交)和
#ROLLBACK(回滚)命令。当用户对数据库执行插入、删除、更新等操作时,这些
#变化的数据都被立刻保存在磁盘中。
#这样,在多用户环境中,会导致诸多问题。
#为避免同一时间有多个用户对数据库中指定表进行操作,可以应用
#表锁定来避免在用户操作数据表过程中受到干扰。
#当且仅当该用户释放表的操作锁定后,其他用户才可以访问
#这些修改后的数据表。
#
#设置表锁定代替事务表添加锁定。
#步骤如下:
#(1)为指定数据表添加锁定。
# LOCK TABLES table_name lock_type,...
#(2)用户执行数据表的操作,可以添加、删除或者更改部分数据。
#(3)用户完成对锁定数据表的操作后,需要对该表进行解锁操作,释放该表的锁定状态。语法:UNLOCK TABLES
#1.以读方式锁定数据表
lock table studentinfo read;
desc studentinfo;
#或者
show columns from studentinfo;
#| Field | Type | Null | Key | Default | Extra
#+-------+-------------+------+-----+---------+------------
#| id | int(11) | NO | PRI | NULL | auto_increm
#| name | varchar(50) | YES | | NULL |
#+-------+-------------+------+-----+---------+------------
#2 rows in set (0.01 sec)
#mysql> show columns from studentinfo;
#+-------+-------------+------+-----+---------+------------
#| Field | Type | Null | Key | Default | Extra
#+-------+-------------+------+-----+---------+------------
#| id | int(11) | NO | PRI | NULL | auto_increm
#| name | varchar(50) | YES | | NULL |
#+-------+-------------+------+-----+---------+------------
#2 rows in set (0.01 sec)
mysql> insert into studentinfo(name)value('zhangshang');
#ERROR 1100 (HY000): Table 'timelog' was not locked with LOCK TABLES
#从上述结果可以看出,当用户视图向数据库插入数据时,将会返回失败信息。
#当用户将锁定的表解锁后,再次执行插入操作:
unlock table;
insert into studentinfo(name)values('zhangsan');
#mysql>unlock table;
#Query OK,0 rows affected(0.00 sec)
#mysql>insert into studentinfo(name)values('zhangsan');
#Query OK,1 rows affected(0.03 sec)
#锁定释放后,用户可以对数据库执行添加、删除、更新等操作;
#以写方式锁定数据表
#与以读方式锁定表类似,表的以写锁定是设置用户可以修改
#数据表中的数据,但是除自己以外的其他会话中的用户不能进行
#任何读操作。
#用户A:
lock table studentinfo write;
#因为该表为写锁定,用户可以对数据库的数据执行修改、添加、删除等操作。
#mysql>lock table studentinfo write;
#Query OK,0 rows affected(0.00 sec)
#mysql> select * from studentinfo;
#----+----------+
# id | name |
#----+----------+
# 2 | zhnagsan |
#----+----------+
# 1 row in set (0.00 sec)
#用户B:-------在新打开的命令提示界面中:
#mysql> select * from studentinfo;
#
# 没有结果显示
# 此时,用户在队列中等待查看或操作。
#
#
#当用户A在其命令行提示窗口下输入:
#unlock table;
#突然!
#用户B的命令行提示窗口就立马出现了其所查询的数据表:
#
#
#Database changed
#mysql> select * from studentinfo
#+----+----------+
#| id | name |
#+----+----------+
#| 2 | zhnagsan |
#+----+----------+
#1 row in set (1 min 22.81 sec)
#####注意#####
#使用UNLOCK TABLE命令后,将会释放所有当前处于锁定状态的数据表#
#应用表锁定实现伪事务
#下面示例通过使用表锁定对MyISAM表进行锁定操作,
#以此过程来代替事务型表InnoDB,即应用表锁定来实现事务.
#步骤:
#(1)对数据库中的数据表进行锁定操作,可以对多个表做不同的方式锁定,其代码格式如下:
LOCK TABLE table_name1 lock_type1,table_name2 lock_type2,table_name3 lock_type3...
#(2)执行数据库操作,向锁定的数据表执行添加、删除、修改等操作.
#在执行过程中,该伪事务所产生的结果是不会被其他用户更改的。
#(3)释放锁定的数据表,以便让正在队列中等待查看或操作的其他炉用户可以浏览数据表中的数据或
#对操作表执行各种数据的操作。
#实战模拟
#批处理中使用事务(java)
#在企业级的应用程序中,经常会遇到多个数据表同时存取的情况。
#最明显的例子是银行的转账业务,从汇款账户中减去指定金额,并将
#该金额添加至收款账户中。
#但如果在转账过程中发生程序错误或者系统断电等意外情况
#就可能导致汇款账户的余额已经减少而收款账户的余额没有增加
#这就需要应用事务对该问题进行处理。
#
#本实例模拟银行转账系统,通过事务保证转账业务的顺利进行,其运行结果如图
#
#实现过程如下:
#(1)在项目中创建BatchAffair,在该类中定义操作数据的各种方法。
#其中定义获取账户表tb_transition中所有账户的selectIds()方法,该
#方法以List集合对象作为返回值:
#
#具体代码如下:
#public List selectIds(){
# conn= getConn();//获取数据库连接
# Statement cs = null;//定义CallableStatement对象
# String sql = "Select accoutNumber from tb_transition";//定义查询视图的SQL语句
# List list = new ArrayList();//定义保存查询结果的List集合
# try{
# cs = conn.createStatement();//实例化Statement对象
# ResultSet rest = cs.executeQuery(sql);//执行SQL语句
# while(rest.next()){
# String accountNumber = rest.getString(1);
# list.add(accountNumber);
# }
# }catch(SQLException e){
# e.printStackTrace();
# }
# return list;
#}
#
#public void Batch(String incomeId,String goId,float money)throws SQLException{
# try{
# conn = geConn();//获取数据库连接---这个已经是被封装过的方法。
# boolean autoCommit = conn.getAutoCommit();
# conn.setAutoCommit(false);
#
# Statement cs = null; //定义Statement对象
# cs = conn.createStatement();//实例化Statement对象
# cs.addBatch("update tb_transaction set deposit=deposit-" + money
# + ",transition=transition-" + money
# + "where accoutNumber=" + goId);//定义修改转账表中数据的方法
# cs.addBatch("update tb_transition set deposit=depostit+" + money
# + ",shift=shift+" + money + "where accountNumber="
# +incomeId);
# cs.executeBatch();//批量执行SQL语句----这个是已经被封装过的方法。
# cs.close();
# conn.commit();
# conn.setAutoCommit(autoCommit);
# conn.close();
# }catch(){
# conn.rollback();
# e.printStackTrace();//其实这样写不好,应该为: throw new RuntimeException(e);
# }
#}
#***查询优化***#
#MySQL性能优化目的是为了是MySQL数据库以进行运行速度更快、占用空间更小
#的方式进行。其中查询是数据库操作中最频繁的操作方式之一,为了
#提高查询速度和提高MySQL数据库的性能,本章将向读者介绍多种不同的方式
#来对查询进行优化处理,并保证查询有效、稳定的运行。
#
#学习摘要
#索引
#分析查询语句
#查询高速缓存
#优化多表结构
#使用临时表
#优化表设计
#索引
#分析查询优化应用EXPLAIN 数据库查询语句
explain select * from studentinfo where name='zhangsan';
#
#+----+-------------+-------------+------+---------------+------+---------+------
#+------+-------------+
#| id | select_type | table | type | possible_keys | key | key_len | ref
#| rows | Extra |
#+----+-------------+-------------+------+---------------+------+---------+------
#+------+-------------+
#| 1 | SIMPLE | studentinfo | ALL | NULL | NULL | NULL | NULL
#| 1 | Using where |
#+----|+-------------+-------------+------+---------------+------+---------+------
#+----|--+-------------+
# |
# v
# 表格字段rows为1,如果该记录的字段rows为10000000..... 这样的话,每条前面的每条记录都要被
#遍历一遍,这样将会耗费很多的时间。
#其中各个字段所在表的意义如下:
#id列:支出在整个查询中SELECT的位置
#table列:指定所查询的表名
#type列:连接类型,该列中存储很多值,范围从const到ALL
#possible_keys列:指出为了提高查找速度,在MySQL中可以使用的索引
#key列:指出实际使用的键
#rows列:指出MySQL需要在相应表中返回查询结果所检验的行数,为了得到
#总行数,MySQL必须扫描处理整个查询,再乘以每个表的行值。
#Extra列:包含一些其他信息,设计MySQL如何处理查询。
# 现在,在name字段上建立一个名为index_name索引。
#创建该索引的代码如下:
# CREATE INDEX index_name ON studentinfo(name);
#
#在使用查询操作中,使用索引不但会自动优化查询效率,同时会降低服务器的开销。
#使用索引查询
#explain select * from studentinfo where name like '%1';
#示例应用了LIKE关键字,并匹配字符串中含有百分号"%"的符号,应用
#explain语句执行如上命令。
#2.查询语句中使用多列索引
CREATE INDEX index_student_info ON studentinfo(name,sex);
#3.查询语句中使用OR关键字
SELECT * FROM studentinfo WHERE name='Chris' OR sex='M';
#
#分析查询语句
#
#DESCRIBE 缩写 DESC
#使用方法与EXPLAIN语法是相同的。
#查询高速缓存
#在MySQL中,用户通过SELECT语句查询数据库时,该操作将结果集被保存到一个特殊的高级缓存中,
#从而实现查询操作。首次查询后,当用户再次做相同的查询操作时,MySQL即可从高速缓存中检索结果。
#这样一来,既提高了查询效率,又起到了优化查询的作用。
SHOW VARIABLES LIKE '%query_cache';
#+------------------+-------+
#| Variable_name | Value |
#+------------------+-------+
#| have_query_cache | YES |
#+------------------+-------+
#1 row in set (1.01 sec)
#下面对主要参数进行说明:
#have_query_cache:表明服务器在默认安装下,是否已经配置查询高速缓存
#query_cache_size:高速缓存分配空间,如果该空间为86则证明分配给高速缓存
#空间大小为86MB。如果该值为0则表明查询高速缓存已经关闭。
#query_cache_type:判断高速缓存开启状态,其变量值范围从0~2.
#其中当该值为0或OFF时,表明查询高速缓存已经关闭;当该值为1或ON时表明高速缓存已经打开;其值为2或DEMAND时,表明要
#根据需要运行都是带有SQL_CACHE选项的SELECT语句,提供查询高速缓存。
#使用高速缓存
#在MySQL中,查询高速缓存的具体语法结构如下:
SELECT SQL_CACHE * FROM 表名;
#mysql> SELECT SQL_CACHE * FROM
#+----+----------+
#| id | name |
#+----+----------+
#| 2 | zhnagsan |
#+----+----------+
#1 row in set (0.00 sec)
#如果经常运行查询高速缓存,将会提高MySQL数据库的性能。
#指点迷津:
# 一旦表有变化,使用这个表的查询高速缓存将会失效,且将从高速缓存中删除。
#另外,不使用高速缓存查找可以应用SQL_NO_CACHE关键字。
#优化多表查询
#在MySQL中,用户可以通过连接实现多表查询,在查询过程中,用户将表中的一个
#或多个共同字段进行连接,定义查询条件,返回同一的查询结果。这通常用来佳丽RDBMS常规表
#之间的关系。在多表查询中,可以应用子查询来优化多表查询,即SELECT语句中嵌套其他SELECT语句。采用
#子查询优化多表查询的好处有很多,其中,可以将分步查询的结果整合成一个查询,这样就不需要再执行多个单独
#查询,从而提高了多表查询的效率。
#
#下面通过一个实例来说明如何优化多表查询:
create table connection(
sid int(16) primary key auto_increment,
cellphone int(11)
);
select cellphone from connection where sid=(select id from studentinfo where name='zhangsan');
#下面应用优化算法,以便可以优化查询速度。
#在命令提示符中输入以下命令:
select stu_con.cellphone from connection as stu_con,studentinfo as stu_info where stu_con.sid=stu_info.sid and stu_info.name='Leonsk';
#以上命令的作用是将connection 和 studentinfo表分别设置别名stu_con、stu_info,通过连个表的sid字段建立连接
#并判断studentinfo表中是否含有名称为"LeonSK"的学生姓名,并将其电话号码
#在屏幕输出。该语句已经将算法进行优化,以便提高数据库的效率,从而实现
#查询优化的效果。
#
#
#########################################额外补充#################################################
#为表取别名:
#当表的名字特别长的时候,在查询中直接使用表名很不方便。这时可以为表取一个贴切的别名。
select * from tb_program p where p.talk='PHP';
#为字段取别名:
#格式如下:
#字段名 [AS] 别名
#e.g
select section AS login_section,name AS login_name from tb_login;
##########################################################################################
#如果用户希望避免因出现SELECT嵌套导致代码可读性下降,则可以通过服务器变量进行优化处理,下面
#应用SELECT嵌套方式来查询数据库,在命令提示符中输入如下命令:
select name from studentinfo where age > (select avg(age) from studentinfo);
#输入该命令的目的是获取学生信息表中年龄大于平均年龄
#的返回结果集,下面应用服务器端MySQL变量对查询进行优化,
#在命令提示符中输入如下代码:
select @avgage:=avg(age) from studentinfo;
select distinct name from studentinfo where age >@avgage;
#上述合并两个查询的效率将优于子查询运行效率,故采用服务器变量也可以优化查询。
###使用临时表
# 在MySQL中,还允许使用CREATE TEMPORARY TABLE 命令创建临时表。
#临时表是针对单一MySQL会话过程而存在的,其生命周期从客户机打开该会话过程开始,
#至客户机关闭与MySQL数据库连接时结束。当用户一旦断开数据库连接时,
#该会话过程即被删除。临时表一般用于临时存放基于会话的数据或计算,
#或者暂时为用户保存部分数据。但是该表依赖于会话,所以在不同的会话中,即使用户
#名相同的临时表,也不会引起冲突。
# 临时表只存在内存中,所以,从读写方面考虑,其读写速度都优于将数据存储在硬盘
#的读写速度。临时表结果可以有效地作为中间存储区域,以便提高
#查询效率和MySQL性能,帮助用户把复杂的查询拆分成更为简单的部件,或者作为子查询和连接支持
#的代替。
#
# 当需要查询的数据过于庞大时,对于庞大的数据进行指定查询(如应用MySQL内置函数SUM()或AVG())可能
#会耗费大量的时间并占用大量的服务器资源。
#为了解决这一问题,这里可以应用INSERT...SELECT语句,只提取某一段数据,并将该段数据存入
#一个临时表中。并在临时表中对数据进行处理,从而起到优化的作用。当用户关闭数据库
#连接后,临时表将被删除。同样,临时表中可能包含很多记录子集,
#其性能将会得到很大提高,同时也降低了服务器的负荷。
#
#下面创建一个临时学生成绩信息表,其代码如下:
create temporary table studentscore(
id int(11) primary key auto_increment not null,
math int(5) not null,
physics int(5) not null,
english int(5) not null,
history int(5) not null,
science int(5) not null,
sid int(11) not null);
#向临时表中插入一条数据,在命令提示符中输入以下命令:
insert into studentscore(math,physics,english,science,sid)values(88,90,79,68,89,1);
#然后通过SELECT语句查看该临时表,其结果如图所示:
select * from studentscore;
#当用户关闭数据库连接时,再次打开数据库并应用SELECT语句查询该数据表
#则会提示用户不存在该数据表,其运行结果如图所示:
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 17
Current database: test
ERROR 1146 (42S02): Table 'test.studentscore' doesn't exist
#优化表设计
# 在MySQL数据库中,为了使查询能够更加精炼、高效,在用户设计数据表时,应该考虑一些因素
# 首先,在设计数据表时应优先考虑使用特定字段长度,后考虑使用变长字段,如在用户
#创建数据表时,考虑创建某个字段类型为VARCHAR而设置其长度为255,但是在实际应用时,
#该用户所存储的数据根本达不到该字段所设置的最大长度,如设置用户性别的字段,往往可以用"M"表示男性
#"F"表示女性,如果给该字段设置长度为VARCHAR(50),则该字段占用了过多的列宽,这样不仅浪费
#资源,也会降低数据表的查询效率。适当调整列宽不仅可以减少磁盘空间,同时也可以使数据在进行处理
#时产生的I/O过程减少。将字段长度设置成其可能应用的最大范围可以充分优化查询效率。
# 改善性能的另一项技术是使用OPTIMIZE TABLE命令处理用户经常造作的表。频繁操作数据库中的特定表会
#导致磁盘碎片的增加,降低MySQL的效率,故可以应用该命令处理经常操作的数据表,以便于优化访问查询效率
#
# 在考虑改善表的性能的同时,要检查用户已经建立的数据表,划分数据的优势在于可以
#使用户更好地设计数据表,但是过多的表意味着性能降低,故用户应检查这些表是否有必要整合为
#一个表,如没有必要整合,在查询过程中,用户可以使其连接,如果连接的列采用相同的数据类型和、
#长度,同样可以达到查询优化的作用。
###MySQL系统管理
#
#MySQL服务器如何提供对数据的访问
管理
#mysqld(单独实体MySQL服务器)----------->数据目录下的一切
#客户程序绝不会直接操作数据。
#客户程序---服务器提供数据可访问切入点----想使用的数据
命令行(或选项文件) 监听网络连接
#服务器启动 ----------------------------->打开一些日志文件-------------------->为数据目录呈现一个网路接口
连接
#客户端-----------服务器
# MySQL查询传输请求
#客户端---------------------------------->服务器--=-------执行相关的操作
# <———————————————————————————————————
# 返回结果
#服务器是多线程的,并能服务多个客户的同时连接。
#然而,因为MySQL服务器每次只能执行一个修改操作,
#所以,实际效果是顺序化请求,以使另个客户决不能在
#同一时刻改变同一记录。
#服务器作为数据库访问的唯一仲裁者提供了避免可从同时访问数据库表的
#多个进程的破坏的保证。
#管理员应该知道有时候服务器没有对目录进行独裁控制:
#
#(1)当一个单个数据目录上运行多个服务器时。
#(2)当运行各种数据修复工具程序时。
#>>>>>>>>>>MySQL数据库在文件系统里如何表示
#
#MySQL服务器所管理的每一个数据库都有它自己的数据库目录。
#这个数据库目录其实是MySQL数据目录棕的一个子目录。
#MySQL数据表在文件系统里如何表示:
#MySQL支持以下集中针对不同数据表类型的处理程序:
#ISAM、MyISAM、MERGE、BOB、InnoDB和HEAP。
#
#
#MySQL中的每一个数据表在磁盘上至少被表示为一个文件,即存放着该数据比啊哦的结构定义的.frm文件。
#大部分数据表类型还有其他几个用来存放->数据行<-和->索引信息<-的文件。
#这些文件会随着数据表类型的不同而变化。
#
#MySQL中最原始的数据表类型------>ISAM类型<------了。
#在MySQL里,每个ISAM数据表用包含该数据表的数据库目录里
#的三个文件来代表。
#这些文件的基本名与数据表的名字相同,扩展名则分别表明了有关文件的用途。
#
#如:
#名字为mytb1的ISAM数据表被表示为以下三个文件:
mytb1.frm ----- 定义文件,存放着该数据表的格式(结果)定义。
mytb1.ISD ----- ISAM数据文件,存放着该数据表中的各个数据行的内容。
mytb1.ISM ----- ISAM索引文件,存放着该数据表中的全部索引的索引信息。
#MyISAM 数据表
#
#也要使用三个文件来代表一个数据表,这三个文件的扩展名分别是:
#.frm(结构定义文件) frm:framework n.框架,骨架;结构,架构。
#.MYD(数据文件) MY:MyISAM D:data
#.MYI(索引文件) MY:MyISAM I:index
#MERGE数据表
#MERGE数据表其实是一个逻辑结构。
#它代表着由一组结构完全相同的MyISAM数据表所构成的集合,
#有关的查询命令将把它当做一个大的数据表来对待。
#在数据库目录里,每个MERGE数据表将被表示为一个
#.frm文件
#.MRG文件
#.MRG文件其实就是一份由各MyISAM数据表的名单构成的MERGER数据表。
#BDB数据表
#BDB处理程序用两个文件来代表每个数据表。
#其一,是用来存储数据表结构定义的.frm
#其二,是用来存放数据表的数据和索引信息的.db文件。
InnoDB数据表
#上述几种数据表类型都是用多个文件来表示一个数据表的。
#InnoDB数据表与他们有所不同。
#与一个给定InnoDB数据表直接对应的文件只有一个,即数据表的.frm结构定义文件,
#这个文件存放在包含着数据表的数据库目录里。
#所有的InnoDB数据表的数据和索引都被放到同一个专用的空间同一管理。
#一般来说,这个表空间本身将被表示为MySQL目录的一个或者多个大文件。
#构成表空间的这些文件将形成一个在逻辑上连续不断的存储区域,表空间
#的总长度等于各组成文件的长度之和。
#HEAP数据表
#HEAP数据表是创建在----->内存<---中的数据表。因为MySQL服务器把HEAP数据表的数据和索引
#都存放在内存中,而不是存放在硬盘上,所以除相应的.frm文件外,HEAP数据表在文件系统里
#根本没有相应的代表文件。
#>>>>>>>SQL语句如何映射为数据表文件操作?
#每一种数据表类型都要使用一个.frm文件来保存数据表的结构定义。
#有些数据库系统使用一个注册表来记录某数据库里的所有数据表,但MySQL没有这样做
#因为,系统不需要这样设置,MySQL数据目录的层次结构已经把"注册表"隐藏在其中了
#创建数据表
#无论哪种数据表类型,MySQL服务器都将创建一个.frm文件
#来保存数据表的结构定义的内部编码。
#MySQL服务器会根据指定数据表的具体类型创建出其他必要的文件。
#更新数据表
#当发出一条ALTER TABLE tb1_name(CREATE INDEX 和DROP INDEX) 语句时,MySQL服务器
#将对有关数据表的.frm文件重新进行编码,以反应出这条语句所表明的结构性变化。
#删除数据表
#DROP TABLE语句是通过删除代表该数据表的各种有关文件而实现的。
#丢弃一个InnoDB数据表将使数据表在InnoDB表空间里占用的空间被标注为"未使用"
##注意##
# 对于InnoDB或HEAP数据表,因为他们的某些组成部分在文件系统里没有实体性的文件代表。
#所以,针对这两种数据表类型的DROP TABLE 语句没有等效的文件系统级命令。
#
# 例如,InnoDB数据表在文件系统里只有一个相应的.frm文件,用文件系统级命令删除这个文件将使
#该数据表在InnoDB表空间数据和索引成为"流离失所的孤儿"。
#>>>>>>>>>>>>操作系统对数据库和数据表命名的限制
#MySQL对数据库和数据表的命名有自己的一套命名规则,下面是命名的几个
#要点:
#(1)名字
未完,待续。。。