您的位置:首页 > 数据库 > MySQL

SQL Server与MySQL存储过程学习记录之一

2013-10-21 14:48 656 查看
SQL语句执行的时候要先编译,然后执行。

存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。

  SQL Server的存储过程在设计BNU校园百科的时候就有使用,因为存储过程不仅能提高SQL语言的执行效率,同时参数化的调用比每次都写一条SQL语句来得方便。

【SQL Server存储过程的建立】

  在企业管理器新建一个StoreProcedure会自动生成相应导航代码,方便用户编写函数。



-- ================================================

-- Template generated from Template Explorer using:

-- Create Procedure (New Menu).SQL

--

-- Use the Specify Values for Template Parameters 

-- command (Ctrl-Shift-M) to fill in the parameter 

-- values below.

--

-- This block of comments will not be included in

-- the definition of the procedure.

-- ================================================

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

-- =============================================

-- Author:   <Author,,Name>

-- Create date: <Create Date,,>

-- Description: <Description,,>

-- =============================================

CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName> 

-- Add the parameters for the stored procedure here

<@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>, 

<@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>

AS

BEGIN

-- SET NOCOUNT ON added to prevent extra result sets from

-- interfering with SELECT statements.

SET NOCOUNT ON;

    -- Insert statements for procedure here

SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>

END

GO

  我们现在设计一个带参数的存储过程,比如我们经常需要使用这样的一类查询:包含keyword的所有结果集,这个时候为该查询实现一个存储过程如下

CREATE PROCEDURE [dbo].[p_SearchByKeyWord]
@keyword nvarchar(200)
AS
BEGIN
SELECT * From [myTable] where [myWordColumn] like '%'+@keyword+'%'
END
GO

  在SQL Server中调用存储过程的方法是使用EXEC命令,比如我们要查包含“北京师范大学”的所有记录,我们运行如下T-SQL命令

EXEC p_SearchByKeyWord  @keyword = '北京师范大学'

  就能得到结果集如下:如果有多个参数,需要用逗号隔开分别传入,即

EXEC myProcedureName  @parameter1='×××',@parameter2='×××',......



  如果想要修改已经存在的存储过程,只要把CREATE换成ALTER即可,比如我们限定查询数量为100条记录,修改已经建立的p_SearchByKeyWord

ALTER PROCEDURE  [dbo].[p_SearchByKeyWord]
@keyword nvarchar(200)
AS
BEGIN
SELECT TOP 100 * From [myTable] where [myWordColumn] like '%'+@keyword+'%'
END
GO

  删除存储过程就更简单了,直接使用DROP命令,比如

DROP PROCEDURE
[dbo].[p_SearchByKeyWord]

【MySQL存储过程的建立】

  MySQL存储过车的创建、修改、删除语法与SQL Server类似,但是参数定义和调用方式都不一样,所以需要花时间看官方的手册!

  MYSQL没有提供微软企业管理那样的强大前端,当然就没有创建存储过程的向导,但是一旦熟悉了存储过程建立的方法,就觉得自己手写要方便得多。即使有很多第三方的MySQL前端,如Navicat提供了向导式的存储过程建立,但是为了了解底层的语法细节,手动编写每一步是很重要的。下面来看MySQL的存储过程建立方式。

  官方说明有这样一段

CREATE

    [DEFINER = { user | CURRENT_USER }]

    PROCEDURE sp_name ([proc_parameter[,...]])

    [characteristic ...] routine_body

    

proc_parameter:

    [ IN | OUT | INOUT ] param_name type

type:

    Any valid MySQL data type

characteristic:

    LANGUAGE SQL

| [NOT] DETERMINISTIC

| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }

| SQL SECURITY { DEFINER | INVOKER }

| COMMENT 'string'

routine_body:

    Valid SQL procedure statement

  很好理解,比如我们要创建一个简单的不带参数的存储过程p_Test,只需如下极短的代码

CREATE p_Test()

BEGIN

Select * FROM [myTable] LIMIT 100;

END;

  其中BEGINEND块是存储过程的核心,这个与SQL Server相同。另外,需要注意的是,不管有没有参数,存储过程名称后面需要有一个括号,这个与SQL Server是不相同的(有参数和没有参数均不需要任何括号),所以不要忘了。

  现在来创建一个带有参数的查询,记住,所有参数都要包含在刚才所说的括号中。比如我们需要统计在给定两个时间点的所有访问记录数,于是每次调用需要传入起始时间和结束时间,于是需要指定两个参数,如下 _starttime 和 _endtime ,这两个变量之前的 IN 用来修饰参数,表示是输入变量,也可以忽略(默认即输入),也可以显示指定为OUT(输出变量),INOUT(既作为输入,也作为输出,在某些复杂的程序中可能会遇到)

CREATE PROCEDURE p_GetVisitCountByTime(

IN _starttime datetime,

IN _endtime datetime

)

BEGIN

SELECT COUNT(VISIT_ID) AS total FROM myTable

             WHERE VISIT_TIME>=_starttime and 

             VISIT_TIME<_endtime and;

END;

  创建好之后就能调用了,注意MySQL调用存储过程的方法和SQL Server是不一样的,需要使用语法CALL,然后参数全部包含在括号里面,比如

CALL p_GetVisitCountByTime('2009-12-01 00:00:00','2009-12-02 00:00:00');

  这句话查询在09年12月1号到12月2号的总访问人数,清晰明了。

  最后说明一些要注意的地方,也是SQL Server与MySQL差异的地方,在编写存储过程的时候,SQL Server并不需要在每个块结束后使用分号,但是MySQL需要在每个块结束后使用分号标识,比如

CREATE p_Test()

BEGIN

Select * FROM [myTable] LIMIT 100;

END--这里没有分号

  那么会提示编译错误,同样,如果是这样

CREATE p_Test()

BEGIN

Select * FROM [myTable] LIMIT 100--这里没有分号

END;

  那么也会提示编译错误,所以在MySQL里一定不要忘了分号,当然SQL Server则不需要分号!

  更多关于存储过程里循环、条件、定义内部变量等高级的应用和使用上的差异会在学习记录之二再谈,其实也就是SQL Server和MySQL的编程语法!

  总结一下,由于存储过程是数据库的一个重要部分,因此不同的数据库都有起实现方式,但是思想是一致的,在学习不同数据库相应操作的时候,应该进行类比学习,这样在做特定应用的时候就能更加顺手!我也是现在经常遇到基于MySQL的项目才开始关注MySQL的各种细节!

  可以继续阅读学习记录之二

学习记录一中,讨论了SQL Server与MySQL各自建立存储过程的方法和过程,并简单做了一下对比。在实际应用中,查询往往是很复杂的,不可能用一简单的一行SQL语言就能满足我们的需求,这个时候,就需要使用SQL编程。

  实现SQL编程有两种方式,第一种就是用高级语言进行反复调用,因为我们熟悉一门或多门高级程序语言,比如C,C++,C#,PHP,Java等等,这些都是能调用数据库操作的。比如在C#这样的面向对象编程语言里,万物皆对象,在创建一个数据库调用程序时,首先需要新建一个连接,同时建立一条SQL操作指令,然后打开连接,执行该指令,最后返回结果,关闭连接。

  首先以C#调用SQL Server为例,比如我们要运行一条没有返回结果的SQL语句并赋值给sqlStr字符串变量,那么用简单的几行程序就能直接操作数据库了。(需要System.Data和System.Data.SqlClient命名空间)

SqlConnection sqlConn = new SqlConnection(connectStr);

SqlCommand sqlCmd = new SqlCommand(sqlStr, sqlConn);

sqlConn.Open();

sqlCmd.ExecuteNonQuery();

sqlConn.Close();

  于是,要进行复杂的SQL操作时,只要保持数据库的连接打开,不断改变SqlCommand命令来实现不同的操作,如动态生成sqlStr。

  同样的,使用C#连接MySQL数据库时,需要下载MySQL Connector NET,这是一个封装好的用来连接MySQL的类库,所有命令和连接SQL Server毫无差别,只需把Sql换成MySql即可,如下。(需要MySql.Data和MySql.Data.MySqlClient命名空间)

MySqlConnection sqlConn = new MySqlConnection(connectStr);

MySqlCommand sqlCmd = new MySqlCommand(sqlStr, sqlConn);

sqlConn.Open();

sqlCmd.ExecuteNonQuery();

sqlConn.Close();

  但是如果要批量执行SQL语言,通过高级语言循环方式传入不免带来效率上的劣势,因为每次传入的SQL语句都要先编译,然后运行,同时在传送SQL命令的时候也有时间代价(尤其是远程数据库),为何不只传送一条命令,然后在数据库里进行批量执行呢?这也就是存储过程的好处,可以把存储过程看成数据库操作的一个宏,或者批处理。当然,这要数据库支持才行。高兴的是,目前的所有企业级数据库都很好的支持了SQL编程,只是实现细节有差别。下面具体谈谈SQL Server与MySQL的SQL编程方法。

【SQL Server简单编程】

该部分转自http://www.cnblogs.com/Niyowong/archive/2007/08/20/862169.html,如果要学习更高级的内容可以购买人民邮电出版社的《SQL Server 2008基础教程》

1.局部变量

声明单个局部变量

declare @num int

声明多个局部变量

declare   @FirstName nvarchar(20)

                @LastName nvarchar(20)

                @Age int

局部变量赋值

被赋值的局部变量必须是已经声明的。

a.简单赋值方法

declare @UserName varchar(10)

set @UserName = 'Niyo Wong'

b.使用select语句赋值

delcare @NoOfRecords int

set @NoOfRecords = (select count(*) from tableName)

select @NoOfRecords = 20

declare @UserName varchar(20)

declare @UserId varchar(10)

select @UserName = userName from tbl_User where userId = '123401'

select @UserId = max(UserId) from tbl_User

注意:如果查询返回了多个值时,那么只有最后一个值赋给了变量。

c.使用update语句赋值

declare @qyt tinying

update tableName set @qty = fieldName where id = '1'

注意:update无法象select语句一样魏数据提供一些常用的转换,所以在使用update进行赋值时,

最好严格匹配数据类型,否则会产生错误。

2.全局变量

下面列举几个我们在编程中常用的全局变量

a. @@CURSOR_ROWS

返回本次服务器连接中,打开游标取回的数据行的数目。如:

select @@CURSOR_ROWS

declare employee_cursor cursor for

select emplid from tbl_Employee

open employee_cursor

fetch next from employee_cursor

select @@CURSOR_ROWS

close employee_cursor

deallocate employee_cursor

b. @@ERROR


返回上一条语句返回的错误号,执行成功返回0,

一般在insert,update,delete语句之后使用(常结合事务处理)。

c. @@FETCH_STATUS

返回上一次使用游标FETCH操作所返回的状态值。返回值为0表示操作成功,

为-1表示操作失败或者已经超过了游标所能操作的数据行的范围,当到了最后一行数据后,

还要接着取下一列数据,返回-2,表示返回值已经丢失。

d. @@ROWSCOUNT

返回上一条SQL语句所影响到的数据行的数据。常用于检查操作是否达到了目的,

当执行的SQL语句不影响数据库数据时,该变量返回0

e. @@VERSION

返回版本号

3.结构语句

a.条件结构
if.... else ...如:

if((select count(*) from table1) > 0)

begin

declare @num int

set @num = (select max(no) from tabl2)

if(@num >(select count(*) from table1))

begin

print '@num >(select count(*) from table1)'

end

else

if(@num = (select count(*) from table1))

begin

   print '@num = (select count(*) from table1)'

end

end

else

begin

print 'No of record below zero'

end

b.循环结构
while 语句。如:

declare @count int

set @count = 0

while(@count < 10)

begin

print @count

set @count = @count + 1 

end

在循环中常用的语句有break和continue,

break为跳出while,而continue为跳出当前循环,进入下一循环。

有时候也用到return和goto语句,下面我们将讲这两个语句。

c.case语句

case语句又叫条件分支语句。如:

select case userType 

when '1' then 'admin' 

when '2' then 'general user' 

else 'other' end 'userType' 

from tbl_user

或者

select 'userType' = case

when USERiD = '1' then 'admin'

when userName = 'Lucy' then 'admin'

when userType = '1' then 'admin'

when userType = '2' then 'general user'

else 'other' end

from tbl_user

注意:case语句中when匹配成功后,就到end,不会匹配下一个when,

所以如果有一条记录,userid = '1' 并且usertype = '2',

则返回uertype是‘admin'而不是’general user'

d.return语句

立即退出程序,return后面的语句将不执行。return 后常跟一个整形表达式作为返回值。

e.goto语句(最好不用goto语法)
跳转到跟在goto后面的标签位置。如

declare @count int

              @value int

set @count = (select count(*) from table)

if(@count = 0)

begin

    set @value = 0

    goto Flag

end

set @value = @count + 10

Flag:

print @value

【MySQL简单编程】

  MySQL编程与SQL Server类似,也要包含在所谓的区块BEGIN和END里,同时END后面必须要有分号(SQL Server不需要分号)。下面具体讲解变量定义、条件、循环的基本语法。

1、变量定义

declare varname vartype;

比如 declare a int--定义一个整型变量a,也可以用default来声明默认赋值,如 declare a int default 5

2、结构语句

a.定义区块

BEGIN

--sqlStr

END;

或自定义区块名称

LABEL:BEGIN

--sqlStr

END LABEL;

这样就可以用LEAVE LABEL;跳出区块,执行区块以后的代码

b.条件语句

if 条件 then

--my statement

else

--my statement

end if;

c.循环语句

[label:] WHILE expression DO

--sqlStr

END WHILE [label] ;



[label:] LOOP

--sqlStr

END LOOP [label];



[label:] REPEAT

--sqlStr

UNTIL expression

END REPEAT [label];

下面写一个综合的程序如下

create procedrue p_test()

begin

declare a int;

set a=0;

while a<10 do

set a = a+1;

end while;

select a;

end;

  可以看到,使用MySQL编程和SQL Server基本思想是一致的,语法有较大的区别。SQL Server不管是条件、循环等区块仍然要使用begin与end作为起始和结束的标识,而MySQL则直接用END something(如while,if,loop),当然,由于自己接触MySQL并不长,没有使用SQL Server那么熟练,所以写这些也是非常基础的部分,而在实际问题中会千变万化,所以还是需要更多的实践来不断提高。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: