前面的话
本人使用的MySQL 5.1版本,图形化界面用的SQLyog,本文主要介绍有如下内容:
- MySQL常用函数
- 触发器
- 存储过程
- 数据备份与恢复
MySQL常用函数
日期和时间函数
- curdate() 返回当前日期(current date)
- curtime() 返回当前时间
- month(d) 返回日期d中的月份值,范围是1~12
SELECT CURDATE(),CURTIME(),MONTH(birthday)
FROM t_user3;
字符串函数
- char_length(s) 计算字符串s的字符数
- upper(s) 把字符串s中所有字母变成大写字母
- lower(s) 把所有字母变成小写字母
SELECT userName,CHAR_LENGTH(userName),UPPER(userName),LOWER(userName)
FROM t_user3 GROUP BY id;
数学函数
- abs(x) 求绝对值
- sqrt(x) 求平方根
- mod(x,y) 求余
SELECT num,ABS(num),SQRT(4),MOD(9,2)
FROM t_user3;
加密函数
- password(str) 一般对用户的密码加密 不可逆
- md5(str) 普通加密 不可逆
- encode(str,pswd_str) 加密函数,结果是一个二进制数,必须使用blob类型的字段来保存它
- decode(crypt_str,pswd_str) 解密函数
INSERT INTO t_user3 (PASSWORD,password2) VALUES(PASSWORD("123456"),NULL);
INSERT INTO t_user3 (PASSWORD,password2) VALUES(MD5("123456"),ENCODE("123456","aa"));
SELECT DECODE(password2,"aa") FROM t_user3 WHERE id=6;
触发器
触发器(trigger)是由事件来触发某个操作。这些事件包括insert语句、update语句和delete语句。当数据库系统执行这些事件时,就会激活触发器执行响应的操作。
创建与使用触发器
创建只有一个执行语句的触发器
create trigger 触发器名 before|after 触发事件
on 表名 for each row 执行语句
/* 格式 */
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
TRIGGER `db_book`.`trig_book` BEFORE/AFTER INSERT/UPDATE/DELETE
ON `db_book`.`<Table Name>`
FOR EACH ROW BEGIN
END$$
DELIMITER ;
/* 手动创建 */
CREATE TRIGGER trig_book AFTER INSERT
ON t_book FOR EACH ROW
UPDATE t_booktype SET bookNum=bookNum+1 WHERE new.bookTypeId=t_booktype.id;
/* 插入数据 */
INSERT INTO t_book VALUES(NULL,'sfasf',100,'sf',1)
创建有多个执行语句的触发器
create trigger 触发器名 before|after 触发事件
on 表名 for each row
begin
执行语句列表
end
/* 手动创建 */
DELIMITER |
CREATE TRIGGER trig_book2 AFTER DELETE
ON t_book FOR EACH ROW
BEGIN
UPDATE t_bookType SET bookNum=bookNum-1 WHERE old.bookTypeId=t_bookType.id;
INSERT INTO t_log VALUES(NULL,NOW(),'在book表里删除了一条数据');
DELETE FROM t_test WHERE old.bookTypeId=t_test.id;
END
|
DELIMITER ;
/* 数据库创建 */
DELIMITER $$
USE `db_book`$$
DROP TRIGGER IF EXISTS `trig_book2`$$
CREATE
/*!50017 DEFINER = 'root'@'localhost' */
TRIGGER `trig_book2` AFTER DELETE ON `t_book`
FOR EACH ROW BEGIN
UPDATE t_bookType SET bookNum=bookNum-1 WHERE old.bookTypeId=t_bookType.id;
INSERT INTO t_log VALUES(NULL,NOW(),'在book表里删除了一条数据');
DELETE FROM t_test WHERE old.bookTypeId=t_test.id;
END;
$$
DELIMITER ;
查看触发器
show triggers 语句查看所有触发器信息
SHOW TRIGGERS;
SHOW CREATE TRIGGER trig_book2;
在trigger表中查看触发器信息
USE information_schema;
SELECT * FROM TRIGGERS;
删除触发器
drop trigger 触发器名
DROP TRIGGER trig_book;
DROP TRIGGER trig_book2;
存储过程和函数
存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句。
存储过程和函数可以避免开发人员重复编写相同的SQL语句,而且存储过程和函数是在MySQL服务器中存储和执行的,可以减少客户端和服务器端的数据传输。
创建存储过程和函数
创建存储过程
create procedure sp_name([proc_parameter[,...]])
[characteristic...] routine_body
sp_name: 存储过程的名称
proc_parameter: 存储过程的参数列表
characteristic: 存储过程的特性
routine_body: 是SQL代码的内容,可以用begin...end来标志SQL代码的开始和结束。
proc_parameter中的每个参数由3部分组成(输入输出类型、参数名称和参数类型):
[in|out|inout] param_name type
in表示输入参数,out表示输出参数,inout表示既是输入也是输出参数;
param_name参数是参数的名称;
type是参数的类型。
characteristic: 参数有多个取值,取值说明如下:
LANGUAGE SQL:说明routine_body部分是由SQL语言的语句组成,这也是数据库系统默认的语言。
[NOT] DETERMINISTIC:指明存储过程的执行结果是否是确定的。(相同输入,输出是否确定?)
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }:指明子程序使用的SQL的限制:
CONTAINS SQL:表示子程序包含SQL语句,但不包含读或写数据的语句;
NO SQL:表示子程序中不包含SQL语句;
READS SQL DATA:表示子程序中包含读数据的语句;
MODIFIES SQL:表示子程序中包含写数据的语句;
默认情况下,系统会指定CONSTRAINT SQL;
SQL SECURITY { DEFINER | INVOKER }:指明谁有权限来执行。
DEFINER:表示只有定义者自己才能够执行;
INVOKER:表示调用者可以执行。
默认情况下的权限是DEFINER。
COMMENT 'string':注释信息。
/* 格式 */
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
PROCEDURE `db_book`.`pro_book2`()
/*LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'*/
BEGIN
END$$
DELIMITER ;
/* 手动创建 */
DELIMITER $$
CREATE PROCEDURE pro_book(IN bt INT, OUT coun_num INT)
READS SQL DATA
BEGIN
SELECT COUNT(*) FROM t_book WHERE booktypeId=bt;
END
$$
DELIMITER ;
/* 调用存储过程 */
CALL pro_book(1,@total)
/* 数据库创建 */
DELIMITER $$
USE `db_book`$$
DROP PROCEDURE IF EXISTS `pro_book`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_book`(IN bt INT, OUT coun_num INT)
READS SQL DATA
BEGIN
SELECT COUNT(*) FROM t_book WHERE booktypeId=bt;
END$$
DELIMITER ;
创建存储函数
create function sp_name([func_parameter[,...]])
returns type
[characteristic...] routine_body
sp_name:参数是存储函数的名称;
func_parameter:表示存储函数的参数列表;
returns type:指定返回值的类型;
characteristic参数:指定存储过程的特性,该参数的取值与存储过程中的取值是一样的。
routine_body参数:指SQL代码的内容,可以用begin...end来标志SQL代码的开始和结束;
func_parameter:可以由多个参数组成,其中每个参数由参数名称和参数类型组成,其形式如下:
param_name type 其中,param_name是参数名称,type是参数的类型,该类型可以是MySQL数据库的任意数据类型。
/* 数据库创建 */
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
FUNCTION `db_book`.`func_book`()
RETURNS TYPE
/*LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'*/
BEGIN
END$$
DELIMITER ;
/* 手动创建 */
DELIMITER $$
CREATE FUNCTION func_book (bookId INT)
RETURNS VARCHAR(20)
BEGIN
RETURN (SELECT bookName FROM t_book WHERE id=bookId);
END
$$
DELIMITER ;
/* 调用存储函数 */
SELECT func_book(2);
/* 数据库修改存储函数 */
DELIMITER $$
USE `db_book`$$
DROP FUNCTION IF EXISTS `func_book`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `func_book`(bookId INT) RETURNS VARCHAR(20) CHARSET utf8
BEGIN
RETURN (SELECT bookName FROM t_book WHERE id=bookId);
END$$
DELIMITER ;
变量的使用
定义变量
declare var_name[,…] type [default value]
/* 创建存储过程并定义变量 */
DELIMITER $$
CREATE PROCEDURE pro_user()
BEGIN
DECLARE a,b VARCHAR(20);
INSERT INTO t_user VALUES (NULL,a,b);
END
$$
DELIMITER ;
/* 调用存储过程 */
CALL pro_user();
为变量赋值
1)
set var_name=expr[,var_name=expr]…
/* 创建存储过程,定义变量并为通过set为变量赋值 */
DELIMITER $$
CREATE PROCEDURE pro_user2()
BEGIN
DECLARE a,b VARCHAR(20);
SET a="Hello",b="World";
INSERT INTO t_user VALUES (NULL,a,b);
END
$$
DELIMITER ;
/* 调用存储过程 */
CALL pro_user2();
2)
select col_name[,…] into var_name[,…]
from table name
where condition
/* 创建存储过程,定义变量并为通过select为变量赋值 */
DELIMITER $$
CREATE PROCEDURE pro_user2_2()
BEGIN
DECLARE a,b VARCHAR(20);
SELECT userName2,password2 INTO a,b
FROM t_user2_2 WHERE id2=1;
INSERT INTO t_user VALUES (NULL,a,b);
END
$$
DELIMITER ;
CALL pro_user2_2();
游标的使用
查询语句可能查询到多条记录,在存储过程和函数中使用游标来逐条读取查询结果集中的记录。
游标的使用包括声明游标、打开游标、使用游标和关闭游标。
游标必须声明在处理程序之前,并且声明在变量和条件之后。
1) 声明游标
declare cursor_name cursor for select_statement;
2) 打开游标
open cursor_name;
3) 使用游标
fetch cursor_name into var_name[,var_name…];
4) 关闭游标
close cursor_name;
/* 创建存储过程演示游标的使用 */
DELIMITER $$
CREATE PROCEDURE pro_user3()
BEGIN
DECLARE a,b VARCHAR(20);
/* 声明游标 */
DECLARE cur_user2 CURSOR FOR
SELECT userName2,password2 FROM t_user2_2;
/* 打开游标 */
OPEN cur_user2;
/* 使用游标,从游标中取数据 */
FETCH cur_user2 INTO a,b;
INSERT INTO t_user VALUES(NULL,a,b);
/* 关闭游标 */
CLOSE cur_user2;
END
$$
DELIMITER ;
/* 调用存储过程 */
CALL pro_user3();
流程控制的使用
存储过程和函数中可以使用流程控制来控制语句的执行。
MySQL中可以使用IF语句、CASE语句、LOOP语句、LEAVE语句、ITERATE语句、REPEAT语句和WHILE语句来进行流程控制。
IF语句
if search_condition then statement_list
[else if search_condition then statement_list]
…
[else statement_list]
end if
DELIMITER $$
CREATE PROCEDURE pro_user4(IN bookId INT)
BEGIN
SELECT COUNT(*) INTO @num FROM t_user WHERE id=bookId;
IF @num>0 THEN UPDATE t_user SET userName='yyy',PASSWORD='yyy' WHERE id=bookId;
ELSE
INSERT INTO t_user VALUES(NULL,'nnn','nnn');
END IF ;
END
$$
DELIMITER ;
CASE语句
case case_value
when when_value then statement_list
[when when_value then statement_list]
…
[else statement_list]
end case
DELIMITER $$
CREATE PROCEDURE pro_user5(IN bookId INT)
BEGIN
CASE bookId
WHEN 1 THEN
UPDATE t_user SET userName="1",PASSWORD="1" WHERE id=bookId;
WHEN 2 THEN
INSERT INTO t_user VALUES(NULL,"2","2");
ELSE
INSERT INTO t_user VALUES(NULL,"other","other");
END CASE ;
END
$$
DELIMITER ;
LOOP,LEAVE语句
loop语句可以使某些特定的语句重复执行,实现一个简单的循环。但是loop语句本身没有停止循环的语句,必须是遇到leave语句才能停止循环。
[begin_label:] loop
statement_list;
end loop [end_label]
leave 语句主要用于跳出循环控制,语法如下:
leave label
DELIMITER $$
CREATE PROCEDURE pro_user6(IN totalNum INT)
BEGIN
a:LOOP
IF totalNum=0
THEN LEAVE a;
ELSE
INSERT INTO t_user VALUES(totalNum,"afa","faf");
END IF ;
SET totalNum=totalNum-1;
END LOOP a;
END
$$
DELIMITER ;
ITERATE语句
iterate 语句也是用来跳出循环的语句,但是,iterate 语句是跳出本次循环,然后直接进入下一次循环,语法如下:
iterate label;
DELIMITER $$
CREATE PROCEDURE pro_user7(IN totalNum INT)
BEGIN
a:LOOP
SET totalNum=totalNum-1;
IF totalNum=0 THEN LEAVE a;
ELSEIF totalNum=3 THEN ITERATE a;
END IF;
INSERT INTO t_user VALUES(totalNum,'aaa','aaa');
END LOOP a;
END
$$
DELIMITER ;
REPEAT语句
repeat 语句是有条件控制的循环语句。
当满足特定条件时,就会跳出循环语句。
repeat语句的基本语法如下:
[begin_label:]repeat
statement_list
until search_condition
end repeat[end_label]
DELIMITER $$
CREATE PROCEDURE pro_user8(IN totalNum INT)
BEGIN
REPEAT
INSERT INTO t_user VALUES(totalNum,"xxx","xxx");
SET totalNum=totalNum-1;
UNTIL totalNum=0
END REPEAT;
END
$$
DELIMITER ;
WHILE语句
[begin_label:]while search_condition do
statement_list
end while[end_label]
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
PROCEDURE `db_book`.`pro_user9`(IN totalNum INT)
/*LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'*/
BEGIN
WHILE totalNum>0 DO
INSERT INTO t_user VALUES(totalNum, 'zzz', 'zz');
SET totalNum=totalNum-1;
END WHILE ;
END$$
DELIMITER ;
调用存储过程和函数
调用存储过程
call sp_name([parameter[,…]])
调用存储函数
fun_name([parameter[,…]])
查看存储过程和函数
SHOW STATUS 语句查看存储过程和函数的状态
show {procedure | function} status [like ‘pattern’]
SHOW CREATE 语句查看存储过程和函数的定义
show create {procedure | function } sp_name;
从information_schema.Routines 表中查看存储过程和函数的信息
select * from information_schema.Routines;
修改存储过程和函数
alter {procedure | function} sp_name [characteristic…]
ALTER PROCEDURE pro_user9 COMMENT "我来增加一个comment";
删除存储过程和函数
drop {procedure | function} sp_name;
DROP PROCEDURE pro_book;
数据备份与还原
数据备份
数据备份可以保证数据库中的数据的安全,数据库管理员需要定期地进行数据库备份。
使用mysqldump命令备份
mysqldump -u username -p dbname table1 table2 …>BackupName.sql
dbname 参数表示数据库的名称;
table1和table2参数表示表的名称,没有该参数时将备份整个数据库;
BackupName.sql参数表示备份文件的名称,文件名前面可以加上一个绝对路径。通常以sql作为后缀。
使用sqlyog图形工具备份
略
数据还原
使用mysql命令数据还原
mysql -u username -p [dbname]<backup.sql
dbname参数表示数据库名称。该参数是可选参数,可以指定数据库名,也可以不指定。指定数据库名时,表示还原该数据库下的表。不指定数据库名时,表示还原特定的一个数据库。而备份文件中有创建数据库的语句。
使用sqlyog图形工具还原
略
结束语
至此,我们的MySQL已经全部通关了,接下来可以通过项目经验的积累让我们对数据库有更深的认识,以及更深的追问。