创建[定义者=用户)程序sp_name([proc_parameter[,...]]) [特征…]routine_body创建[定义者=用户)函数sp_name([func_parameter[…]])返回类型[特征…]routine_bodyproc_parameter: [in | out | inout]param_name类型func_parameter:param_name类型类型:任何有效的MySQL数据类型特征{评论'字符串' |语言SQL | [not]确定性|{包含SQL |否SQL |读取SQL数据|修改SQL数据}| SQL安全{定义器|调用器}}routine_body:有效的SQL例程语句
这些语句用于创建存储例程(存储过程或函数)。也就是说,服务器知道指定的例程。默认情况下,存储的例程与默认数据库相关联。要显式地将例程与给定数据库关联,请将名称指定为db_name.sp_name
当你创建它的时候。
的创建函数
语句在MySQL中也被用于支持udf(用户定义函数)。看到第13.7.4.1节“用户定义函数的CREATE FUNCTION语句”.UDF可以被视为一个外部存储函数。存储函数与udf共享命名空间。看到第9.2.5节“函数名解析和解析”,用于描述服务器如何解释对不同类型函数的引用的规则。
方法调用存储过程调用
声明(见第13.2.1节,“CALL语句”).要调用存储函数,请在表达式中引用它。函数在表达式求值期间返回一个值。
创建过程
而且创建函数
要求创建程序
特权。如果定义者
子句存在时,所需的特权取决于用户
价值,如在第25.6节,“存储对象访问控制”.如果启用了二进制日志记录,创建函数
可能需要超级
特权,如在第25.7节“存储程序二进制日志记录”.
默认情况下,MySQL自动授予改变日常
而且执行
例程创建者的特权。控件可以更改此行为automatic_sp_privileges
系统变量。看到第25.2.2节“存储例程和MySQL特权”.
的定义者
而且SQL安全
子句指定在例程执行时检查访问特权时要使用的安全上下文,如本节后面所述。
如果例程名称与内置SQL函数的名称相同,则会发生语法错误,除非在定义例程或稍后调用它时在名称和下面的括号之间使用空格。出于这个原因,避免为自己的存储例程使用现有SQL函数的名称。
的IGNORE_SPACE
SQL模式适用于内置函数,而不适用于存储例程。在存储的例程名称后面总是允许有空格,无论是否IGNORE_SPACE
启用。
括号内的参数列表必须始终存在。的空参数列表()
应该使用。参数名不区分大小写。
每个参数都是在
默认参数。若要为参数指定其他参数,请使用关键字出
或INOUT
在参数名称之前。
将参数指定为在
,出
,或INOUT
仅对a有效过程
.对于一个函数
,参数总是被视为在
参数。
一个在
参数将值传递给过程。过程可以修改值,但当过程返回时,调用方不可见修改。一个出
参数将过程中的值传递回调用方。它的初始值为零
,当过程返回时,它的值对调用者是可见的。一个INOUT
参数由调用方初始化,可以由过程修改,过程所做的任何更改在过程返回时都对调用方可见。
为每一个出
或INOUT
参数中传递一个用户定义的变量调用
调用过程的语句,以便在过程返回时获取其值。如果从另一个存储过程或函数中调用过程,还可以将例程参数或局部例程变量作为出
或INOUT
参数。如果从触发器内部调用过程,也可以传递新的。
作为一个col_name
出
或INOUT
参数。
有关未处理条件对过程参数的影响的信息,请参见第13.6.7.8节“条件处理和OUT或INOUT参数”.
例程参数不能在例程内准备的语句中引用;看到第25.8节,“存储程序的限制”.
下面的示例显示了一个简单的存储过程,给定一个国家代码,计算该国家的城市数量城市
表的世界
数据库。类型传递国家代码在
参数返回城市计数出
参数:
mysql> delimiter // mysql> CREATE PROCEDURE citycount (IN country CHAR(3), OUT cities INT) BEGIN SELECT COUNT(*) INTO cities FROM world。WHERE CountryCode =国家;结束//查询OK, 0 rows affected (0.01 sec) mysql> delimiter;mysql>调用城市计数('JPN', @城市);查询OK, 1 row affected (0.00 sec) mysql> SELECT @cities;+---------+ | @ 城市 | +---------+ | 248年 | +---------+ 1行组(0.00秒)mysql >调用citycount(联邦铁路局,@cities);——法国城市查询OK, 1 row affected (0.00 sec) mysql> SELECT @cities;+---------+ | @ 城市 | +---------+ | 40 | +---------+ 1行集(0.00秒)
该示例使用mysql客户端分隔符
命令来更改语句分隔符;
来//
在定义过程时。这使;
在过程体中使用的分隔符,要传递给服务器,而不是由mysql本身。看到第25.1节“定义存储程序”.
的返回
子句只能用于函数
,这是强制性的。它指示函数的返回类型,函数体必须包含返回
声明。如果价值
返回
语句返回不同类型的值,该值被强制转换为正确的类型。例如,如果函数指定了枚举
或集
的价值返回
条款,但返回
语句返回一个整数,函数返回的值是对应的字符串枚举
集合的成员集
成员。
下面的示例函数接受一个参数,使用SQL函数执行一个操作,并返回结果。在这种情况下,就没有必要使用了分隔符
因为函数定义不包含内部;
语句分隔符:
mysql>返回CHAR(50) DETERMINISTIC RETURN CONCAT(' hello,',s,'!');查询OK, 0 rows affected (0.00 sec) mysql> SELECT hello('world');+----------------+ | 你好(“世界上 ') | +----------------+ | 你好,世界!| +----------------+ 1 row in set (0.00 sec)
参数类型和函数返回类型可以声明为使用任何有效的数据类型。的核对
属性前若有字符集
规范。
的routine_body
由有效的SQL例程语句组成。这可以是一个简单的语句,例如选择
或插入
,或用开始
而且结束
.复合语句可以包含声明、循环和其他控制结构语句。这些语句的语法在第13.6节,“复合语句语法”.在实践中,存储函数倾向于使用复合语句,除非主体由单个语句组成返回
声明。
MySQL允许例程包含DDL语句,例如创建
而且下降
.MySQL还允许存储过程(但不允许存储函数)包含SQL事务语句,例如提交
.存储的函数不能包含执行显式或隐式提交或回滚的语句。SQL标准并不要求支持这些语句,它规定每个DBMS供应商可以决定是否允许它们。
返回结果集的语句可以在存储过程中使用,但不能在存储函数中使用。这个禁令包括选择
语句中没有成
子句和其他语句,如var_list
显示
,解释
,检查表
.对于可以在函数定义时确定返回结果集的语句,a不允许从函数返回结果集
发生错误(ER_SP_NO_RETSET
).对于只能在运行时确定返回结果集的语句,a过程%s不能在给定的上下文中返回结果集
发生错误(ER_SP_BADSELECT
).
使用
存储例程中的语句是不允许的。当调用例程时,隐式使用
执行(当例程终止时撤销)。使例程在执行时具有给定的默认数据库。对数据库中除例程默认数据库之外的对象的引用应使用适当的数据库名称进行限定。db_name
有关存储例程中不允许的语句的其他信息,请参见第25.8节,“存储程序的限制”.
有关从用具有MySQL接口的语言编写的程序中调用存储过程的信息,请参见第13.2.1节,“CALL语句”.
MySQL存储sql_mode
系统变量设置在例程创建或更改时生效,并且总是在此设置生效时执行例程,无论例程开始执行时的当前服务器SQL模式是什么.
从调用程序的SQL模式切换到例程的SQL模式发生在实参求值并将结果值赋值给例程参数之后。如果在严格SQL模式下定义例程,但在非严格模式下调用它,则不会在严格模式下为例程参数赋值。如果要求以严格SQL模式分配传递给例程的表达式,则应该在严格模式生效的情况下调用例程。
的评论
feature是一个MySQL扩展,可以用来描述存储例程。控件显示此信息显示创建过程
而且显示创建函数
语句。
的语言
特征表示编写例程所用的语言。服务器忽略这个特性;只支持SQL例程。
考虑一个例程”确定的”如果它总是对相同的输入参数产生相同的结果,并且”不确定性”否则。如果既不确定的
也不不确定性
在例程定义中给出,默认为不确定性
.要声明一个函数是确定性的,必须指定确定的
明确。
对例行公事性质的评估是基于”诚实”MySQL不会检查例程是否声明确定的
不包含产生不确定结果的语句。然而,错误地声明例程可能会影响结果或影响性能。将一个非确定性例程声明为确定的
可能导致优化器做出不正确的执行计划选择,从而导致意想不到的结果。声明一个确定性例程为不确定的
可能会导致无法使用可用的优化,从而降低性能。
如果启用了二进制日志记录,则确定的
特性影响MySQL接受哪些例程定义。看到第25.7节“存储程序二进制日志记录”.
类的例程现在()
函数(或其同义词)或RAND ()
是不确定的,但它可能仍然是复制安全的。为现在()
,二进制日志包含时间戳并正确复制。RAND ()
只要在例程执行期间只调用一次,也可以正确复制。(可以将例程执行时间戳和随机数种子视为源和副本上相同的隐式输入。)
有几个特征提供了关于例程使用数据的性质的信息。在MySQL中,这些特征只是建议。服务器不使用它们来约束例程允许执行哪种类型的语句。
的SQL安全
特性可以定义者
或调用程序
指定安全上下文;也就是说,例程是否使用例程中指定的帐户的特权执行定义者
子句或调用它的用户。此帐户必须具有访问例程关联的数据库的权限。默认值为定义者
.调用例程的用户必须具有执行
特权为之,必为之定义者
帐户,如果例程在定义器安全上下文中执行。
的定义者
子句指定在例程执行时检查访问权限时要使用的MySQL帐户SQL安全定义者
的特点。
如果定义者
从句是存在的用户
值应该是MySQL帐户指定为'
,user_name
“@”host_name
'CURRENT_USER
,或CURRENT_USER ()
.允许用户
值取决于您持有的特权,如中所讨论的第25.6节,“存储对象访问控制”.有关存储例程安全性的其他信息,请参见该部分。
如果定义者
子句时,默认定义者是执行创建过程
或创建函数
声明。这与指定是一样的定义者= CURRENT_USER
明确。
类定义的存储例程的主体中SQL安全定义者
特点,CURRENT_USER
函数返回例程的定义者
价值。有关存储例程中的用户审计的信息,请参见第6.2.22节,“基于sql的帐户活动审计”.
考虑下面的过程,该过程显示MySQL帐户的数量mysql.user
系统表:
CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count() BEGIN SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;结束;
该程序被分配了一个定义者
账户的“admin”@“localhost”
无论哪个用户定义它。无论哪个用户调用它,它都使用该帐户的特权执行(因为默认的安全特性是定义者
).过程的成功或失败取决于调用方是否具有执行
对它的特权“admin”@“localhost”
有选择
特权的mysql.user
表格
现在假设过程是用SQL安全调用程序
特点:
CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count() SQL SECURITY INVOKER BEGIN SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;结束;
这个过程还有一个定义者
的“admin”@“localhost”
但是在本例中,它使用调用用户的特权执行。因此,过程的成功或失败取决于调用方是否拥有执行
它的特权和选择
特权的mysql.user
表格
服务器处理例程参数的数据类型、创建的本地例程变量声明
,或函数返回值如下所示:
检查赋值是否存在数据类型不匹配和溢出。转换和溢出问题在严格SQL模式下会导致警告或错误。
只能分配标量值。例如,这样的语句
SET x = (SELECT 1,2)
是无效的。对于字符数据类型,如果
字符集
时,将使用指定的字符集及其默认排序规则。如果核对
属性,则使用该排序规则而不是默认的排序规则。如果
字符集
而且核对
如果不存在,则使用例程创建时有效的数据库字符集和排序。为避免服务器使用数据库字符集和排序规则,请提供显式的字符集
和一个核对
字符数据参数的属性。如果更改数据库默认字符集或排序规则,则必须删除并重新创建要使用新的数据库默认值的存储例程。
的值给出数据库字符集和排序规则
character_set_database
而且collation_database
系统变量。有关更多信息,请参见第10.3.3节“数据库字符集和排序规则”.