1.创建函数
1 CREATE FUNCTION factorial (n DECIMAL(3,0))
2 RETURNS DECIMAL(20,0)
3 DETERMINISTIC
4 BEGIN
5 DECLARE factorial DECIMAL(20,0) DEFAULT 1;
6 DECLARE counter DECIMAL(3,0);
7 SET counter = n;
8 factorial_loop: REPEAT
9 SET factorial = factorial * counter;
10 SET counter = counter - 1;
11 UNTIL counter = 1
12 END REPEAT;
13 RETURN factorial;
14 END //
函数跟过程很相似,唯一需要指出的语法上的不同:创建函数后必须有RETURN语句指定返回值类型并返回相应类型的值.下面是函数使用的例子:
1 INSERT INTO t VALUES (factorial(pi)) //
2 SELECT s1, factorial (s1) FROM t //
3 UPDATE t SET s1 = factorial(s1) WHERE factorial(s1) < 5 //
注意在函数中访问表,这使得函数不如存储过程强大,以下是不能出现在函数中的限制:
ALTER 'CACHE INDEX' CALL COMMIT CREATE DELETE
DROP 'FLUSH PRIVILEGES' GRANT INSERT KILL
LOCK OPTIMIZE REPAIR REPLACE REVOKE
ROLLBACK SAVEPOINT 'SELECT FROM table'
'SET system variable' 'SET TRANSACTION'
SHOW 'START TRANSACTION' TRUNCATE UPDATE
以下指令是可以出现在函数中的:
'BEGIN END'
DECLARE
IF
ITERATE
LOOP
REPEAT
RETURN
'SET declared variable'
WHILE
2. Metadata元数据
我们创建的过程或函数,都会保存在MySQL数据库中.如果要查看MySQL实际上保存了什么信息,有以下四种方法,分别是两个SHOW和两个SELECT语句:
mysql> show create procedure p6//
+-------------+------------+--------------------------------------------------------------------+
| Procedure | sql_mode | Create Procedure |
+-------------+------------+--------------------------------------------------------------------+
| CREATE PROCEDURE `db5`.`p6`(out p | int) set p = -5 |
+-------------+------------+--------------------------------------------------------------------+
这同SHOW CREATE TABLE及其他类似MySQL语句一样.它并不返回你创建过程时设定的返回值,但大部分情况下已经够用了.
mysql> SHOW PROCEDURE STATUS LIKE 'p6'//
SELECT * FROM mysql.proc WHERE name = 'p6'//
4) SELECT from information_schema:
1 mysql > SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
2 -> WHERE TABLE_NAME = 'ROUTINES';//
这是被推荐的方式,因为其他方式可能会出现错误:
1) 其他DBMS如SQL Server 2000,使用information_schema,只有MySQL才有SHOW方式.
2) 我们访问mysql.proc的权限是没有保证的,但有访问information_schema视图的权限,每个用户都有隐式的对当局者迷information_schema数据库的SELECT权限.
3) SELECT功能很多,可以计算表达式,分组,排序,产生可以获取信息的结果集.而这些功能SHOW没有.
下面是使用该方法的例子,首先使用SELECT information_schema来显示information_schema例程中有哪些列:
1 mysql > SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
2 -> WHERE TABLE_NAME = 'ROUTINES';//
执行以上指令后会输出结果如下:
TABLE_NAME | COLUMN_NAME | COLUMN_TYPE |
ROUTINES | SPECIFIC_NAME | varchar(64) |
ROUTINES | ROUTINE_CATALOG | longtext |
ROUTINES | ROUTINE_SCHEMA | varchar(64) |
ROUTINES | ROUTINE_NAME | varchar(64) |
ROUTINES | ROUTINE_TYPE | varchar(9) |
ROUTINES | DTD_IDENTIFIER | varchar(64) |
ROUTINES | ROUTINE_BODY | varchar(8) |
ROUTINES | ROUTINE_DEFINITION | longtext |
ROUTINES | EXTERNAL_NAME | varchar(64) |
ROUTINES | EXTERNAL_LANGUAGE | varchar(64) |
ROUTINES | PARAMETER_STYLE | varchar(8) |
ROUTINES | IS_DETERMINISTIC | varchar(3) |
ROUTINES | SQL_DATA_ACCESS | varchar(64) |
ROUTINES | SQL_PATH | varchar(64) |
ROUTINES | SECURITY_TYPE | varchar(7) |
ROUTINES | CREATED | varbinary(19) |
ROUTINES | LAST_ALTERED | varbinary(19) |
ROUTINES | SQL_MODE | longtext |
ROUTINES | ROUTINE_COMMENT | varchar(64) |
ROUTINES | DEFINER | varchar(77) |
知道了上面的表结构,就可以查询我们想要得到的信息,如下代码可查看数据库db6中定义的存储过程:
1 mysql > SELECT COUNT(*) FROM INFORMATION_SCHEMA.ROUTINES
2 -> WHERE ROUTINE_SCHEMA = 'db6';//
ROUTINE_DEFINITION列的访问控制
在INFORMATION_SCHEMA中的ROUTINE_DEFINITION列是由过程或函数组成过程体获得的,因可能存在敏感信息而只对过程创建者可见.
CURRENT_USER<>INFORMATIN_SCHEMA.ROUTINES.DEFINER:如果对它使用SELECT的用户不是创建它的用户,则MySQL将返回null值,而不是ROUTINE_DEFINITION列.
SHOW PROCEDURE STATUS中的辅助子句
SHOW PROCEDURE STATUS [WHERE condition];
1 mysql> SHOW PROCEDURE STATUS WHERE Db = 'p';
2 /*ERROR 1054 (42S22): Unknown column 'Db' in 'where clause'*/
3 mysql> SHOW PROCEDURE STATUS WHERE ROUTINE_NAME = 'p';