在ASP中,一般通过cmd对象调用存储过程,根据不同情况,本文也介绍其它调用方法。
1. 只返回单一记录集的存储过程
===============================================================================【1】
Create PROCEDURE dbo.getUserList
AS
SET NOCOUNT ON
BEGIN
SELECT * FROM dbo.[userinfo]
END
a、通过 Command 对象调用;
===========================================================
dim cmd,rs
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = con_string 'con_string 数据库连接字串
cmd.cmdText = "getUserList" '指定存储过程名
cmd.cmdType = 4 '表明这是一个存储过程
cmd.Prepared = true '要求将SQL命令先行编译
Set rs = cmd.Execute '执行调用
Set rs = Nothing
Set cmd = Nothing
-----------------------------------------------------------
CommandType属性表明请求的类型,取值及说明如下:
-1 表明CommandText参数的类型无法确定
1 表明CommandText是一般的命令类型
2 表明CommandText参数是一个存在的表名称
4 表明CommandText参数是一个存储过程的名称
b、通过Connection对象调用;
===========================================================
dim con,rs
Set con = Server.CreateObject("ADODB.Connection")
con.open con_string 'con_string是数据库连接字串
Set rs = con.Execute("getUserList",0,4) '最后一个参断含义同CommandType
Set rs = Nothing
Set con = Nothing
c、通过Recordset对象调用;
===========================================================
dim rs
Set rs = Server.CreateObject("ADODB.Recordset")
rs.open "getUserList",con_string,0,1,4
Set rs = Nothing
'con_string是数据库连接字串,最后一个参断含义与CommandType相同
2. 没有输入输出的存储过程
===============================================================================【2】
Create PROCEDURE dbo.delUserAll
AS
SET NOCOUNT ON
BEGIN
DELETE FROM dbo.[userinfo]
END
调用过程
===========================================================
当然也可通过Connection对象或Recordset对象调用此类存储过程,不过建立Recordset
对象是为了取得记录集,在没有返回记录集的情况下,还是利用Command对象吧
-----------------------------------------------------------
dim cmd
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = con_string
cmd.CommandText = "delUserAll"
cmd.CommandType = 4
cmd.Prepared = true
cmd.Execute '此处不必再取得记录集
Set cmd = Nothing
3. 有返回值的存储过程
===============================================================================【3】
01、对于带参数的存储过程,只能使用Command对象调用(也有资料说可通过Connection对象或Recordset对象调用,但我没有试成过)。
02、以下存储过程,在delete顺利执行时,返回1,否则返回0,并进行回滚操作。
-------------------------------------------------------------------------------
Create PROCEDURE dbo.delUserAll
AS
SET NOCOUNT ON
BEGIN
BEGIN TRANSACTION
DELETE FROM dbo.[userinfo]
IF error=0
BEGIN
COMMIT TRANSACTION
return 1
END
ELSE
BEGIN
ROLLBACK TRANSACTION
return 0
END
return
END
调用过程
===========================================================
dim cmd,pr,value
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = con_string
cmd.CommandText = "delUserAll"
cmd.CommandType = 4
cmd.Prepared = true
Set pr = cmd.CreateParameter("RETURN",2,4) '声明返回值
cmd.Parameters.Append pr
cmd.Execute
value = cmd(0) '或retValue = cmd.Parameters(0),取得返回值
Set cmd = Nothing
-----------------------------------------------------------
在 cmd.CreateParameter("RETURN",2,4) 中,各参数的含义如下:
第一个参数("RETURN")为参数名。参数名可以任意设定,但一般应与存储过程中声明的参数名相同。此处是返回值,我习惯上设为"RETURN";
第二个参数(2),表明该参数的数据类型,具体的类型代码请参阅ADO参考,以下给出常用的类型代码:
adBigInt: 20 ;
adBinary: 128 ;
adBoolean: 11 ;
adChar: 129 ;
adDBTimeStamp: 135 ;
adEmpty: 0 ;
adInteger: 3 ;
adSmallInt: 2 ;
adTinyInt: 16 ;
adVarChar: 200 ;
对于返回值,只能取整形,且-1到-99为保留值;
第三个参数(4),表明参数的性质,此处4表明这是一个返回值。此参数取值的说明如下:
0: 类型无法确定;
1: 输入参数;
2: 输入参数;
3:输入或输出参数;
4: 返回值
4. 有输入参数和输出参数的存储过程
===============================================================================【4】
返回值其实是一种特殊的输出参数。在大多数情况下,我们用到的是同时有输入及输出参数的存储过程,比如我们想取得用户信息表中,某ID用户的用户名,这时候,有一个输入参数“用户ID”,和一个输出参数“用户名”
-------------------------------------------------------------------------------
Create PROCEDURE dbo.getUserName @UserID int, @UserName varchar(40) output
AS
SET NOCOUNT ON
BEGIN
IF @UserID IS NULL return
SELECT @UserName=username FROM dbo.[userinfo] WHERE userid=@UserID
return
END
调用过程
===========================================================
dim cmd,UserID,UserName
UserID = 1
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = con_string
cmd.CommandText = "getUserName"
cmd.CommandType = 4
cmd.Prepared = true
cmd.Parameters.append cmd.CreateParameter("@UserID",3,1,4,UserID) '声明参数
cmd.Parameters.append cmd.CreateParameter("@UserName",200,2,40)
cmd.Execute
UserName = cmd(1) '取得出参数
Set cmd = Nothing
-----------------------------------------------------------
01、在以上代码中,可以看到,与声明返回值不同,声明输入参数时需要5个参数,声明输出
参数时需要4个参数。声明输入参数时5个参数分别为:参数名、参数数据类型、参数类型、
数据长度、参数值。声明输出参数时,没有最后一个参数:参数值。
02、需要特别注意的是:在声明参数时,顺序一定要与存储过程中定义的顺序相同,而且各参数
的数据类型、长度也要与存储过程中定义的相同。
-----------------------------------------------------------【扩展】
01、如果存储过程有多个参数,ASP代码会显得繁琐,可以使用with命令简化代码:
02、如果需要多次调用同一存储过程,只需改变输入参数
-----------------------------------------------------------
dim cmd,UserID,UserName
UserID = 1
Set cmd = Server.CreateObject("ADODB.Command")
for UserID = 1 to 10
with cmd
.ActiveConnection = con_string
.CommandText = "getUserName"
.CommandType = 4
.Prepared = true
if UserID = 1 then
.Parameters.append .CreateParameter("@UserID",3,1,4,UserID)
.Parameters.append .CreateParameter("@UserName",200,2,40)
.Execute
else
'重新给入参赋值(此时参数值不发生变化的入参以及出参不必重新声明)
.Parameters("@UserID") = UserID
.Execute
end if
end with
UserName = UserName + cmd(1) + "," '也许你喜欢用数组存储
next
Set cmd = Nothing
5. 同时具有返回值、输入参数、输出参数的存储过程
===============================================================================【5】
01、在调用存储过程时,声明参数的顺序要与存储过程中定义的顺序相同。
02、如果存储过程同时具有返回值以及输入、输出参数,返回值要最先声明。
-------------------------------------------------------------------------------
Create PROCEDURE dbo.getUserName @UserName varchar(40) output, @UserID int
--为了加深对"顺序"的印象,将以下两参数的定义顺序颠倒一下
AS
SET NOCOUNT ON
BEGIN
IF @UserID IS NULL return
SELECT @UserName=username FROM dbo.[userinfo] WHERE userid=@UserID
IF @@RowCount> 0
return 1
ELSE
return 0
return
END
调用过程
===========================================================
dim cmd,UserID,UserName
UserID = 1
Set cmd = Server.CreateObject("ADODB.Command")
with cmd
.ActiveConnection = con_string
.CommandText = "getUserName"
.CommandType = 4
.Prepared = true
.Parameters.Append .CreateParameter("RETURN",2,4) '返回值要最先被声明
'以下两参数的声明顺序也做相应颠倒
.Parameters.append .CreateParameter("@UserName",200,2,40)
.Parameters.append .CreateParameter("@UserID",3,1,4,UserID)
.Execute
end with
if cmd(0) = 1 then
UserName = cmd(1)
else
UserName = "该用户不存在"
end if
Set cmd = Nothing
6. 同时返回参数和记录集的存储过程
===============================================================================【6】
01、有时候,我们需要存储过程同时返回参数和记录集,比如在利用存储过程分页时,要同时返回记录集以及数据总量等参数。
02、在上面的存储过程中,输入当前页号及每页记录数,返回当前页的记录集,总页数及记录总数。
-------------------------------------------------------------------------------
Create PROCEDURE dbo.getUserList
@iPageCount int OUTPUT, --总页数
@iPage int, --当前页号
@iPageSize int --每页记录数
AS
SET NOCOUNT ON
BEGIN
--创建临时表
CREATE TABLE #t (ID int IDENTITY, userid int, username varchar(40))
--向临时表中写入数据
INSERT INTO #t SELECT userid,username FROM dbo.[UserInfo] ORDER BY userid
--取得记录总数
DECLARE @iRecordCount int
SET @iRecordCount = @@rowcount
--确定总页数
IF @iRecordCount%@iPageSize=0
SET @iPageCount=CEILING(@iRecordCount/@iPageSize)
ELSE
SET @iPageCount=CEILING(@iRecordCount/@iPageSize)+1
--若请求的页号大于总页数,则显示最后一页
IF @iPage > @iPageCount
SELECT @iPage = @iPageCount
--确定当前页的始末记录
DECLARE @iStart int --start record
DECLARE @iEnd int --end record
SELECT @iStart = (@iPage - 1) * @iPageSize
SELECT @iEnd = @iStart + @iPageSize + 1
--取当前页记录
SELECT * FROM #t WHERE ID> @iStart AND ID <@iEnd
--删除临时表
DROP TABLE #t
--返回记录总数
return @iRecordCount
END
调用过程
===========================================================
dim pagenumber,pagesize,pagecount,recordcount
dim cmd,rs
pagenumber = Request("pn") '自定义函数用于验证自然数
if isNumeric(pagenumber) = false then pagenumber = 1
pagesize = 20
Set cmd = Server.CreateObject("ADODB.Command")
with cmd
.ActiveConnection = con_string
.CommandText = "getUserList"
.CommandType = 4
.Prepared = true
.Parameters.Append .CreateParameter("RETURN",2,4) '返回值(记录总量)
.Parameters.Append .CreateParameter("@iPageCount",3,2) '出参(总页数)
.Parameters.append .CreateParameter("@iPage",3,1,4,pagenumber) '入参(当前页号)
.Parameters.append .CreateParameter("@iPageSize",3,1,4,pagesize) '入参(每页记录数)
Set rs = .Execute
end with
if rs.state = 0 then '未取到数据,rs关闭
recordcount = -1
else
rs.close '注意:若要取得参数值,需先关闭记录集对象
recordcount = cmd(0)
pagecount = cmd(1)
if cint(pagenumber)> =cint(pagecount) then pagenumber=pagecount
end if
Set cmd = Nothing
if recordcount = 0 then '以下显示记录
Response.Write "无记录"
elseif recordcount > 0 then
rs.open
do until rs.EOF
......
loop
......
else 'recordcount=-1 '以下显示分页信息
Response.Write "参数错误"
end if
-----------------------------------------------------------
对于以上代码,只有一点需要说明:同时返回记录集和参数时,若要取得参数,需先将记录集关闭,使用记录集时再将其打开。
7. 返回多个记录集的存储过程
===============================================================================【7】
Create PROCEDURE dbo.getUserInfo @userid int, @checklogin bit
AS
SET NOCOUNT ON
BEGIN
IF @userid IS NULL OR @checklogin IS NULL return
SELECT username FROM dbo.[usrinfo] WHERE userid=@userid
--若为登录用户,取usertel及usermail
IF @checklogin=1
SELECT usertel,usermail FROM dbo.[userinfo] WHERE userid=@userid
return
END
调用过程
===========================================================
dim checklg,UserID,UserName,UserTel,UserMail
dim cmd,rs
UserID = 1
'checklogin()为自定义函数,判断访问者是否登录
checklg = checklogin()
Set cmd = Server.CreateObject("ADODB.Command")
with cmd
.ActiveConnection = con_string
.CommandText = "getUserInfo"
.CommandType = 4
.Prepared = true
.Parameters.append .CreateParameter("@userid",3,1,4,UserID)
.Parameters.append .CreateParameter("@checklogin",11,1,1,checklg)
Set rs = .Execute
end with
Set cmd = Nothing
UserName = rs(0) '从第一个记录集中取值
if not rs is Nothing then '从第二个记录集中取值
Set rs = rs.NextRecordset()
UserTel = rs(0)
UserMail = rs(1)
end if
Set rs = Nothing
-----------------------------------------------------------
以上代码中,利用Recordset对象的NextRecordset方法,取得了存储过程返回的多个记录集。
8. 总结
===============================================================================【8】
在一个ASP程序中,调用多个存储过程至少有以下三种方法是可行的:
1. 创建多个Command对象
===========================================================
dim cmd
Set cmd = Server.CreateObject("ADODB.Command")
'调用存储过程一
......
Set cmd = Nothing
Set cmd = Server.CreateObject("ADODB.Command")
'调用存储过程二
......
Set cmd = Nothing
......
2. 只创建一个Command对象,结束一次调用时,清除其参数
===========================================================
此时要注意:清除参数的顺序与参数声明的顺序相反,原因嘛,我也不知道。
-----------------------------------------------------------
dim cmd
Set cmd = Server.CreateObject("ADODB.Command")
'调用存储过程一
.....
'清除参数(假设有三个参数)
cmd.Parameters.delete 2
cmd.Parameters.delete 1
cmd.Parameters.delete 0
'调用存储过程二并清除参数
......
Set cmd = Nothing
3. 利用Parameters数据集合的Refresh方法重置Parameter对象
===========================================================
dim cmd
Set cmd = Server.CreateObject("ADODB.Command")
'调用存储过程一
.....
'重置Parameters数据集合中包含的所有Parameter对象
cmd.Parameters.Refresh
'调用存储过程二
.....
Set cmd = Nothing
总结:
===========================================================
01、一般认为,重复创建对象是效率较低的一种方法,但是经测试(测试工具为Microsoft Application Center Test),结果出人意料:
方法2 > = 方法1 > > 方法3
02、方法2的运行速度大于等于方法1(最多可高4%左右),这两种方法的运行速度远大于方法3(最多竟高达130%),所以建议在参数多时,采用方法1,在参数较少时,采用方法2。 |