MySQL技术内幕之一:使用SQL管理数据


1 字符集支持
可以分别设置库、表、字段的字符集及排序方式
create database db_name character set charset collate collation;
create table tb_name (...) character set charset collate collation;
name char(10) character set charset collate collation;

如果没有进行显式的设置,则上一级的设置将应用到下一级的设置上。
可以使用show charset/collation来查看当前支持的字符集与排序方式。

2 存储引擎
show engines 用来查看当前支持的存储引擎列表。
对于各个引擎,每创建一个数据库,都会在data目录下创建一个目录,每在数据库中创建一个表,都会在对应目录下,创建库表及数据文件。各引擎都会创建tbname.frm的表定义文件,随着引擎的不同,创建相应的数据文件及索引文件。MyISAM创建t.MYD 和 t.MYI,INNODB创建t.ibd文件。

MyISAM和Innodb的库文件都是可移植的,只要两台服务器的硬件特性相同,就可以直接复制数据文件。前提是当前数据库无数据更新,没有信息在日志文件里。


2 创建表 
2.1 创建分区表

create table log_partition
{...}
partition by range(year(dt))
(
	partition p0 values less than (2005),
	partition p1 values less than (2006),
	partition p2 values less than (2007),
	partition p0 values less than MAXVALUE
);

2.2 创建Fedrated表
本类型的表用于访问远程的数据表,可以进行CRUD。只需要使用和远程相同的表定义,最后增加访问远程的信息即可。
create table tb_name 
(...) 
engine = federated
connection = 'mysql://user:pass@host/db/table';

为了避免可以查看表定义的人能看到你的用户名和密码,可以先创建一个存储信息的服务,然后在connection中使用它。
create server serv_name
foreign data wrapper mysql
options (user 'user',passoword 'pass',host 'host',database 'db');

connection = 'serv_name/tb_name'

2.3 创建Merger表
Merger存储引擎可以将多张MyISAM表合并成一张表,前提是这些表具有相同的定义。通常用于合并分库出来的多张子表的数据。
create table tb_name
(...)
engine='merge' union (tb1,tb2,tb3 ...)

2.4 在已有数据上创建表
方法1
create table tb_name like tb_name_orign;
insert into tb_name select * from tb_name;

这样先创建了一个和原始表结构完全一样的表,包括索引等,然后将数据从其他表中导入。

方法2

create table tb_name select * from tb_orign where ...;

如果不需要完全一样的表定义,则可以在创建表时,同时导入数据,表的字段类型将取决于选择出来的字段的类型,我们也可以使用CAST来转换这个类型,或者对字段的类型进行重新的定义。例如

create table mytbl (id int ,ts time, value decimal) 
select 1 as id ,cast(curtime() as time) as ts, cast(PI() as decimal) as d;

2.5 临时表
对于连接上创建的临时表,在连接断开后,会自动删除。若创建的临时表和系统中已经有的表重名,则其会隐藏原有表,当表在删除后,原来的表才能看到。
create temporary table tb_name ...;
drop temporary table tb_name;

3 删除表
Drop [temporary] table [if exists] tb_name;

4 创建索引
索引的类型有唯一索引、非唯一索引、全文索引、SPATIAL索引、HASH索引。
不同的引擎支持的索引特性亦不相同,MyISAM支持FULLTEXT,而Innodb则不支持。

索引可以在创建时添加,索引的类型有index/unique/primary key/fulltext/spatial
create table tb_name 
(   ... 
   index_type idx_name [using btree](column(n)) ...
)

也可以在运行时修改表来添加。
alter table tb_name add Index_type index_name (column(n) ...);

或使用create index语句创建
create index_type index idx_name on tb_name (column ...);

在对列创建前缀索引时,对于字符串为前N个字符,对于其他类型为前N个字节。在有些时候只有创建前缀索引,如blob/text类型的数据列,以及单个列或联合索引的总长度超这存储引擎所允许的最大索引长度时。

5 删除索引
drop index idx_name on tbl_name;
alter table tbl_name drop inx_name;
//删除主键
drop index primary on tbl_name;
alter table tbl_name drop primary key;

6 修改表

修改字段类型 

alter table tbl_name modify col type...;
alter table tbl_name change old new_col type...;

修改表引擎 

alter table tb_name engine = 'new_engine';

修改表名

alter table db.tbl_name rename to db.new_name;
rename table db.tbl_name to db.new_name;  //当表名位于不同数据库时,将把数据复制到目的库表

7 查看信息

7.1 show语句
SHOW AUTHORS
SHOW CHARACTER SET [like_or_where]
SHOW COLLATION [like_or_where]
SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [like_or_where]


SHOW CREATE DATABASE db_name
SHOW CREATE EVENT event_name
SHOW CREATE FUNCTION funcname
SHOW CREATE PROCEDURE procname
SHOW CREATE TABLE tbl_name
SHOW CREATE TRIGGER trigger_name
SHOW CREATE VIEW view_name


SHOW DATABASES [like_or_where]
SHOW ENGINE engine_name {STATUS | MUTEX}
SHOW [STORAGE] ENGINES
SHOW ERRORS [LIMIT [offset,] row_count]
SHOW [FULL] EVENTS
SHOW FUNCTION CODE sp_name
SHOW FUNCTION STATUS [like_or_where]
SHOW GRANTS FOR user
SHOW INDEX FROM tbl_name [FROM db_name]
SHOW INNODB STATUS
SHOW OPEN TABLES [FROM db_name] [like_or_where]
SHOW PLUGINS
SHOW PROCEDURE CODE sp_name
SHOW PROCEDURE STATUS [like_or_where]
SHOW PRIVILEGES
SHOW [FULL] PROCESSLIST
SHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n]
SHOW PROFILES
SHOW SCHEDULER STATUS
SHOW [GLOBAL | SESSION] STATUS [like_or_where]
SHOW TABLE STATUS [FROM db_name] [like_or_where]
SHOW TABLES [FROM db_name] [like_or_where]
SHOW TRIGGERS [FROM db_name] [like_or_where]
SHOW [GLOBAL | SESSION] VARIABLES [like_or_where]
SHOW WARNINGS [LIMIT [offset,] row_count]

7.2 information_scheme
此库中的各个表记录了相关的信息,可以直接查询,并且其提供了更好的移植性。

7.3 mysqlshow
可以在命令行下使用来获取相关的信息,可以查看命令行帮助。

8 联结查询
8.1 内联结

inner join / cross join /join 有着类似的作用,只连接满足条件的行。条件可以用on/where给出;如果两个表的字段名相同,可以使用using (column)子句。

8.2 外联结
left/right outer join 
左/右联结通常用于查找不在某个表中的结果。

9 子查询
9.1 子查询与关系操作符


关系运算符可以和标题子查询配合使用:子查询返回一个值,主查询中使用这个值作为检索条件。
例如对于学生表和成绩表,需要查Jobs的成绩
select * from score where stuent_id = (select stuent_id from student where name="Jobs" limit 1);

有时候需要在子查询中使用聚合函数来解决,例如想找到年龄最小的学生。
select * from student where age = (select min(age) from student);

如果子查询返回一个数据行,则可以用一个数据行构造器把一行数据与子查询结果进行比较。
select * from tbl where (col1 ,col2 ) = (select col11 ,col22 from tbl2 where ...);

9.2 子查询与IN/NOT IN 
IN和NOT IN用于测试给定的比较值是否出现在一个特定的集合里。Exists和NOT EXISTS具有类似的作用。
例如希望找到所有女学生的成绩信息
select * from score where student_id in (select student_id from student where sexy = "FEMALE");

9.3 ALL/ANY
用于测试比较值是否与子查询返回的全部或部分值匹配。
例如查找年龄大于所有老师的学生信息
select * from student where student.age > all (select age from teacher);

9.4 与主查询有关的查询
上面列出的这些查询,子查询并不使用主查询中的字段。还有一些子查询,依赖与主查询。
例如,要查看所有缺勤学生的信息
select * from student where exists (select * from absence where absence.student_id = student.student_id);

9.5 作为FROM子句的子查询
子查询返回一个表,可以和普通表一样使用,但需要提供别名以供引用。
select s.name from (select * from student where sexy = "Female") as s;

10 Union
利用union可将多个查询的结果合并在一起创建一个结果集。
select f1 from t1 union select f2 from t2;

不同的结果集只要列数相同,不需要区分列名和列的类型,都可以合并在一起。但结果集的列名来自第一个SELECT语句里数据列的名字。
默认情况下,UNION会从结果集中剔除重复的数据行,其等同于UNION DISTINCT,如果不需要排重,则使用UNION ALL。

如果需要对合并的结果进行排序,则需要对每个SELECT加上括号,并在最后一个子句后加ORDER BY。Limit的使用是类似的。order by 和 limit也可以放在各括号内部,但与放在外面的作用完全不同。
(select f1 from t1) union (select f2 from t2) order by f1;

10 视图
创建视图
create view vname [(col,col,...)] as select col1,col2 ... from tbl;

视图创建后,其上的查询操作和普通表是一样的。


11 涉及多个数据表的删除与更新

单个库上的删除和更新形式如下:
delete from tbl where cond..
update tbl set col = ? where ...

对于需要删除联结所查到的数据
删除tbl1中的行
delete tbl1 from tbl1 join tbl2 where ...

删除两个表中的行
delete tbl1,tbl2 from tbl1 join tbl2 where ...

更新符合条件的行
update tbl1,tbl2 set tbl.col = ? where ...

12 事务
12.1 启动事务的方法

方法1
start transaction;
CURD...
commit / rollback;

方法2
set autocommit = 0
CRUD...
commit/rollback
set autocommit = 1

12.2 保存点
CRUD...
saveporint sp_name
...
rollback to savepotint sp_name

12.3 事务的隔离级别
目前支持4种隔离级别,如下表所示:
隔离解别 脏读 不可重复读 幻读
Read Uncommitted Y Y Y
Read Committed N Y Y
Repeatable Read (default) N N Y
Serializable N N N

set [global|session] transaction isolation level lev;

12.4 事务的其他解决方案
以下两种方案可以在一定程度上解决事务问题,但并不完善,如不支持失败回滚。
1 锁表
lock table tbl_name [read|write]
CRUD
unlock table tbl_name
2 语句合并
如果多条语句可以合并在一条语句里执行,则不会出现并发的干扰问题。

13 引用完整性
引用完整性也称为外键约束,使用它可以对表之间的数据行施加严格的约束,是一种有效的错误防范机制。
13.1 创建外键
... foreign key [fk_name] (columns) 
    references tbl_name (columns)
    [on delete action]
    [on update action]

 action有以下几种
 no action          父表变化时,子表不变化
 restrict           同上
 cascade            随父表的变化级联变化
 set null/default   置为空和默认值

14 全文索引
全文索引只能建立在MYISAM引擎之上,且列的类型只能是char/varchar/text。
match(column,..) against(pattern,mode) 函数用来在指定的列上进行全文的索引查找。
mode有三种
in natural language mode
in boolean mode
with query expansion 

15 杂项

在设计数据库之前,应该对存放的数据做深入的思考,以避免在存入数据之后再做调整。

SQL语句中除了库名/表名外,字段、条件比较通常都是不区分大小写的。库名、表名随所在的操作系统而不同。在Win上不区分大小写,而在Linux上区分大小写。

随机查询的方法 select * from table order by rand() limit N;

变量可以在sql的查询上下文中起作用 select @var:= age ,name from student where id = 1; select @val;

sql_mode可以设置MySQL所处的模式,可以在启动时--sql-mode="",也可运行时set GLOBAL sql_mode=""


你可能感兴趣的:(MySQL技术内幕之一:使用SQL管理数据)