loading

Logout succeed

Logout succeed. See you again!

ebook img

MySQL 5.0存储过程 PDF

pages59 Pages
release year2017
file size2.12 MB
languageChinese

Preview MySQL 5.0存储过程

存存存存储储储储过过过过程程程程 MySQL 5.0 新特性系列 第一部分 MySQL 5.0 MySQL 技技技技术术术术白白白白皮皮皮皮书书书书 Peter Gulutzan March, 2005 翻译:陈朋奕 西安电子科技大学 2005-5-6 (声明:属于个人翻译,不涉及任何商业目的,支持国内MySQL发展,请转载时注明出处,谢谢) Copyright 2005, MySQL AB 第 1 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 Table of Contents 目目目目录录录录 (目录不做翻译了,因为基本都是专有名词) Introduction ....................................................................................................3 A Definition and an Example ........................................................................3 Why Stored Procedures ................................................................................4 Why MySQL Statements are Legal in a Procedure Body...........................8 Characteristics Clauses ..............................................................................10 Parameters....................................................................................................13 The New SQL Statements ...........................................................................15 Scope ...........................................................................................................16 Loops.............................................................................................................21 Error Handling..............................................................................................29 Cursors .........................................................................................................35 Security .........................................................................................................41 Functions ......................................................................................................43 Metadata........................................................................................................44 Details ...........................................................................................................48 Style...............................................................................................................52 Tips when writing long routines.................................................................63 Bugs ..............................................................................................................64 Feature Requests .........................................................................................65 Resources .....................................................................................................65 Conclusion....................................................................................................66 About MySQL ...............................................................................................66 Copyright 2005, MySQL AB 第 2 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 Introduction 本书是为需要了解5.0版本新特性的MySQL老用户而写的。简单的来说是介绍了“存储 过程、触发器、视图、信息架构视图”,这是介绍MySQL 5.0新特性丛书的第一集。希望这 本书能像内行专家那样与您进行对话,用简单的问题、例子让你学到需要的知识。 为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示 较大的实用用例,在学习之前也许大家会认为这个用例很难,但是只要跟着课程去学,相 信很 快就能掌握。 Conventions and Styles约约约约定定定定和和和和编编编编程程程程风风风风格格格格 每次我想要演示实际代码时,我会对mysql客户端的屏幕就出现的代码进行调整,将字体改成 Courier,使他们看起来与普通文本不一样。在这里举个例子: mysql> DROP FUNCTION f; Query OK, 0 rows affected (0.00 sec) 如果实例比较大,则需要在某些行和段落间加注释,同时我会用将“<--”符号放在页面 的右边以表示强调。例如: mysql> CREATE PROCEDURE p () -> BEGIN -> /* This procedure does nothing */ <-- -> END;// Query OK, 0 rows affected (0.00 sec) 有时候我会将例子中的"mysql>"和"->"这些系统显示去掉,你可以直接将代码复制到mysql 客户端程序中(如果你现在所读的不是电子版的,可以在mysql.com网站下载相关脚本) 所以的例子都已经在Suse 9.2 Linux、Mysql 5.0.3公共版上测试通过。在您阅读本书的时候, Mysql已经有更高的版本,同时能支持更多OS了,包括Windows,Sparc,HP-UX。因此这里的 例子将能正常的运行在您的电脑上。但如果运行仍然出现故障,可以咨询你认识的资深Mysql 用户,以得到长久的支持和帮助。 A Definition and an Example 定定定定义义义义及及及及实实实实例例例例 存储过程是一种存储在书库库中的程序(就像正规语言里的子程序一样),准确的来说, MySQL支持的“routines(例程)”有两种:一是我们说的存储过程, 二是在其他SQL语句中 可以返回值的函数(使用起来和Mysql预装载的函数一样,如pi())。我在本书里面会更经常使用 存储过程,因为这是我们过去的习惯,相信大家也会接受。 Copyright 2005, MySQL AB 第 3 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 一个存储过程包括名字,参数列表,以及可以包括很多SQL语句的SQL语句集。 在这里对局部变量,异常处理,循环控制和IF条件句有新的语法定义。 下面是一个包括存储过程的实例声明: (译注:为了方便阅读,此后的程序不添任何中文注释) CREATE PROCEDURE procedure1 /* name 存储过程名*/ (IN parameter1 INTEGER) /* parameters 参数*/ BEGIN /* start of block 语句块头*/ DECLARE variable1 CHAR(10); /* variables变量声明 */ IF parameter1 = 17 THEN /* start of IF IF条件开始*/ SET variable1 = 'birds'; /* assignment 赋值*/ ELSE SET variable1 = 'beasts'; /* assignment 赋值*/ END IF; /* end of IF IF结束*/ INSERT INTO table1 VALUES (variable1);/* statement SQL语句*/ END /* end of block 语句块结束*/ 下面我将会介绍你可以利用存储过程做的工作的所有细节。同时我们将介绍新的数据库对 象——触发器,因为触发器和存储过程的关联是必然的。 Why Stored Procedures 为为为为什什什什么么么么要要要要用用用用存存存存储储储储过过过过程程程程 由于存储过程对于MySQL来说是新的功能,很自然的在使用时你需要更加注意。 毕竟, 在此之前没有任何人使用过,也没有很多大量的有经验的用户来带你走他们走过的 路。然而你应该开始考虑把现有程序(可能在服务器应用程序中, 用户自定义函数 (UDF)中,或是脚本中)转移到存储过程中来。这样做不需要原因, 你不得不去做。 存存存存储储储储过过过过程程程程是是是是已已已已经经经经被被被被认认认认证证证证的的的的技技技技术术术术!!!!虽然在Mysql中它是新的,但是相同功能的函数 在其他DBMS中早已存在,而它们的语法往往是相同的。因此你可以从 其他人那里获 得这些概念,也有很多你可以咨询或者雇用的经验用户,还有许多第三方的文档可供 你阅读。 存存存存储储储储过过过过程程程程会会会会使使使使系系系系统统统统运运运运行行行行更更更更快快快快!!!!虽然我们暂时不能在Mysql上证明这个优势,用户得到的 体验也不一样。我们可以说的就是Mysql服务器在缓存机制上做了改进,就像Prepared statements(预处理语句)所做的那样。由于没有编译器,因此SQL存储过程不会像 外部语言(如C)编写的程序运行起来那么快。但是提升速度的主要方法却在于能否降 低网络信息流量。如果你需要处理的是需要检查、循环、多语句但没有用户交互的重 复性任务,你就可以使用保存在服务器上的存储过程来完成。这样在执行任务的每一步 时服务器和客户端之间就没那么多的信息来往了。 存存存存储储储储过过过过程程程程是是是是可可可可复复复复用用用用的的的的组组组组件件件件!!!!想象一下如果你改变了主机的语言,这对存储过程不会 产生影响,因为它是数据库逻辑而不是应用程序。存储过程是可以移植的!当你用SQL 编写存储过程时,你就知道它可以运行在Mysql支持的任何平台上,不需要你额外添加 运行环境包,也不需要为程序在操作系统中执行设置许可,或者为你的不同型号的电脑 配置不同的包。这就是与Java、C或PHP等外部语言相比使用SQL语句的优势。不过, 使用外部语言例程的好处还是很好的选择,它们只是没有以上的优点而已。 Copyright 2005, MySQL AB 第 4 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 存存存存储储储储过过过过程程程程将将将将被被被被保保保保存存存存!!!!如果你编写好了一个程序,例如显示银行事物处理中的支票撤消, 那想要了解支票的人就可以找到你的程序。 它会以源代码的形式保存在数据库中。这 将使数据和处理数据的进程有意义的关联这可能跟你在课上听到的规划论中说的一样。 存存存存储储储储过过过过程程程程可可可可以以以以移移移移植植植植!!!!Mysql完全支持SQL 2003标准。某些数据库(如DB2、Mimer) 同样支持。但也有部分不支持的,如Oracle、SQL Server不支持。我们将会给予足够 帮助和工具,使为其他DBMS编写的代码能更容易转移到Mysql上。 Setting up with MySQL 5.0 设设设设置置置置并并并并开开开开始始始始MySQL 5.0服服服服务务务务 通过mysql_fix_privilege_tables或者~/mysql-5.0/scripts/mysql_install_db来开始MySQL服务 作为我们练习的准备工作的一部分,我假定MySQL 5.0已经安装。如果没有数据库管理员 为你安装好数据库以及其他软件,你就需要自己去安装了。不过你很容易忘掉一件事, 那就是你需要有一个名为mysql.proc的表。 在安装了最新版本后,你必须运行mysql_fix_privilege_tables或者mysql_install_db(只需要 运行其中一个就够了)——不然存储过程将不能工作。我同时启用在root身份后运行一个 非正式的SQL脚本,如下: mysql>source/home/pgulutzan/mysql- 5.0/scripts/mysql_prepare_privilege_tables_for_5.sql Starting the MySQL Client 启启启启动动动动MySQL客客客客户户户户端端端端 这是我启动mysql客户端的方式。你也许会使用其他方式,如果你使用的是二进制版本或者是 Windows系统的电脑,你可能会在其他子目录下运行以下程序: pgulutzan@mysqlcom:~> /usr/local/mysql/bin/mysql --user=root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 5.0.3-alpha-debug Type 'help;' or '\h' for help. Type '\c' to clear the buffer. 在演示中,我将会展示以root身份登陆后的mysql客户端返回的结果,这样意味着我有极大的 特权。 Check for the Correct Version 核核核核对对对对版版版版本本本本 为了确认使用的MySQL的版本是正确的,我们要查询版本。我有两种方法确认我使用的 是 5.0版本: SHOW VARIABLES LIKE 'version'; or SELECT VERSION(); Copyright 2005, MySQL AB 第 5 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 例如: mysql> SHOW VARIABLES LIKE 'version'; +---------------+-------------------+ | Variable_name | Value | +---------------+-------------------+ | version | 5.0.3-alpha-debug | +---------------+-------------------+ 1 row in set (0.00 sec) mysql> SELECT VERSION(); +-------------------+ | VERSION() | +-------------------+ | 5.0.3-alpha-debug | +-------------------+ 1 row in set (0.00 sec) 当看见数字'5.0.x'后就可以确认存储过程能够在这个客户端上正常工作。 The Sample "Database" 示示示示例例例例数数数数据据据据库库库库 现在要做的第一件事是创建一个新的数据库然后设定为默认数据库实现这个步骤的 SQL语句如下: CREATE DATABASE db5; USE db5; 例如: mysql> CREATE DATABASE db5; Query OK, 1 row affected (0.00 sec) mysql> USE db5; Database changed 在这里要避免使用有重要数据的实际的数据库然后我们创建一个简单的工作表。 实现这个步骤的SQL语句如下: mysql> CREATE DATABASE db5; Query OK, 1 row affected (0.01 sec) mysql> USE db5; Database changed mysql> CREATE TABLE t (s1 INT); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO t VALUES (5); Query OK, 1 row affected (0.00 sec) 你会发现我只在表中插入了一列。这样做的原因是我要保持表的简单,因为在这里并不需要 展示查询数据的技巧,而是教授存储过程,不需要使用大的数据表,因为它本身已经够复杂了。 Copyright 2005, MySQL AB 第 6 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 这就是示例数据库,我们将从这个名字为t的只包含一列的表开始 Pick a Delimiter 选选选选择择择择分分分分隔隔隔隔符符符符 现在我们需要一个分隔符,实现这个步骤的SQL语句如下: DELIMITER // 例如: mysql> DELIMITER // 分隔符是你通知mysql客户端你已经完成输入一个SQL语句的字符或字符串符号。一直以来 我们都使用分号“;”,但在存储过程中,这会产生不少问题,因为存储过程中有许多语 句,所以每一个都需要一个分号因此你需要选择一个不太可能出现在你的语句或程序中的 字符串作为分隔符。我曾用过双斜杠“//”,也有人用竖线“|”。我曾见过在DB2程序中使用 “@”符号的,但我不喜欢这样。你可以根据自己的喜好来选择,但是在这个课程中为了更 容易理解,你最好选择跟我一样。如果以后要恢复使用“;”(分号)作为分隔符,输入下 面语句就可以了: "DELIMITER ;//". CREATE PROCEDURE Example 创创创创建建建建程程程程序序序序实实实实例例例例 CREATE PROCEDURE p1 () SELECT * FROM t; // 也许这是你使用Mysql创建的第一个存储过程。假如是这样的话,最好在你的日记中记下这个 重要的里程碑。 CREATE PROCEDURE p1 () SELECT * FROM t; // <-- SQL语句存储过程的第一部分是 “CREATE PROCEDURE”: CREATE PROCEDURE p1 () SELECT * FROM t; // <-- 第二部分是过程名,上面新存储过程的名字是p1。 Digression: Legal Identifiers 题题题题外外外外话话话话::::合合合合法法法法标标标标识识识识符符符符的的的的问问问问题题题题 存储过程名对大小写不敏感,因此‘P1’和‘p1’是同一个名字,在同一个数据库中你将 不能给两个存储过程取相同的名字,因为这样将会导致重载。某些DBMS允许重载(Oracle 支持),但是MySQL不支持(译者话:希望以后会支持吧。)。 你可以采取 “数据库名.存储过程名”这样的折中方法,如“db5.p1”。存储过程名可以分开,它可以 包括空格符,其长度限制为64个字符,但注意不要使用MySQL内建函数的名字,如果这样 做了,在调用时将会出现下面的情况: Copyright 2005, MySQL AB 第 7 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 mysql> CALL pi(); Error 1064 (42000): You have a syntax error. mysql> CALL pi (); Error 1305 (42000): PROCEDURE does not exist. 在上面的第一个例子里,我调用的是一个名字叫pi的函数,但你必须在调用的函数名后加上 空格,就像第二个例子那样。 CREATE PROCEDURE p1 () SELECT * FROM t; // <-- 其中“()”是“参数列表”。 CREATE PROCEDURE 语句的第三部分是参数列表。通常需要在括号内添加参数。例子中 的存储过程没有参数,因此参数列表是空的——所以我只需要键入空括号,然而这是必须的。 CREATE PROCEDURE p1 () SELECT * FROM t; // <-- "SELECT * FROM t;"是存储过程的主体。 然后到了语句的最后一个部分了,它是存储过程的主体,是一般的SQL语句。过程体中语句 "SELECT * FROM t;"包含一个分号,如果后面有语句结束符号(//)时可以不写这个分号。 如果你还记得我把这部分叫做程序的主体将会是件好事,因为(body)这个词是大家使用的 技术上的术语。通常我们不会将SELECT语句用在存储过程中,这里只是为了演示。所以使 用这样的语句,能在调用时更好的看出程序是否正常工作。 Why MySQL Statements are Legal in a Procedure Body 什什什什么么么么MySQL语语语语句句句句在在在在存存存存储储储储过过过过程程程程体体体体中中中中是是是是合合合合法法法法的的的的???? 什么样的SQL语句在Mysql存储过程中才是合法的呢?你可以创建一个包含INSERT, UPDATE, DELETE, SELECT, DROP, CREATE, REPLACE等等的语句。你唯一需要记住的是如果代码中 包含MySQL扩充功能,那么代码将不能移植。在标准SQL语句中:任何数据库定义语言都是 合法的,如: CREATE PROCEDURE p () DELETE FROM t; // SET、COMMIT以及ROLLBACK也是合法的,如: CREATE PROCEDURE p () SET @x = 5; // MySQL的附加功能:任何数据操作语言的语句都将合法。 CREATE PROCEDURE p () DROP TABLE t; // MySQL扩充功能:直接的SELECT也是合法的: CREATE PROCEDURE p () SELECT 'a'; // 顺便提一下,我将存储过程中包括DDL语句的功能称为MySQL附加功能的原因是在SQL标 准中把这个定义为非核心的,即可选组件。 Copyright 2005, MySQL AB 第 8 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 在过程体中有一个约束,就是不能有对例程或表操作的数据库操作语句。例如下面的例子就 是非法的: CREATE PROCEDURE p1 () CREATE PROCEDURE p2 () DELETE FROM t; // 下面这些对MySQL 5.0来说全新的语句,在过程体中是非法的: CREATE PROCEDURE, ALTER PROCEDURE, DROP PROCEDURE, CREATE FUNCTION, DROP FUNCTION, CREATE TRIGGER, DROP TRIGGER. 不过你可以使用 "CREATE PROCEDURE db5.p1 () DROP DATABASE db5//",但是类似"USE database"语句 也是非法的,因为MySQL假定默认数据库就是过程的工作场所。 Call the Procedure 调调调调用用用用存存存存储储储储过过过过程程程程 1. 现现现现在在在在我我我我们们们们就就就就可可可可以以以以调调调调用用用用一一一一个个个个存存存存储储储储过过过过程程程程了了了了,,,,你你你你所所所所需需需需要要要要输输输输入入入入的的的的全全全全部部部部就就就就是是是是CALL和和和和你你你你过过过过程程程程名名名名以以以以及及及及一一一一 个个个个括括括括号号号号再再再再一一一一次次次次强强强强调调调调,,,,括括括括号号号号是是是是必必必必须须须须的的的的当当当当你你你你调调调调用用用用例例例例子子子子里里里里面面面面的的的的p1过过过过程程程程时时时时,,,,结结结结果果果果是是是是屏屏屏屏幕幕幕幕返返返返回回回回了了了了t表表表表的的的的内内内内容容容容 mysql> CALL p1() // +------+ | s1 | +------+ | 5 | +------+ 1 row in set (0.03 sec) Query OK, 0 rows affected (0.03 sec) 因为过程中的语句是"SELECT * FROM t;" 2. 其其其其他他他他实实实实现现现现方方方方式式式式 mysql> CALL p1() // 和下面语句的执行效果一样: mysql> SELECT * FROM t; // 所以,你调用p1过程就相当于你执行了下面语句: "SELECT * FROM t;". 好了,主要的知识点“创建和调用过程方法”已经清楚了。我希望你能对自己说这相当简 单。但是很快我们就有一系列的练习,每次都加一条子句,或者改变已经存在的子句。 那样在写复杂部件前我们将会有很多可用的子句。 Copyright 2005, MySQL AB 第 9 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息 Characteristics Clauses 特特特特征征征征子子子子句句句句 1. CREATE PROCEDURE p2 () LANGUAGE SQL <-- NOT DETERMINISTIC <-- SQL SECURITY DEFINER <-- COMMENT 'A Procedure' <-- SELECT CURRENT_DATE, RAND() FROM t // 这里我给出的是一些能反映存储过程特性的子句。子句内容在括号之后,主体之前。这些 子句都是可选的,他们有什么作用呢? 2. CREATE PROCEDURE p2 () LANGUAGE SQL <-- NOT DETERMINISTIC SQL SECURITY DEFINER COMMENT 'A Procedure' SELECT CURRENT_DATE, RAND() FROM t // 很好,这个LANGUAGE SQL子句是没有作用的。仅仅是为了说明下面过程的主体使用SQL语 言编写。这条是系统默认的,但你在这里声明是有用的,因为某些DBMS(IBM的DB2)需要 它,如果你关注DB2的兼容问题最好还是用上。此外,今后可能会出现除SQL外的其他语言 支持的存储过程 。 3. CREATE PROCEDURE p2 () LANGUAGE SQL NOT DETERMINISTIC <-- SQL SECURITY DEFINER COMMENT 'A Procedure' SELECT CURRENT_DATE, RAND() FROM t // 下一个子句,NOT DETERMINISTIC,是传递给系统的信息。这里一个确定过程的定义就是那 些每次输入一样输出也一样的程序。在这个案例中,既然主体中含有SELECT语句,那返回 肯定是未知的因此我们称其NOT DETERMINISTIC。但是MySQL内置的优化程序不会注意这 个,至少在现在不注意。 Copyright 2005, MySQL AB 第 10 页 如有错误请来信[email protected],谢谢您的支持和阅读,同时感谢您对MySQL事业的关注 请转载时保留这些信息

See more

The list of books you might like