MySQL学习手册--基础篇

对于很多mysql的初学者,或者平时工作接触数据库较少的朋友,可能对mysql的概念较为生疏,这里总结了一篇mysql的基本语法手册,可以满足于基础sql语句的查询。后续有时间会更新更加高级,旨在编写优质sql语句的高级教程,敬请期待。PS:本文属于隔壁小王的原创,若觉得有用,可转勿盗,谢谢看官对在下劳动成果的珍惜和支持。

1.MySql基本语句

链接数据库

mysql -h localhost -u username -p password

不建议写成:mysql -uroot -p111,这样容易被其他人发现你的密码。

连接成功后,首先面对的是库,库有一个或多个。

选库语句

use 库名

查库语句

show databases

选完库后面对的是表。

创建数据库语句

create database 数据库名[charset 字符集]

删除数据库语句

drop database 数据库名

修改数据库名语句

mysql中,表和列可以改名,database不能改名

查表语句

show tables

删表语句

drop table 表名

表更名语句

rename table old_name to new_name

清空表语句

truncate 表名

truncate相当于删除表再重建同结构的表,delete是从删除数据行层面来操作的。

 

2.增删改查之insert

insert into class

(name1, name2, name3...)

vlaues

(value1, value2, value3...);

 

3.增删改查之update、delete

update 表名

set

gender='女',

compand='千度'

where expr

delete from 表名

where expr

注意:不能只删除某一行里的某个项的值,其实这只是改,只能update。

 

4.select基本语法

select name1,name2,name3 from 表名 where expr

 

5.MySql的建表及列类型

建表过程,就是一个声明列的过程。

不同的列类型所占据的空间和效率是不同的。

MySql三大列类型:

数值型

整型:

Tinyint(M)

占据1个字节

Smallint(M)

占据2个字节

Mediumint(M)

占据3个字节

Int(M)

占据4个字节

bigint(M)

占据8个字节

存储参数:

(M):列宽度,必须和zerofill配合才有意义

unsigned:表示无符号,可以影响存储的范围

zerofill:表示不够位数用零填充,注意带0填充的一定是unsigned

例:

alter table 表名 add sno smallint(5) zerofill not null default 0;

浮点型、定点型:

float(M, D):

M:精度,代表总位数

D:标度,代表小数位

float存储大小是固定的。

decimal(M, D):

把整数部分和小数部分分开存储,比float精确。

M:精度,代表总位数

D:标度,代表小数位

decimal可以根据需要的大小来设置字符的长度。

字符型

char(M):

定长字符串,查询速度较快。对于定长n,无论够不够指定长度,实际都会占据n个长度,如

果不够n个长度,用空格在末尾补至n个长度,但取出的时候会将右侧空格全部删除,如果原

记录末尾有空格,可能会造成困扰。

varchar(M):

变长字符串,在内存中,数据前会有1-2字节来记录内容的长度,也就是说即使varchar中

内容为空,存储空间也是有前缀的值的。在实际存储中,varchar占用的空间小于等于指定的

空间存储效率较高。

char和varchar的宽度参数M指的是字符数不是字节数,因此M=6就是可以存储6个汉字。

text:

文本类型,可以存储比较大的文本段,搜索速度较慢。除此以外,还有mediumtest等更加长

的存储类型,可以根据需要决定。声明text时不能声明默认值。

blob:

二进制类型,用来存储图像、音频等信息。也不能声明默认值。意义:2进制,0-255都有空

能出现,因此防止因为字符集的问题,导致信息丢失。

时期时间类型

date:

YYYY-MM-DD

范围是1000-01-01到9999-12-31

如果输入错误或者没有输入,年份会设置为全0。

time:

hh:mm:ss

datetime/timestamp:

YYYY-MM-DD HH:MM:SS

可以使用当前时间,自动插入:

ts timestamp default CURRENT_TIMESTAMP

year:

YYYY

 

6.表修改语法之列的增删改

增加列

Alter table 表名 add 列名称 列类型 列参数;

Alter table 表名 add 列名称 列类型 列参数 after 指定列名;【把新列加在指定某列的后面】

Alter table 表名 add 列名称 列类型 列参数 first;【把新列加在最前的位置】

删除列

Alter table 表名 drop 列名称;

修改列类型

Alter table 表名 modify 列名称 新列类型 新列参数;

注意:modify不能修改列名。

修改列名及列类型

Alter table 表名称 change 旧列名 新列名 新类型 新参数;

注意:如果列类型改变后,导致数据存储不下,数据将会丢失,或者在mysql的strict_mode下,将修改不了。

 

7.sql查询表达式

查表具有5种子句,变化很多,新手与老手写查数据,效率会相差很多。这5种子句分别为:

where 条件查询

group by 分组

having 筛选

order by 排序

limit 限制结果条数

where:

select 列名/* from 表名 where 表达式

相关运算符:

<

例:略

>

例:略

!= / <>

例:select goods_id,cat_id, goods_name from goods where cat_id != 3;

注意:not in 的效率不如 !=

<=

例:略

>=

例:略

=

例:略

in【在某集合内】

例:select * from goods where cat_id in (4, 11);【cat_id在4和11集合中满足之一】

between【在某范围内】

例:select * from goods where price between 100 and 500;

not / !

例:select * from goods where cat_id not in (3, 11);

or / ||

例:略

and / &&

例:select * from goods where cat_id != 3 and cat_id != 11;

组合示例:

select * from goods where price >= 1 and price <= 3 or price >= 40 and price <= 50;

注意:and的优先级比or要高。

select * from goods where cat_id = 3 and (price<100 or price>300) and click_count >= 5;

模糊查询:

select * from goods where goods_name like "诺基亚%";【%表示匹配任意字符串】

update goods set goods_name = 'HTC' where goods_name like '诺基亚%';

select * from goods where goods_name like "诺基亚N__";【_表示任意一个字符】

统计函数

select max(列名称) from 表名;【查询某列中的最大值】

select min(列名称) from 表名;【查询某列中的最小值】

select sum(列名称) from 表名;【查询某列数值的总和】

select avg(列名称) from 表名;【查询某列数值的平均值】

select count(*) from 表名;【查询某表中存储记录的数量】

注意:select count(*) from 表名,查询的是绝对的行数,哪怕某一行所有字段全部为null,也计算在内。而select count(列名) from 表名,查询的是该列不为null的所有行的行数。

用count(*)和count(1)谁好呢?

其实对于myisam引擎的表,没有区别的。这种引擎内部有一计数器在维护着行数。Innodb的表用count(*)直接读行数,效率很低,因为真的要数一遍。

group

将查询到的信息按照预计的分组进行查询。

select ??? from 表名 group by 列名称

having

select a, b, c, (a-b) as discount from goods where discount > 200;

这是错误的,因为where是针对表进行的操作,表中没有discount这一列。

如果需要对查出的结果进行筛选,就需要使用having对结果进行再次筛选。

例:select cat_id, sum(goods_number*shop_price ) as zhk from goods group by cat_id having zhk > 20000;

order by

用于结果集的排序,排序是针对最终结果集的,因此order by要放在where/group/having等的后面,顺序不能颠倒。排序可以多字段。

例:select goods_id, goods_name, shop_price from goods where cat_id=4 order by shop_price desc;【desc是降序排列;asc是升序排列】

limit [offset], N

限制条目。offset是偏移量,表示需要跳过的条目数,默认为0,如果offset为2,则表示跳过前两条条目从第三条开始取;N是需要取出的条目数。

例:select goods_id, cat_id, goods_name, shop_price from goods where cat_id=3 order by shop_price asc limit 10;【表示控制条目数为10】

 

8.子查询

where型子查询

把内层查询的结果作为外层查询的条件。

例:select goods_id, goods_name where goods_id = (select max(goods_id) from goods)

from型子查询

注意:查询结果集可以当做表看,因此可以基于此进行再次查询。

from型子查询会将内层的查询结果,当成一张临时表,供外层sql再次查询。

例:select * from (select goods_id, cat_id, goods_name from goods order by cat_id asc, goods_id desc) as tmp group by cat_id;

注意:gruop by是取各个种类中的第一条记录显示。

exists型子查询

把外层sql的结果,拿到内层sql去测试,如果内层成立,则该行取出。

例:select cat_id, cat_name from category where exists (select * from goods where goods.cat_id = category.cat_id);

 

9.奇怪的NULL

建表时,列后面的not null default ' '/0,表示让这个列不为NULL,如果这个列确实没有值,也没有默认值,也不会为NULL。

注意:NULL有特有的运算符,is NULL和is not NULL。

为什么建表时设置为not NULL?

NULL是空类型,比较时只能用专门的is NULL和is not NULL,遇到其他运算符,一律返回NULL,不便于比较。效率不高,影响索引的效率。因此在建表时,声明not null default ''/0。

注意:在mysql中,NULL和''是有区别的,''还是个字符串,只是长度为0。

 

10.左连接与右连接查询

集合(set)的相关知识

1.元素唯一性,即内部元素没有重复的。

2.集合的运算:求交集、并集、笛卡尔积(集合的元素做两两组合)。

表与集合的关系

一张表就是一个集合

每一行就是一个元素

在数据库的操作上,如何操作表,完成集合相乘的效果即集合的笛卡尔积?

直接用','隔开表名,查询即可。

例:select * from test1, test2;

从行的角度看,就是两表每行两两组合;从列的角度看,就是两表列名的相加。

例:select goods_id, goods_name, goods_number, shop_price, cat_name from goods, category where goods.cat_id = category.cat_id;

两表全相乘的方法效率是较低的,尤其在行数非常多的时候。

注意:如果在多表联查时,如果某一列,在2张或2张以上的表都有,则在列名前需要指定表名。

左连接

假设A表在左不动,B表在A表的右边滑动,A表与B表通过一个关系来筛选B表的行。

语法:

A left join B on 条件;当条件为真,则B表对应的行取出,结果集一样可以看成一张表,A、B表的列均可以查。

例:select goods_id, goods_name, goods_number, shop_price, cat_name from goods left join category on goods.cat_id = category.cat_id;

若在B表中查不出满足结果的条目,则在查询结果中,用NULL补齐。

注意:左连接查询比全相乘的效率有大幅度的提高。全相乘不仅数据量大,而且由于产生的是临时表,因此没有索引。

左连接与右连接的区别

a left join b并不是说a表就一定在左边,只是说在查询数据时以a表为准。

左右连接是可以互换的,A left join B,就等价于B right join A。本质上讲,两者是一回事。既然左右连接可以互换,尽量用左连接,处于移植时兼容性方面的考虑。

内连接

例:select * from A inner join B on 条件

从集合的角度看:

A inner join B和A left/right join B的关系:内连接是左右连接的交集,而外连接是左右连接的并集(Mysql中是不支持外连接的)。

 

11.UNION查询

语法:

sql1 union sql2;

用于连接查询结果;union是结果集,不区分来自那张表。

注意:如果取自于两张表的列名(包括类型)不同,也是可以查询的,但是结果中的列会以前一个sql中的列名为准。当然也可以使用as构建别名的方式使列名保持一致。

注意:当两个sql的字段数不一样时,不能使用union进行联合查询。

注意:当union查出的结果存在一样选项时,会自动去重;如果不想去重,可以使用union all来进行sql连接。

 

12.常用Mysql的数学函数

数学函数

abs(x) 绝对值函数

bin(x) 返回x的二进制(oct返回八进制,hex返回十六进制)

ceiling(x) 返回大于x的最小整数值

exp(x) 返回e的x次方

floor(x) 返回小于x的最大整数值

greatest(x1, x2, ..., xn) 返回集合中最大的值

least(x1, x2, ..., xn) 返回集合中最小的值

ln(x) 返回x的自然对数

log(x, y) 返回x的以y为底的对数

mod(x, y) 返回x/y的模

pi() 返回pi的值

rand() 返回0到1内的随机数,可以通过提供一个参数使rand()随机数生成器生成一个指定的值

round(x, y) 返回参数x的四舍五入的有y位小数的值

sign(x) 返回代表数字x的符号的值

sqrt(x) 返回一个数的平方根

truncate(x, y) 返回数字x截短为y位小数的结果

聚合函数

avg(col) 返回指定列的平均值

count(col) 返回指定列中非NULL值的个数

max(col) 返回指定列的最大值

min(col) 返回指定列的最小值

sum(col) 返回指定列的所有值之和

group_concat(col) 返回由属于一组的列值连接组合而成的结果

字符串函数

ascii(col) 返回字符的ascii码值

bit_length(str) 返回字符串的比特长度

concat(s1, s2, ... sn) 将所有元素连接成字符串

concat_ws(sep, s1, s2, ... sn) 将s1-sn连接成字符串并用sep字符间隔

insert(str, x, y, instr) 将字符串str从第x位置开始,y个字符长的子串替换为字符串instr,返回结果

find_in_set(str, list) 分析逗号分隔的list列表,如果发现str,返回str在list中的位置

lcase(str)/lower(str) 返回将字符串str中所有字符改变为小写后的结果

left(str, x) 返回字符创str中最左边的x个字符

length(s) 返回字符串str中的字符数

ltrim(str) 从字符串str中切掉开头的空格

position(substr, str) 返回子串substr在字符串str中第一次出现的位置

quote(str) 用反斜杠转义str中的单引号

repeat(str, srchstr, rplcstr) 返回字符串str重复x次的结果

reverse(str) 返回颠倒str的结果

right(str, x) 返回字符串str最右边的x个字符

rtrim(str) 返回字符串str尾部的空格

strcmp(s1, s2) 比较字符串s1和s2

trim(str) 去除字符串首部和尾部的所有空格

ucase(str)/upper(str) 返回将字符串str中所有字符转变为大写后的结果

日期和时间函数

curdate()/current_date() 返回当前的日期

curtime()/current_time() 返回当前的时间

date_add(date, interval int keyword) 返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化),如:select date_add(current_date, interval 6 month)

date_format(date, fmt) 依照指定的fmt格式格式化日期date值

date_sub(date, interval int keyword) 返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化),如select date_sub(current_date, interval 6 month)

dayofweek(date) 返回date所代表的一星期中的第几天

dayofmonth(date) 返回date是一个月的第几天

dayofyear(date) 返回date是一年的第几天

dayname(date) 返回date的星期名

from_unixtime(ts, fmt) 根据指定的fmt格式,格式化unix时间戳ts

hour(time) 返回time的小时值

minute(time) 返回time的分钟值

month(date) 返回date的月份值

monthname(date) 返回date的月份名

now() 返回当前的时间和日期

quarter(date) 返回date在一年中的季度

week(date) 返回日期date为一年中的第几周

year(date) 返回日期date的年份

加密函数

aes_encrypt(str, key) 返回用秘钥key对字符串str利用高级加密标准算法加密后的结果,调用aes_encrypt的结果是一个二进制字符串,以blob类型存储

aes_decrypt(str, key) 返回用秘钥key对字符串str利用高级加密标准算法解密后的结果

decode(str, key) 使用key作为秘钥解密加密字符串str

encrypt(str, salt) 使用unixcrypt()函数,用关键词salt(一个可以唯一确定口令的字符串,就像钥匙一样)加密字符串str

encode(str, key) 使用key作为秘钥加密字符串str,调用encode()的结果是一个二进制字符串,它以blob类型存储

md5() 计算字符串str和md5的校验和

password(str) 返回字符串str的加密版本,这个加密过程是不可逆转的,和unix密码加密过程使用不同的算法

sha() 计算字符串str的安全散列算法(sha)校验和

控制流函数

case when[test1] then [result1]...else [default] end:如果testn是真,则返回resultn,否则返回default

case [test] when[val1] then [result]...else [default]end:如果test和valn相等,则返回resultn,否则返回default

if(test, t, f):如果test是真,返回t,否则返回f

格式化函数

date_format(date, fmt) 依照字符串fmt格式化日期date值

format(x, y) 把x格式化为以逗号隔开的数字序列,y是结果的小数位数

inet_aton(ip) 返回ip地址的数字表示

inet_ntoa(num) 返回数字所代表的ip地址

time_format(time, fmt) 依照字符串fmt格式化时间time值

类型转化函数

mysql提供了cast()函数,它可以把一个值转化为指定的数据类型。数据类型有:binary,char,date,time,datetime,signed,unsigned

示例:

select cast(now() as signed integer), curdate() + 0;

select 'f' = binary 'f', 'f' = cast('f' as binary);

系统信息函数

database() 返回当前数据库名

benchmark(count, expr) 将表达式expr重复运行count次

connection_id() 返回当前客户的连接id

found_rows() 返回最后一个

user()/system_user() 返回当前登陆的用户名

version() 返回mysql服务器的版本

 

13.视图 View

View是什么?View可以看成一张虚拟的表,是表通过某种运算得到的一个投影或者说是映射。因此,表的变化是会影响到视图的。

创建视图的语法

将查询结果命名为视图就可以了。即:

Create view 视图名

As

Sql语句

创建后show tables会多出一张临时视图表。

视图的作用

1.可以简化我们的查询,降低复杂sql语句的使用频率。

2.更精细的权限控制:若需要给对方提供一些数据查询权限,但是又不希望对方能够查看到整表的内容时,通过仅提供视图的权限即可。

3.数据多,分表时可以使用:若需要的数据可能来源于多个表时,可以通过union连接后,将多表的数据合并为一个视图。

表与视图数据变化时的相互影响问题

1.表的数据变化会影响到视图的数据变化

2.视图的数据在某种情况下也是可以影响表的数据的:要求视图的数据和表的数据一一对应(包括order by,limit,group by等,使用后均不是一一对应关系)。

注意:视图的定义会一直存在,但是不会占用空间,即该视图关联的查询语句是一直存在的;删除视图和删除表的方法是一样的,使用drop view xxx即可。

视图algorithm的概念

对于一些简单的视图,在发挥作用的过程中,并没有建立临时表,而只是把条件存起来,下次查询时,把条件合并起来直接查原表。具体是否建立临时表或是合并语句,都是由algorithm决定的。

algorithm有3种值:

1.merge:合并查询语句

2.temptable:临时表

3.undefined:未定义,由系统判断

如何指定algorithm选项:

create algorithm = 选项 view 视图名

as

sql语句

 

14.编码和字符集

字符集的基本知识

2进制编码到字符的映射就是字符集。

ascii码是最早的字符集,建立该字符集时,仅仅考虑到欧美的使用习惯,包括了键盘上的所有字符。一个ascii码占8位/1字节,但只使用了8位中低7位,最高位为0,共有128种组合。

包括中文的第一字符集叫GB2312,占两个字节。那么如何既能兼容ascii又能双字节表示中文呢?即GB2312每个字节8位编码完全不占用0-127的字节范围,使用其他范围内的编码作为汉字编码。因此,由于每个汉字两个字节中每个字节只能使用129-255这个范围内的编码,GB2312只能容纳6763个汉字。

为了提升编码的容量,新增了GBK字符集。GBK也是占用2个字节的编码,GBK的第二个字节,不再局限于129-255,小于127的也是可以用的。方法是:遇到某个字节大于128的,就再往后找一个字节,两个字节理解成中文。可以提供约20000多个汉字的编码。

注意:ANSI代表本地字符集,在中文操作系统中代表GBK,在日本就是JIS。

为了解决世界各国字符集的兼容问题,发布了终极大招--unicode(国际化字符集),unicode是一个世界通用的码表,全世界范围内的字符,统一分配一个标号,每个字符占4个字节。但是,unicode只是负责分配编号,而且每个编号占用4个字节,浪费较大,因此出现了专用于简化unicode编号的编码,其中最为出名的是UTF-8。UTF-8是不定长的,会根据unicode中编号的长短而进行调整。

Mysql字符集参数

在客户端与数据库之间,会存在一个单元,叫做连接器,连接器拥有自己的字符集。客户端的字符会先发给连接器,连接器会选择一种编码将其转换,临时存储;然后转换成服务器需要的编码并存储在服务器。

因此,在数据库转码过程中,一共需要3个参数:客户端发送的编码,连接器使用的编码,获取的返回数据的编码。

设置客户端编码类型:set character_set_client=gbk;

设置连接器编码类型:set character_set_connection=utf8;

设置返回值编码类型:set character_set_results=gbk;(注意:这是服务器返回值的编码类型,并不是服务器的存储类型)

注意:如果设置的编码类型和实际的输入编码类型不相同,则会报错,不允许插入或者丢失数据;同理,如果设置的编码类型和实际返回的编码类型不一致,则在显示数据时也会出现乱码。

如果3者都是GBK,可以用过简写:set names gbk来同时设置client,conn,results。

 

15.MYSQL的存储引擎及事务简介

引擎粗略的说,是mysql存储数据的方式。

主要引擎的特点:

最常用的是myisam和innodb两种。myisam速度快,但是在安全性上要远远逊色于innodb。

什么是事务

事务的四个特性:原子性、一致性、隔离性、持久性。

原子性:n步操作,逻辑上不可分割,即一套操作(包含若干子操作),要么都成功,要么都不成功,如果失败了则会执行回滚操作。

一致性:是指操作前后,值的变化逻辑上成立。

隔离性:事务结束前,每一步带来的影响他人是无法看到的。

持久性:事务一旦完成,无法撤销,只能再做一次“补偿性事务”。

注意:可以通过"start transaction"开启mysql的事务模式,具体详细操作可自行查阅。

猜你喜欢

转载自blog.csdn.net/BmwGaara/article/details/81490858