MySQL 存储过程详解
1. 如何创建存储过程?
- 创建存储过程的语法:
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
CREATE
[DEFINER = { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement
2.详细解释
CREATE PROCEDURE and CREATE FUNCTION require the CREATE ROUTINE privilege. They might also require the SUPER privilege, depending on the DEFINER value, as described later in this section. If binary logging is enabled, CREATE FUNCTION might require the SUPER privilege, as described in Section 23.7, “Binary Logging of Stored Programs”.
- 关于修改和执行存储过程的权限
By default, MySQL automatically grants the ALTER ROUTINE and EXECUTE privileges to the routine creator. This behavior can be changed by disabling the automatic_sp_privileges system variable.
- 访问权限
The DEFINER and SQL SECURITY clauses specify the security context to be used when checking access privileges at routine execution time, as described later in this section.
The SQL SECURITY characteristic can be DEFINER or INVOKER to specify the security context; that is,whether the routine executes using the privileges of the account named in the routine DEFINER clause or the user who invokes it. This account must have permission to access the database with which the routine is associated. The default value is DEFINER. The user who invokes the routine must have the EXECUTE privilege for it, as must the DEFINER account if the routine executes in definer security context.
The DEFINER clause specifies the MySQL account to be used when checking access privileges at routine execution time for routines that have the SQL SECURITY DEFINER characteristic.
If a user value is given for the DEFINER clause, it should be a MySQL account specified as
‘user_name’@‘host_name’, CURRENT_USER, or CURRENT_USER(). The default DEFINER value is the user who executes the CREATE PROCEDURE or CREATE FUNCTION statement. This is the same as specifying DEFINER = CURRENT_USER explicitly.
If you specify the DEFINER clause, these rules determine the valid DEFINER user values:
• If you do not have the SUPER privilege, the only permitted user value is your own account, either specified literally or by using CURRENT_USER. You cannot set the definer to some other account.
• If you have the SUPER privilege, you can specify any syntactically valid account name. If the account does not exist, a warning is generated.
• Although it is possible to create a routine with a nonexistent DEFINER account, an error occurs at routine execution time if the SQL SECURITY value is DEFINER but the definer account does not exist.
For more information about stored routine security.
Within a stored routine that is defined with the SQL SECURITY DEFINER characteristic, CURRENT_USER returns the routine’s DEFINER value. For information about user auditing within stored routines.
很好理解,我不再翻译了。【注意两个单词即可:definer
定义者;invoker
调用者】
下面给出一个示例:
Consider the following procedure, which displays a count of the number of MySQL accounts listed in the mysql.user table:
CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()
BEGIN
SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
END;
【楼下是重点】
The procedure is assigned a DEFINER account of ‘admin’@‘localhost’ no matter which user defines it. It executes with the privileges of that account no matter which user invokes it (because the default security characteristic is DEFINER). The procedure succeeds or fails depending on whether invoker has the EXECUTE privilege for it and ‘admin’@‘localhost’ has the SELECT privilege for the mysql.user table.
Now suppose that the procedure is defined with the SQL SECURITY INVOKER characteristic:
CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()
SQL SECURITY INVOKER
BEGIN
SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
END;
The procedure still has a DEFINER of ‘admin’@‘localhost’, but in this case, it executes with the
privileges of the invoking user. Thus, the procedure succeeds or fails depending on whether the invoker has the EXECUTE privilege for it and the SELECT privilege for the mysql.user table.
3.总结
这么来看,我个人觉得 仅仅使用 DEFINER
会比 SQL SECURITY INVOKER
要好用的多。
4.常见错误
如果这个地方没有处理好,通常会带来如下的错误:
View 'xxx' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
错误代码是ERROR 1449 (HY000)