对表的增删改操作:
创建表:
create table student (
id int primary key auto_increment,
name varchar(10) character set utf8 not null,
sex char(2) default ‘M’,
constraint fk_student_score foreign key(id) references score(id)
) engine=InnoDB;
primary key :指定表的主键;
如果是指定单个主键,可直接在该字段后声明;
如果是指定多个主键,只能采用primary key (X,Y)的形式;
定义外键:
constraint fk_T2_T1 foreign key(t2_id) references T1(t1_id); //将T1表中的t1_id字段设置成为T2表的外键;
增加外键
alter table T2 orderitemds add constraint fk_T2_T1 foreign key(id) references T1(id); //将T1表中的t1_id字段设置成为T2表的外键;
auto_increment :让Mysql自动对该列增量;每个表只允许有一个auto_increment列,且必须被索引(以最大的数去递增),从而可将该列当作主键;
注:select last_insert_id():该语句可获得最后一个auto_increment的值;
default:为字段设置默认值;
character set …:指定编码格式,通常是为了让其能识别中文;
engine = …:指定mysql引擎;
常用的引擎类型:
InnoDB:可靠地事物处理引擎,但不支持全文检索;
MyISAM:性能极高的引擎,支持全文检索,但不支持事务处理;
MEMORY:功能同于MyISAM,但由于数据库在内存里,速度很快;适用于临时表;
注:新版Mysql默认引擎是InnoDB;
更新表:使用alter table语句
增加列:
alter table T add Tname varchar(20); //为T表增加一个名为Tname的列
删除列:一次只能删除一列;
alter table T drop column Tname; ///删除T表中名为Tname的列
删除表:使用Drop table语句
例:drop table T;
重命名表:使用rename table语句
例:rename table T1 to t1, T2 to t2, T3 to t3;
对表中数据的查询操作:
SQL语句格式:
select
from
where
group by
having
order by
limit
去重:distinct
例:select distinct * from T
数据分组: group by , having , rollup
group by :进行分组; 如果分组中具有null值,则null将作为一个分组返回;
having :过滤分组; 它支持所有where中的操作符;
注:可以使用rollup关键字来显示出分组前所有的数据;例:group by prod_id with rollup;
除聚集计算语句外,select语句中使用的每个选择列或表达式列,都必须在group by子句中给出;
排序:order by
select * from XXX order byXXX (desc(降序)/asc(升序))
限制检索行数:limit, limit offset
例: select * from XXX limit 0,2 (从第0行开始,取2行)
等价于 select * from xxx limit 1 offset 2(从第2行开始取1行)
起别名:
可以为表或列起别名;
有两种形式:
(1)table1 t1
(2)table1 as t1
where语句中注意的问题:
注:and比or的优先级高
‘<>’ 等价于 ‘!=’f
between A and B:包括边界
is null
in :指定条件范围 取值时用","分隔,相当于or的作用,但比or操作符执行的更快;并且可以包含select语句;
not
like: %:任意字符(null除外) _:单个字符
注:用通配符过滤:花费时间较长,避免过度使用;可以考虑用正则表达式;
mysql支持部分正则表达式,可以匹配基本的字符和字符串;
形如: select * from products where prod_name regexp ‘XXXX’
例:检索到prod_name包含文本1000的所有行;
select * from products where prod_name regexp ‘1000’
mysql的预定义字符集:
[:digit:]---任意的数字(同[0-9])
[:lower:]---任意小写字母(同[a-z])
[:upper:]---任意大写字母(同[A-Z])
[:alpha:]---任意字符(同[a-zA-Z])
[:alnum:]---任意数字和字母(同[a-zA-Z0-9])
[:blank:]---空格和制表符(同[\\t])
[:space:]---任意的空白字符,包括空格;(同[\\f\\n\\r\\t\\v])
例:-- 表示检索出现连在一起的任意4位数字和小写字母的所有行
select prod_name
from products
where prod_name regexp ‘[[:digit:][:lower:]]{4}’
like 和 regexp的区别:
like是匹配这个列,如果被匹配的文本仅在列值中出现,like并不会找到它,相应的行将不会返回(使用通配符除外)。
regexp是匹配列值,如果被匹配的文本在列值中出现,regexp会找到它,相应的行将会返回(可以用定位符号^和$,让regexp匹配这个列,而非列值)。
当一些操作,不需要从表上选择数据时,mysql中提供了一个内置的特殊的表dual(空表),来方便操作;
mysql中提供的一些常用函数:
聚集函数(汇总函数):
max(), min(), sum(), avg(), count();
注:它们都忽略列值为null的行;
它们都可以和distinct关键字联合使用;例如:count(distinct prod_price)
文本处理函数:
concat( , ) :用来拼接字段
例:
select concat(vend_name, vend_country)
from vendors
trim( , ):去掉字段中值中的所有空格
rtrim( , ):去掉字段中值右边的所有空格
ltrim( , ):去掉字段中值左边的所有空格
soundex( ):能对串进行发音比较;可将任何文本串转化为描述其语音表示的字母数字;
例如:soundex(cust_contact) = soundex(‘Y.Lie’) //可找到表中cust_contact=Y Lee的这条记录;
日期和时间处理函数:
Now() :返回当前日期和时间
CurData():返回当前日期
Curtime():返回当前时间
Year(D):返回回一个日期D中的年份部分 类似有:Month(D)……
DateOfWeek(D):返回对于一个日期D,返回对应的星期几
DateDiff(D1,D2):计算D1到D2两个日期之差
Date_Format(D,F):按照表示式F的要求显示日期D;
AddDate(D,n):计算起始日期D加上n天的日期;
SubDate(D,n): 计算起始日期D减去n天的日期;
子查询:嵌套在其他查询中的查询
使用子查询的两种方式:
1.一般与in操作符结合使用,但也可以用于测试等不等于;
2.用子查询去创建计算字段;将子查询整体作为一个计算字段使用;
注:一切的问题都可以采用子查询写出;
连接:两个表之间字段取交集
等值连接:where …=…
例: from T1,T2 where T1.p_id=T2.p_id;
内部连接:inner join…on…
例:from T1 inner join T2 on T1.p_id =T2.p_id;
注:推荐用inner join on子句,它的性能好于where.
外连接:left outer join … on… 、right outer join …on…
左外连接:得到的内容为 两者的公共交集+ 左边的表中非关联部分
右外连接:得到的内容为 两者的公共交集+ 右边的表中非关联部分
例:from T1 left outer join T2 on T1.p_id =T2.p_id;
自连接:速度很好,推荐使用
可以通过子查询来实现,
select
from t
where t_id = { }
也可以通过不同的别名来实现;
select
from t as t1, t as t2
where t1_id = t2_id
组合查询:多个查询并将结果作为一个查询结果集返回,使用union操作字
需要使用组合查询的情况:
- 在单个查询中从不同的表返回类似结构的数据;
- 对单个表执行多个查询,按单个查询返回数据;
在各select语句之间放上关键字union,每个查询必须包含相同的列、表达式或聚集函数。
它会从查询结果中自动去除重复的行,如果需要不取消行,可使用union all;
注:使用uinon可以替代where,能够用较简单的方式去完成由where非常复杂才得到的结果;
范式:
第一范式(1NF):确保每列保持原子性
第二范式(2NF):符合1NF,并且,确保表中的每列都和主键相关
第三范式(3NF):符合2NF,并且,确保每列都和主键列直接相关,而不是间接相关;
BC范式(BCNF):符合3NF,并且,主属性不依赖于主属性
第四范式:要求把同一表内的多对多关系删除。
第五范式:从最终结构重新建立原始结构。
对表中数据的增删改操作:
注:T代表某个表
向表中增加行:有四种形式;
第一种形式:插入完整行,必须按默认顺序为每个列提供一个值;
insert into T
values(……)
注:若该列没有值则用null表示;
第二种形式:插入部分行,可按自己指定的顺序为每个列赋值;
insert into T(……)
values(……)
第三种形式:插入多行;
insert into T(……)
values(……) ;
insert into T(……)
values(……) ;
或
(Mysql特有的)
insert into T(……)
values(……) ,(……);
第四种形式:插入部分某些查询结果;
insert into T(……)
select ……
修改表中的数据:
update T set ……
例:
//修改编号为1002顾客的顾客名和顾客电话
update customers set cust_name=’Tom’, cust_tele=”10086” where cust_id=1002;
//删除编号为1001顾客的邮件地址
updata customers set cust_email=null where cust_id=1001;
从表中删除行:
delete from T where……
注:也可以用truncate table语句删除表中所有数据,它的速度更快,相当于删除原表,在建一个空表;
视图:即:虚拟的表,它只是一个SQL查询,不包含任何数据;
查看创建视图的语句:show create view <视图名称>
创建视图:
create view <视图名称>
as
select查询语句
删除视图:drop view <视图名称>
注: 通常视图都是和select语句使用的,
虽然视图是可更新的,即可以对视图使用insert,update,delete;但其实更新一个视图,实际上是更新其基表,是对基表的增删改,所以并不推荐这样使用;
优点:可重用SQL语句;
化简了复杂的SQL操作
使用的部分表,而不是整个表;
能保护数据;
可更改数据格式和表示;
缺点:视图会影响性能,因此使用大量视图时要慎重;
Mysql高级语言
有三种形式的注释:
行注释: #XXX -- XXX(之间至少有一个空格符)
块注释: /* XXX */
变量:局部变量用@开头;全局变量用@@开头;
声明变量: 用declare语句 , 变量不能加@符号;使用游标是只能用declare定义
daclare var_name[,……] type (default value)
注:declare语句必须用在begin……end语句块中且必须在最前面;变量名不区分大小写; mysql中是一般可以不用事先申明变量,可直接用set或select赋值,
变量赋值:;使用变量时用“@var_name”表示即可; 打印时只能用以下的方式;
用set语句直接赋值:可以用”=”或”:=”赋值
set @var_name=value[,…] 或set @var_name:=value[,…]
用select语句查询赋值:只能用”=”赋值,因为在select语句中=被看作比较运算符;
①select @var_name:=value[,…]
②select @var_name[,…]
from……
where……
③select @col_name[,…] into var_name[,…] #把选定的列赋值给变量
from ……where……
注:直接用set/select语句定义的变量必须加@符号,除非该变量已经被declare声明过;
例://通过连续赋值,加起来赋为t1,并把每个值都打印出来;
select @t1:=(@t2=1)+@t3:=4,@t1,@t2,@t3; from…where…
变量的分类:
mysql手册将变量分系统变量和用户变量
但实际中常有以下几种:
局部变量(作用域是当前语句块,即:begin……end):必须用declare声明
用户变量(作用域是当前整个连接):无需使用declare申明,可用select或set会话变量:(作用域是当前整个连接):
定义:
set @var_name=value;
set session @var_name=value;
set @@session var_name=value;
查看:
select @@var_name;
select @@session.var_name;
show session variables like “%var%”
全局变量(作用域是整个数据库):
set global @@var_name=value;
查看:
select @@global.var_name;
show global variables like “%var%”
存储过程中的控制语句:
if(expr1, expr2, expr3):相当于java中的三目运算符,
expr1是true,则返回expr2,否则返回expr3;
ifnull(expr1, expr2):
若expr1非null,返回本身;否则返回expr2;
nullif(expr1,expr2):
若两者相等,返回null,否则返回expr1;
分支语句之if:
if condition then result
[else result]
end if;
分支语句2之case:
形式一:
case value
when compare-value then result
[when compare-value then result
……]
[else result]
end case;
形式二:====java中的if else语句
case
when condition then result
[when condition then result
……]
[else result]
end case;
注:在流程控制中end后不用写case;
condition是一个表达式;
循环语句之while循环:执行前检查是否满足循环条件
while condition do
……
end while;
循环语句之repeat循环:执行前检查是否不满足循环条件
repeat
……
until condition (没有‘;’)
end repeat;
循环语句之loop循环:
lable_1:loop
……
leave lable_1;
end loop;
注:
leave语句:只能循环语句中使用,意思离开语句标号为lable_1的语句,相当于“跳出整个循环”(类似java中的break);当满足了特定条件时,通过“leave 循环标号”语句跳出整个循环;
iterater语句:只能循环语句中使用,意思直接跳转到语句标号为lable_1的语句,相当于“跳过本次循环” (类似java中的continue);
当满足了特定条件时,通过“iterater 循环标号”语句跳过本次循环;
语句标号:lables可以用到while, repeat ,loop等循环控制语句中;
存储过程和函数:统称为PL/SQL子程序,它们是被命名的PL/SQL块,均存储在数据库中,以便共享;
唯一区别:函数向调用者返回数据,而过程不返回数据;函数可以在SQL语句内部被调用,而过程则不能被调用;
存储过程和函数的优点:简单,安全,高性能;
创建存储过程:
注:为了安全可以先执行这句:drop procedure if exists <过程名称>;
delimiter //(有空格符)
create procedure <过程名称> (
参数声明
)
begin
过程体
end //
delimiter ;(有空格符)
注:
①delimiter意思是定义符号, 目的是用delimiter关键字申明当前段的自定义分隔符,将其之间的内容当作存储过程,使mysql编译器不会执行这些的代码;记得用完后要把分隔符还原;
②存储过程定义时有三种参数类型: in, out, inout
in 输入参数:在调用时指定,执行中不能被修改并返回;
out 输出参数:执行中能被修改并返回;
inout 输入输出参数:在调用时指定,执行中能被修改并返回;
调用存储过程:
call proc_name (…);
修改存储过程:
alter procedure proc_name ……;
删除存储过程:
drop procedure proc_name ;
查看存储过程:可以获取何时,有谁创建的信息
查看所有存储过程的信息:
show procedure status;
查看指定的存储过程:
show create procedure proc_name;
函数:大体类似于存储过程,只是将关键字procedure变为function
但注意创建函数时不能使用in,out,inout关键字,因为它默认其所有的参数都是in的;
注:为了安全可以先执行这句:drop function if exists <函数名称>;
delimiter //(有空格符)
create function <函数名称> (
参数声明 (参数不能是带@的)
)
returns 参数
begin
过程体
return 参数;
end //
delimiter ;(有空格符)
函数不能用call调用外,但它能在SQL语句内部被调用
例如:select func_name(…) from … where…
使用存储过程和函数的选择:
1.返回多个值或不返回值,用存储过程;返回一个值,用函数;
2.存储过程一般用于执行一个指定的动作;
函数一般用于计算和返回一个值;
3.要在SQL语句内部被使用,只能用函数;
游标cursor:只能用与存储过程或函数;
能在检索出来的行中前进或后退一行或多行;
它不是select语句,而是被该语句检索出来的结果;
创建游标:定义时并未检索数据 只能用declare定义变量;
decalar cur_name cursor for 定义使用的select语句;
打开游标:打开时才按定义检索数据
open cur_name;
使用游标: 通常在while,repeat,loop循环中使用; 游标也可以嵌套;
关闭游标:
close cur_name;
注意:使用后必须关闭游标;存储过程或函数中定义的局部变量必须放在游标之前,而定义的句柄必须放在游标之后;
例:创建一个存储过程,使用游标输出orders表中所有的order_num;
但是这样会有多个结果窗口;
delimiter //
create procedure p_1()
begin
declare o int; #局部变量最先定义
declare done boolean default 0;
declare ordernumbers cursor for #游标在其后定义
select order_num from orders;
declare continue handler for #处理器在最后定义
sqlstate '02000' set done = 1;
open ordernumbers;
fetch ordernumbers into o;
repeat
select o;
#最好将fetch语句放在循环的最后,当其发生异常时能够立即终止循环;
fetch ordernumbers into o;
until done
end repeat;
close ordernumbers;
end //
delimiter ;
注:
fetch cursor into var_name:获取游标当前指向的数据行并将指针指向下一行,然后赋给一个变量;(只能取一行数据)
declare continue handler forsqlstate '02000' set done = 1;
它表示fetch的执行过程中发生满足sql状态码所代表的异常时,会被自动执行的代码;
触发器trigger: 让某些语句在事件发生前或后自动执行;
创建触发器:
delimiter $
create trigger <触发器名称>
[before|after] [insert|update|delete] on <表名称>
for ench row
begin
<触发器SQL语句>
end $
delimiter ;
支持的事件类型:insert, update, delete;
例:在增加tab1表记录后,自动将记录中的tab1_id列中的数据增加到tab2表中;
delimiter $
create trigger t_1
after insert on tab1
/* 一次只能定义一种事件类型;
before update on tab1
after delete on tab1
*/
for each row
begin
#在增加tab1表中记录后,自动将在指定的新增数据添加到tab2表中;
insert into tab2(tab2_id) values (new.tab1_id);
/*
#在tab1表中修改tab1_name列中数据时,会自动将数据变为大写;
set tab1_name = Upper(new.tab1_name);
#在删除tab1表中记录后,自动将指定的删除数据添加到tab2表中;
insert into tab2(tab2_id) values (old.tab1_id);
*/
end $
delimiter ;
注:
在insert触发器中是不能使用old关键字的,只能用new;
在delete触发器中是不能使用new关键字的,只能用old;
在updeta触发器中,before时用new, after时用old;
因为new中的值可被更新修改;而old中的值都是只读的,不能更新修改;
事务处理:它是一种用来维护数据库完整性的机制,可以保证一组操作的原子性,即:要不整体执行,要不执行;如果成功,则写入数据库;如果发生错误,则可以进行回退到以前的某种状态;一般用于增删改操作;
(内部实现的就是让操作在内存中执行,然后一次性将结果写入硬盘)
涉及的关键字:
transaction:事务
rollback:回退
commit:提交到硬盘
savepoint:保留点,它是事务处理中设置的临时占位符,可以对它发布回退,使其恢复到之前的状态;
例:
start transaction; #开始事务处理
delete from tab1 where id= 0;
savepoint point1; #设置保留点
delete from tab1 where id= 1;
delete from tab1 where id= 2;
rollback to point1; #回退到保留点point1之前的状态;
rollback; #回退到开始事务处理之前的状态
commit; #将结果提交到硬盘
注:如果不用事务处理,Mysql默认是自动提交的,但可以用set autocommit=0 语句,取消自动提交;这样就可以使用回退操作;
安全管理:
创建MySql用户账号:
create user 用户名
indentified by ‘密码’;
更改用户名:
rename user … to…;
删掉用户名:
drop user 用户名;
设置访问权限:
show grants for
设置口令:
set password for …… =password(‘ 口令’); //设置自己的口令
set password for …… =password(‘ 口令’);
数据库维护:
备份数据库:使用mysqldump命令
备份多个数据库:
mysqldump –u username –p –all –database
dbname1 dbname2 > Backup.sql
备份所有数据库:
mysqldump –u username –p –all --database
> Backup.sql
注:
-n:不创建数据库
-d:不导出任何数据,只导出数据库的表结构
-t:只导出数据
-r:导出存储过程以及自定义函数
还原数据:
mysql –u root –p dbname < backup.sql
数据库易混点:
数据库中用“=”表示是否相等而不是“==”;
null和任何值操作的结果都是null;