创建[definer = .用户)程序sp_name([proc_parameter[,...]]) [特征…]routine_body创建[definer = .用户)函数sp_name([func_parameter[…]])返回类型[特征…]routine_bodyproc_parameter: [in | out | inout]param_name类型func_parameter:param_name类型类型:任何有效的MySQL数据类型特征{注释'字符串' |语言SQL |[不]确定性|{包含SQL | no 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。国家代码=国家;END//查询OK, 0 rows affected(0.01秒)mysql> delimiter;mysql> CALL citycount('JPN', @cities);——日本城市查询OK, 1行影响(0.00秒)mysql> SELECT @cities;+---------+ | @ 城市 | +---------+ | 248年 | +---------+ 1行组(0.00秒)mysql >调用citycount(联邦铁路局,@cities);——法国的城市查询OK, 1行影响(0.00秒)mysql> SELECT @城市+---------+ | @ 城市 | +---------+ | 40 | +---------+ 1行集(0.00秒)
该示例使用mysql客户端分隔符
命令更改语句分隔符;
来//
在定义过程时。这将启用;
在过程体中使用的分隔符,该分隔符将传递给服务器,而不是由mysql本身。看到第25.1节“定义存储程序”.
的返回
子句只能用于函数
,这是强制性的。它表示函数的返回类型,并且函数体必须包含返回
声明。如果价值
返回
语句返回不同类型的值,该值被强制转换为正确的类型。例如,如果函数指定枚举
或集
的价值返回
条款,但返回
语句返回一个整数,函数返回的值是对应的字符串枚举
集合的成员集
成员。
下面的示例函数接受一个参数,使用SQL函数执行操作,并返回结果。在这种情况下,没有必要使用分隔符
因为函数定义不包含内部;
语句分隔符:
mysql>返回CHAR(50) DETERMINISTIC RETURN CONCAT(' hello,',s,'!');mysql> SELECT hello('world');+----------------+ | 你好(“世界上 ') | +----------------+ | 你好,世界!| +----------------+ 1 row in set (0.00 sec)
参数类型和函数返回类型可以声明为使用任何有效的数据类型。的核对
属性前加字符集
规范。
的routine_body
由有效的SQL例程语句组成。这可以是一个简单的语句,例如选择
或插入
,或用开始
而且结束
.复合语句可以包含声明、循环和其他控制结构语句。中描述了这些语句的语法第13.6节“复合语句语法”.实际上,存储函数倾向于使用复合语句,除非函数体由单个语句组成返回
声明。
MySQL允许例程包含DDL语句,例如创建
而且下降
.MySQL还允许存储过程(但不允许存储函数)包含SQL事务语句,例如提交
.存储函数不能包含执行显式或隐式提交或回滚的语句。SQL标准并不要求对这些语句的支持,该标准规定每个DBMS供应商可以决定是否允许它们。
返回结果集的语句可以在存储过程中使用,但不能在存储函数中使用。这项禁令包括选择
没有变量的语句成
子句和其他语句,如var_list
显示
,解释
,检查表
.对于可以在函数定义时确定返回结果集的语句,使用不允许从函数返回结果集
发生错误(ER_SP_NO_RETSET
).对于只能在运行时确定返回结果集的语句,可以使用在给定的上下文中,%s不能返回结果集
发生错误(ER_SP_BADSELECT
).
使用
不允许存储例程中的语句。当调用一个例程时,隐式使用
执行(并在例程终止时撤消)。使例程在执行时具有给定的默认数据库。对除例程默认数据库之外的数据库中的对象的引用应使用适当的数据库名称进行限定。db_name
有关存储例程中不允许的语句的其他信息,请参见第25.8节“存储程序的限制”.
有关从用具有MySQL接口的语言编写的程序中调用存储过程的信息,请参见第13.2.1节“CALL语句”.
MySQL存储sql_mode
当一个例程被创建或改变时,系统变量设置生效,并且总是在这个设置生效时执行例程,当例程开始执行时,不管当前的服务器SQL模式如何.
从调用方的SQL模式切换到例程的SQL模式发生在对参数求值并将结果值赋给例程参数之后。如果在严格SQL模式下定义例程,但在非严格模式下调用它,则不会在严格模式下将参数赋值给例程参数。如果要求以严格SQL模式分配传递给例程的表达式,则应该使用严格模式调用该例程。
的评论
characteristic是一个MySQL扩展,可以用来描述存储的例程。命令显示此信息显示创建过程
而且显示创建函数
语句。
的语言
特征指示编写例程所用的语言。服务器忽略这个特性;只支持SQL例程。
例程被认为是”确定的”如果它总是对相同的输入参数产生相同的结果,那么”不确定性”否则。如果既不确定的
也不不确定性
是在例程定义中给出的,默认是不确定性
.要声明一个函数是确定的,必须指定确定的
明确。
对套路性质的评估是基于”诚实”MySQL不检查已声明的例程确定的
不包含产生不确定结果的语句。然而,错误地声明一个例程可能会影响结果或性能。将一个不确定例程声明为确定的
可能导致优化器做出不正确的执行计划选择,从而导致意想不到的结果。将一个确定性例程声明为不确定的
可能会导致不使用可用的优化,从而降低性能。
如果启用了二进制日志记录,则确定的
特性影响MySQL接受哪些例程定义。看到第25.7节“存储程序二进制日志记录”.
类的例程现在()
函数(或其同义词)或RAND ()
不确定,但还是可以复制的。为现在()
,二进制日志包括时间戳并正确复制。RAND ()
也可以正确复制,只要在例程执行期间只调用一次。(您可以将例程执行时间戳和随机数种子视为源和副本上相同的隐式输入。)
有几个特征提供了关于例程使用数据的性质的信息。在MySQL中,这些特征只是建议的。服务器不使用它们来约束一个例程允许执行哪些类型的语句。
的SQL安全
特征可以是定义者
或调用程序
指定安全上下文;也就是说,该例程是否使用例程中指定的帐户的特权执行定义者
子句或调用它的用户。此帐户必须具有访问与例程关联的数据库的权限。默认值为定义者
.调用例程的用户必须具有执行
特权为之,必须为之定义者
如果例程在定义器安全上下文中执行,则指定帐户。
的定义者
子句指定在例程执行时检查访问权限时使用的MySQL帐户SQL安全定义器
的特点。
如果定义者
子句存在时,则用户
值应该是MySQL帐户指定为'
,user_name
“@”host_name
'CURRENT_USER
,或CURRENT_USER ()
.允许用户
值取决于您所拥有的特权,如中所讨论的第25.6节“存储对象访问控制”.有关存储例程安全性的其他信息,请参见该部分。
如果定义者
子句时,默认定义者是执行创建过程
或创建函数
声明。这和指定是一样的Definer = 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节“数据库字符集和排序规则”.