存储程序(1)——MYSQL

MySQL支持把几种对象存放在服务器端供以后使用。这几种对象有一些可以根据情况通过程序代码调用,有一些会在数据表被修改时自动执行,还有一些可以在预定时刻自动执行。它们包括以下几种:

1.存储函数(stored function)。返回一个计算结果,该结果可以用在表达式里。
2.存储过程(stored procedure)。不直接返回一个结果,但可以用来完成一般的运算或是生成一个结果集并传递回客户。
3.触发器(trigger)。与数据表相关联,当那个数据表被工NSERT、DELETE或UPDATE语句修改时,触发器将自动执行。
4.事件(event)。根据时间表在预定时刻自动执行。

MySQL对存储函数和存储过程的支持始于5.0.0版本,对触发器和事件的支持分别始于5.0.2版本和5.1.6版本。存储程序有以下优点和能力:

1.存储程序对象的可执行部分可以用复合语句来编写,复合语句对SQL语法进行了扩展,可以包括代码块、循环和条件语句。
2.存储程序都被保存在服务器端,定义它们所需要的代码只需在它们被创建时通过网络传递一次,而不是每次执行都要传递一次。这大大减少了开销。
3.它们可以把复杂的计算封装为程序单元,而你可以简单地通过程序单元的名字来调用它们。你甚至可以把一组存储程序打包为一个“函数库”供其他应用程序调用。
4.它们提供了一种错误处理机制。
5.它们可以提高数据库的安全性。你可以通过选择存储程序执行时所需的权限下来对敏感数据的访问情况进行限制和调控。

存储程序。泛指各种类型的存储对象(存储函数、存储过程、触发器、事件)。存储例程(stored routine ),特指存储函数和存储过程。这两种对象的定义语法很相似,所以很自然地把它们放在一起讨论。在开始讨论各种类型的存储程序之前,我们首先学习一下:复合语句。

1.复合语句和语句分隔符

简单的存储程序只包含一条SQL语句,在编写时不需要特殊对待。下面的存储过程使用了一条SELECT语句来列出sampdb数据库里的数据表的名字:

PROCEDURE sampdb_tables()
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA=’sampdb’ ORDER BY TABLE_NAME;

不过,存储程序并非只能包含一条简单的SQL语句。它们可以包含多条SQL语句,可以使用局部变量、条件语句、循环和嵌套语句块等多种语法构造。要使用这些构造编写存储程序,就需要用到复合语句。复合语句由BEGIN开头,END结束,在它们之间可以写出任意数量的语句,这些语句构成了一个语句块。下面的存储过程将显示一条欢迎消息,其中有你的用户名;如果你是一位匿名用户,用户名将是“earthing":

CREATE PROCEDURE greetings()
BEGIN#77=16  for username+60 for hostname+1 for '@'DECLARE user CHAR(77) CHARACTER SET utf8;SET user = (SELECT CURRENT USER());IF INSTR(user,’@’)>0 THEN#返回字符串在某一个字段的内容中的位置, 没有找到字符串返回0,否则返回位置(从1开始)SET user=SUBSTRING_INDEX(user, '@', 1);END IF;IF user = '' THENSET user='earthling';END IF;SELECT CONCAT('Greetings,',user, '!') AS greeting;
END;

在使用复合语句时,必须考虑和解决这样一个问题:复合语句块里的语句必须以分号(;)彼此隔开,但因为分号同时也是mysql程序默认使用的语句分隔符,所以在使用mysql程序定义存储程序时会发生冲突。
解决这个问题的办法是使用delimiter命令把mysql程序的语句分隔符重定义为另一个字符或字符串,它必须是在存储例程的定义里没有出现过的。这样一来,mysql程序就不会把分号解释为语句终止符了,它将把整个对象定义作为一条语句传递给服务器。在定义完存储程序之后,可以把mysql程序的语句终止符重新定义为分号。

use weibo;
delimiter $
CREATE PROCEDURE show_times()
BEGINSELECT 'Local time is:', CURRENT_TIMESTAMP;SELECT 'UTC time is:', UTC_TIMESTAMP;
END$
delimiter ;-- delimiter后空格加分号,将分号设置为分隔符
CALL show_times();

定义一个存储过程时把mysql程序的默认分隔符临时改变为$,然后在恢复了mysql程序的默认分隔符之后执行了那个存储过程:

Local time is:2014-01-15 23:00:26 
image

分隔符不必非得是$字符,也不必非得是单个的字符:

delimiter EOF

这里的原则是:只要在某个存储程序内部的语句里会用到分号,就应该在定义这个存储程序时临时改变mysql程序的分隔符。

2.存储函数和存储过程

存储函数将向调用者返回一个计算结果,这个结果可以用在表达式里(就像COS()或HEX()这样的内建函数那样)。存储过程需要使用CALL语句来调用,是一个独立的操作,不能用在表达式里。使用存储过程的情况主要有两种:(1)只需通过运算来实现某种效果或动作而无需返回一个值,(2)运算会返回多个结果集(函数做不到这一点)。这只是些指导性建议,不是硬性规定。
比如说,如果你需要返回两个或更多的值,就不能使用函数。但你可以使用一个过程,因为过程支持的参数类型允许它们的值在过程执行期间被设置,而调用者可以在过程返回后去访问那些值。

存储函数要用CREATE FUNCTION语句来创建,存储过程要用CREATE PROCEDURE语句来创建。下面的例子将创建一个函数,该函数有一个代表着年份的整数参数。(为了与数据表或数据列的名字有所区别,参数命名时将使用p_前缀)。

delimiter $
CREATE FUNCTION count_born_in_year(p_year INT)
RETURNS INT
READS SQL DATA
BEGINRETURN (SELECT COUNT(*) FROM president WHERE YEAR(birtb) = p_year);
END$
delimiter ;

这个函数有一条用来表明其返回值数据类型的RETURNS子句和一个用来计算那个值的函数体。函数体至少需要包含一条RETURN语句,用来向调用者返回一个值。把计算定义为函数的好处是可以方便地执行它而无须每次都写出所有的逻辑,你可以像使用内建函数那样来调用存储函数:

SELECT count_born_in_year(1990);

你无法让一个给定的函数返回多个值。你可以编写任意多个函数,然后在同一条语句里调用它们全体。另一个办法是使用一个存储过程并通过它的OUT参数“返回”多个值。存储过程负责计算那些值并把它们赋值给相应的参数,而那些参数可以在过程返回后由调用者访问。如果你定义了一个与某个MySQL内建函数同名的存储函数,在调用它时就必须用数据库的名字对该函数的名字进行限定以避免歧义。

存储过程和存储函数很相似,但它不返回值。因此,它没有RETURNS子句或任何RETURN语句。下面这个简单的存储过程和count_born_in_year()函数很相似,它将显示一个结果集而不是把计算结果作为其返回值。

delimiter $
CREATE PROCEDURE show_born_in_year(p_year INT)
BEGINSELECT first_name, last_name, birth, deathFROM presidentWHERE YEAR(birth)=P_year;
END$
delimiter ;

与存储函数不同,存储过程不能用在表达式里,它们只能通过CALL语句来调用。如下所示:

CALL show_born_in_year(1990);

前面的例子都是选取信息,但存储例程还可以用来修改数据表,如下例所示:

delimiter $
CREATE PROCEDURE update_expiration (p_id INT UNSIGNED, p_date DATE)
BEGINUPDATE member SET expiration=p_date WHERE member_id=p_id;
END$
delimiter ;

存储函数必须遵守这样一条限制:不允许对调用本函数的语句正在读或写的数据表进行修改。存储过程通常没有这个限制,但如果它们是从存储函数里被调用,就需要遵守这条限制。

3.存储函数和存储过程的权限

存储函数和存储过程属于数据库。要想创建存储函数或存储过程,必须拥有那个数据库的CREATE ROUTINE权限。在默认的情况下,当你创建一个存储例程时,服务器将自动地把EXECUTE和ALTER ROUTINE权限授予你(如果你还没有获得这些权限),这样你才可以执行那个例程或删除它。当你删除那个例程时,服务器将自动撤销那些权限。如果你不想使用这种自动化的权限授予/撤销机制,把automatic_sp_privileges系统变量设置为0即可。

如果服务器启用了二进制日志功能,存储函数还需要遵守一些额外的限制条件(不允许创建不确定或是会修改数据的存储函数)以保证二进制日志能够安全地完成备份和复制操作。这些限制条件如下:
1.如果log_bin_trust_function_creators系统变量没有被激活,你就必须具备SUPER权限才能创建存储函数。在此前提下,你创建的每一个函数都必须是确定的,并且不得修改数据。为了表明这一点,需要使用DETERMINISTIC、NO SQL或READS SQL DATA之一来定义存储函数。
2.如果log bin_trust_function_creators系统变量已被激活,则没有任何限制。只有当你可以相信MySQL服务器上的所有用户都不会去定义不安全的存储函数时,这种设置才是最适当的。

与log_bin_trust_function_creators系统变量有关的限制条件同样适用于触发器的创建工作。

4.存储过程的参数类型

存储过程的参数分为3种类型。对于IN参数,调用者把一个值传递给过程,过程可以对这个值进行修改,但任何修改在过程返回后对调用者是不可见的。OUT参数刚好相反,过程把一个值赋值给OUT参数,这个值在过程返回后可以由调用者访问。INOUT参数允许调用者向过程传递一个值,然后再取回一个值。
要想明确地为参数指定类型,在参数表里把IN, OUT或INOUT写在参数名字前面即可。如果没有为参数指定类型,其默认类型将是IN。

在使用OUT或INOUT参数时,在调用过程时需要给出一个变量名。过程可以设置参数的值,相应的变量将在过程返回时获得那个值。如果想让某个存储过程返回多个结果值,OUT和INOUT参数类型将非常有用(存储函数只能返回一个值,不能胜任)。下面的过程演示了OUT参数的用法。它将分别统计出student数据表里的男生和女生人数并通过它的参数返回这两个计数值,让调用者可以访问它们:

delimiter $
CREATE PROCEDURE count_students_by_sex(OUT p_male INT, OUT p_female INT)
BEGINSELECT COUNT(*) FROM student WHERE sex= 'F' INTO p_female;SELECT COUNT(*) FROM student WHERE sex= 'F' INTO p_female;
END$
delimiter ;

在调用这个过程时,请把各个参数替换为相应的用户定义变量。这个过程将把计数值放到这些参数里,在它返回之后,那些变量将包含计数值:

CALL count_students_by_sex(@mcoant, @fcount);
SELECT 'Number of male students:'@mcount;

IN、OUT和INOUT关键字不适用于存储函数、触发器或事件。对于存储函数,所有的参数都像IN参数。触发器和事件则根本没有任何参数。下一部分介绍:触发器和事件。

转载于:https://www.cnblogs.com/houkai/p/3523563.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

闯过这 54 关,点亮你的 Git 技能树 (五) - 完结篇

这是一个系列文章,介绍学习 Git 的一个小游戏 - githug,如果你是第一次看到,请先阅读:闯过这 54 关,点亮你的 Git 技能树闯过这 54 关,点亮你的 Git 技能树(一)闯过这 54 关&#xf…

Jupyter notebook 不安装主题,通过修改css更改 默认字体,字体大小等

目标: Jupyter notebook 又不想改更主题的的情况下,可以通过修改css的目的来达到修改默认的字体,字号心达到可以好的阅读效果。 方法 要修改的css文件目录如下, D:\Anaconda\Lib\site-packages\notebook\static\custom 这个就是…

坚果nuts 加速 官网_【喂你播】坚果手机2020新品发布会来了;三星定向华为手机推以旧换新...

周五喂diu 不只有你们爱的女主播 还有小编呢BGM:Make You Hustle-Croatia Squad坚果手机2020新品发布会来了坚果手机正式宣布:坚果手机2020新品发布会将于10月20日19:30在五棵松M空间举行。根据此前爆料,坚果手机新品或命名为坚果Pro4&#x…

图像处理核函数:之高斯核的生成方法 python

图像处理核函数:之高斯核函数的生成方法 python高斯核函数(低通高斯滤波器核)高斯分布函数高斯核生成函数代码效果高斯核函数的图像高斯核函数(低通高斯滤波器核) 最近在看DIP(Digital Image Processing)&…

WEB-INFO/lib build path 的jar包问题

为什么80%的码农都做不了架构师?>>> 一、build path&WEB-INFO/lib介绍 build path:可以说是引用; WEB-INFO/lib:可以说是固定在一个地方; eclipse编译项目的时候是根据build path的,如果…

Windows phone 7之页面布局

Windows phone的页面布局方式一般是依赖布局控件实现的,而布局控件有三种Grid,StackPanel和Canvas Grid是网格布局方式,相当于一个表格,有行和列,新建一个Windows phone项目,打开MainPage.xaml,…

苹果电脑删除软件_软件自动开启很烦人?如何彻底关掉开机自动开启的应用程序...

使用Mac的小伙伴有没有这样的烦恼,电脑一开机,一堆烦人的软件就自动开启了,让人很懊恼,如何才能彻底关掉开机自动开启的应用程序?mac开机启动项怎么设置?开机启动项要怎么禁止?今天就带大家解决…

csgo怎么控制电脑玩家_电脑远程控制怎么弄

本教程以“Win 10”系统为例进行演示。方法一:1/6在“此电脑”单击鼠标右键选择“属性”2/6在弹出窗口中点击“远程设置”3/6勾选“允许远程协助连接这台计算机”,然后点击应用并确定4/6在微软小娜搜索“mstsc”5/6打开“远程桌面连接”6/6输入对方的IP地…

MNIST 手写数字识别,我是如何做到886个可训练参数,识别率达到98.2%? (参数、模型压缩), Keras实现,模型优化

一 项目展示 下面可以看到验证集可以到了0.9823了,实际上,在下面的另外一个训练,可以得到0.9839,我保守的写了0.982 二 项目参数展示 我们先来看看LeNet 5 的结构与参数,参数有61,706个。 这个是我用…

javascript 计算两个坐标的距离 米_土方全面应用计算

各种土方量的计算方法汇总8.2.1 DTM法土方计算由DTM模型来计算土方量是根据实地测定的地面点坐标(X,Y,Z)和设计高程,通过生成三角网来计算每一个三棱锥的填挖方量,最后累计得到指定范围内填方和挖方的土方量,并绘出填…

unity 阳光插件_网络广告,阳光创信保驾护航

网络广告 就找阳光创信。网络营销的技术基础主要是以计算机网络技术为代表的信息技术。计算机网络是现代通信技术与计算机技术相结合的产物,它把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络,从而使众多的计算机…

第2章 Python 数字图像处理(DIP) --数字图像基础1 - 视觉感知要素 - 亮度适应与辨别

数字图像基础1视觉感知要素亮度适应与辨别import sys import numpy as np import cv2 import matplotlib import matplotlib.pyplot as plt import PIL from PIL import Imageprint(f"Python version: {sys.version}") print(f"Numpy version: {np.__version__…

快速幂与快速乘法

List 快速幂与快速乘法 ListKnowledge快速幂 原理code快速乘法 原理codeKnowledge 快速幂 原理 a^b%p 采用二进制得思想,将b转化为二进制数。 b c02^0c12^1c22^2c32^3……cn2^n a^b a^(a12^0)a^(c12^1)……a^(cn2^n) 所以我们可以在log(b)的时间内求出a^(2^0)…

Java程序设计 图形用户界面 小巫版简易计算器

/** 作者:wwj 时间:2012/4/13 功能:实现一个计算器应用程序实验要求:编写一个模拟计算器的应用程序,使用面板和网格布局, 添加一个文本框,10个数字按钮(0~9),…

phython在file同时写入两个_轻松支撑百万级数据点写入 京东智联云时序数据库HoraeDB架构解密...

本文将通过对时序数据的基本概念、应用场景以及京东智联云时序数据库HoraeDB的介绍,为大家揭秘HoraeDB的核心技术架构和解决方案。首先我们来了解下时序数据库的基本概念。时序数据库全称时间序列数据库,主要用于处理带时间标签的数据,带时间…

飞雪迎春

转载于:https://www.cnblogs.com/ysx4221/p/3537810.html

高可用集群技术之corosync应用详解(一)

Corosync概述:Corosync是集群管理套件的一部分,它在传递信息的时候可以通过一个简单的配置文件来定义信息传递的方式和协议等。它是一个新兴的软件,2008年推出,但其实它并不是一个真正意义上的新软件,在2002年的时候有一个项目Ope…

一天总结

这几天忙着弄毕业设计和论文,有好几天都没总结了!学习进度也慢了下来!接下几天把毕业答辩弄好后!把精力放在数据库和编程熟练度上!还有很多要学习的多看书多敲代码!最重要的是要多思考,要有自己…

电脑dns_win10系统dns错误如何解决「系统天地」

最近有位win10系统用户在使用电脑的过程当中,碰到了dns错误的情况,用户不知道如何解决,为此非常苦恼,那么win10系统dns错误如何解决呢?下面为大家分享win10电脑dns错误的解决方法。第一步:使用 ipconfig /flushdns 命…

第2章 Python 数字图像处理(DIP) --数字图像基础5 -- 算术运算、集合、几何变换、傅里叶变换等

目录数字图像处理所有的基本数字工具介绍算术运算集合运算和逻辑运算空间运算向量与矩阵运算图像变换图像和随机变量数字图像处理所有的基本数字工具介绍 算术运算 # 相加 img_ori cv2.imread("DIP_Figures/DIP3E_Original_Images_CH02/Fig0226(galaxy_pair_original).…