8.4 命令对象
在 8.12节中曾经提到命令对象负责对
数据库提供请求,也就是说它定义了将对
数据源执行的指定命令,这些命令可以是
SQL语句、表或存储过程。命令对象提供
了一种简单有效的方法来处理查询或存储
过程,通过该对象可以方便地查询数据库
并返回记录集,并对该记录集执行有关操
作。
8.4.1 命令对象的属性和方法
命令对象既可以利用已经创建的连接对象
来创建, 也可以不用先创建连接对象就直接使
用 命 令 对 象, 只 需 设 置 命 令 对 象 的
ActiveConnection属性为一个连接字串即可, 这
时 ADO将自动创建一个隐含的连接对象, 但不
会分配一个对象变量给它 。 因此如果多个命令
对象要使用相同的连接, 则应明确地创建并打
开一个连接对象, 这样就可将连接对象赋给该
变量 。
1,创建命令对象
使 用 命 令 对 象 之 前, 必 须 先 用
Server.Createobject方法创建该对象 。 可以使用下
列脚本创建命令对象,
<% '创建命令对象
Set comm=Server.Createobject("ADODB.Command")
%>
2,命令对象的属性
通常在使用命令对象之前需要对命令对象的
属性进行必要的设置,以便对该对象进行相应的
操作。下面分别介绍命令对象的属性。
( 1) ActiveConnection属性
在执行命令对象的命令之前, 必须先设置
ActiveConnection属性, 否则将发生错误 。
ActiveConnection属性设置或返回命令对象所
使用的连接对象 。 可以将 ActiveConnection属性设
置为一个已经存在并打开的连接对象, 也可以为
其定义一个连接使用的有效字串 。
( 2) CommandText属性
将命令对象与连接对象关联后, 可以使用
CommandText属性设置数据库查询字串, 并在执
行命令对象的 Execute方法时将该字串提交给数据
提供者处理 。
通常该属性为 SQL语句,但也可以是一个表名
或是一个 StoredProcedure名。
设置了 CommandText属性后, 就可调用命令对
象的 Execute方法来执行由 CommandText属性值所
指定的操作 。
( 3) CommandType属性
CommandType 属 性 定 义 如 何 使 用
CommandText,分别为 adCmdText,adCmdTable,
adCmdStoredProc及 adCmdUnknown。 与前面在讲
连接对象的 Execute方法中的相应的选项的含义相
同 。
设置该属性可优化 CommandText属性的计算。
如果没有设置该属性值,则 ADO因不知
CommandText属性值是 SQL语句、表还是存储过
程,需要花时间去识别而影响系统的执行速度。
( 4) CommandTimeOut属性
该属性定义命令对象终止并产生错误之前需
等待的时间, 默认为 30秒 。
( 5) Prepared属性
Prepared属性决定数据提供者在首次执行命
令对象前是否保存命令的编译版本, 该属性是一
个布尔型值 。
当 Prepared属性设置为 True时, 将会把首次执
行 CommandText属性中指定查询的结果编译并保存
下来, 在后继命令的执行中, 数据提供者将直接使
用已编译好的命令版本, 从而提高执行性能 。
如果该属性设置为 False,则将直接执行命令对
象而不创建编译版本 。
在实际使用中有些数据提供者可能不支持命令
的预编译, 此时当该属性设置为 True时, ADO将返
回错误 。
3,命令对象的方法
( 1) CreateParameter方法:用来产生一个新的
Parameter对象,并在执行之前加到命令对象的
Parameters集合中。返回值为创建的 Parameter对象。
Parameter对象表示传递给 SQL语句或存储过程的一
个或多个参数。
CreateParameter方法的语法格式如下,
Set Param=comm.CreateParameter(name,type,direction,size,value)
其中的各个参数均为可选项,具体说明如下,
?Name,是一个字符串, 指定 Parameter对象的名称,
该名称为参数的引用名, 在后面引用参数的值时
会有用 。
?Type,是一个长整型值, 指定 Parameter对象的数
据类型 。 例如整数为 adInteger;
?Direction,是一个长整型值, 指定参数是输入还
是输出, 相应的值为,adParamInput( 指示输入
参数 ), adParamOutput( 指示为输出参数 ),
adParamReturnValue( 指 示 为 返 回 值 ),
adParamUnknown( 指示参数类型无法确定 ),
adParamInputOutput( 指示为输入 /输出参数 ) ;
?Size,是一个长整型值, 指定参数的最大长度或
最大的值 。
?Value,是一个变体型值, 指定参数的值 。
可以将各个选项分开来写, 例如下面的两种写
法是等价的 。
Set param= comm.CreateParameter(name,type,direction,size,value )
或
Set param= comm.CreateParameter(name,type,direction,size)
param.value=value
下面的方法其灵活性更大 。 大家请注意, 在
使用 了 CreateParameter 方 法后 只 是建 立 了新 的
parameter对象, 还需使用 Parameter对象的 Append
方法将该参数传递给命令对象 。
( 2) Execute方法
调用命令对象的 Execute方法用来执行由
CommandText属性值所指定的查询, SQL语句或存
储过程 。 有以下两种格式,
按行返回的格式,
Set Recordset =Command.Execute(RecordsetsAffected,Parameters,Options)
没有返回的格式,
Command.Execute RecordsetsAffected,Parameters,Options
其中参数说明如下,
?RecordsAffected,可选, 为长整型变量, 返回
操作所影响的记录数 。
?Parameters,可选, 为变体整型组, 返回使用
SQL语句传送的参数值 。 ( 用该参数传送时输出
参数将不返回正确值 )
?Options,可选, 为长整型值, 定义数据提供者
如何理解命令对象的 CommandText属性 。
4,命令对象数据集合
命令对象所提供的数据集合包括 Parameters
数据集合及 Properties数据集合 。 前者表示所要
传递的参数, 后者表示命令对象的所有属性集
合 。 命令对象是通过 Parameter对象来传递一个
参数, 而 Parameters数据集合则是此命令对象所
有 Parameter对象的集合 。
(1) Parameters数据集合
Parameters数据集合所提供的方法与属性有
Count属性, Append方法, Delete方法, Refresh方
法与 Item方法等, 分述如下,
?Count属性:该属性可用来取得 Parameters数据集
合中所包含的 Parameter对象个数 。
? Append方法:该方法可以增加一个 Parameter对象
到 Parameters数据集合中。
?Delete方法:该方法可以从 Parameters数据集合
中删除一个 Parameter对象 。
?Refresh方法:该方法可以重新取得 Parameters数
据集合中所包含的所有 Parameter对象 。
?Item方法:该方法可以用来取得 Parameters数据
集合中所包含的所有 Parameter对象 。 该方法有一
个参数, 表示所要取得的 Parameter对象索引值,
这个索引值通常介于 0到 Count属性值 -1之间 。
需 要 注 意 的 是 使 用 Command 对 象 的
Parameters集合上的 Refresh方法可为在 Command
对象中指定的存储过程或者参数化查询检索提供
者端参数信息 。 对于不支持存储过程调用或参数
化查询的提供者来说, 集合将为空 。
在调用 Refresh方法之前应该将 Command对象
的 ActiveConnection属性设置为有效的 Connection
对象,将 CommandText属性设置为有效命令,并且
将 CommandType属性设置为 adCmdStoredProc。
如果在调用 Refresh 方法之前访问 Parameters
集合, ADO 将自动调用方法并填充集合 。
(2) Parameter对象
Parameter对象负责所要传递参数的相关属性,
Name属性,Value属性,Type属性及 Attribute属性
等,分述如下,
?Name属性:该属性表示对象属性的名称 。
?Value属性:该属性表示表示参数的设置初
值 。
?Type属性:该属性表示对象属性的数据类
型, 与 Property对象的 Type属性相同 。
?Attribute属性:表示表示对象的特性 。
8.4.2 命令对象的使用
1,使用命令对象执行 SQL语句
命令对象代表一个命令(例如,一
个 SQL查询或一个 SQL存储过程)。在第
8章, Activex数据对象, 和第 10章, 使用
记录集, 中,分别介绍了如何用连接对
象的 Execute方法和记录集对象的 Open方
法执行命令字符串。考虑下面这两个例
子,
RS.Open "SELECT * FROM consumption",MyConn
MyConn.Execute "UPDATE consumption SET yjfy=50"
这两个例子都使用了 SQL命令字符串。在第一
个例子中,用命令字符串打开记录集;在第二个例
子中,执行命令字符串来更新数据。
命令对象是对数据存储执行命令的对象。连接
对象也有这样的功能,但是连接对象在处理命令的
功能上受到一定的限制,而命令对象是特别为处理
命令的各方面问题而创建的。实际上,当从连接对
象中运行一条命令时,已经隐含地创建了一个命令
对象。有时其它对象允许向命令传入参数,但在
连接对象中不能指定参数的任何细节。使用命令
对象允许指定参数以及输出参数和命令执行后的
返回值的精确细节(比如,数据类型和长度)。
代替命令字符串,可以使用命令对象。命令
对象可以用来代表一个专门的命令。用命令对象
的一个实例可以返回记录集或执行一个不返回记
录集的 SQL命令,参看下面程序。
程序 sample8-01.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandText="UPDATE consumption SET yjfy=50"
MyCommand.CommandType=adCMDText
MyCommand.Execute
MyConn.Close
%>
在这个例子中, 创建了命令对象 MyCommand。
接着, ActiveConnection属性把命令和一个打开的
连接联系在一起 。 因为是在分配一个对象, 所以
需要用 Set语句完成 。 CommandText属性指定要执
行什么 SQL语句 。 CommandType属性指明该命令
是一个命令的文本定义 。 最后, 调用 Execute方法
执行这个命令 。
命令对象也可用来返回一个记录集。使用命
令对象,可以通过两种途径返回记录集,上面脚
本中使用的是第一种途径。另一种途径采用了
Execute()方法。如,
程序 sample11-02.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdText
MyCommand.commandText="SELECT * FROM member"
Set RS=MyCommand.Execute()
RS.Close
MyConn.Close
%>
在这段脚本中, 命令对象的 Execute()方法被用来返
回一个记录集 。 注意因为该方法被用来返回结果所
以要使用括号 。 用命令对象创建了记录集对象 RS
后, 就可以用标准的方式对它进行操作 。 也可以和
一个已经存在的记录集一起使用命令对象, 如下面
程序,
程序 sample11-03.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
Set Rs=Server.CreateObject("ADODB.RecordSet")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;,
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdText
MyCommand.commandText="SELECT * FROM member"
RS.Open MyCommand,,3,3
MyConn.Close
%>
用命令对象打开一个已经存在的记录集对象的
好处是可以指定记录集的游标和锁定类型 。 在
这个例子中, 命令对象用来打开一个使用静态
游标和 adLockOptimistic锁定的记录集 。 注意打
开记录集时如果使用了命令对象, 那么就不需
指定连接对象, 命令对象即可决定该使用哪个
连接 。
2,存储过程及存储过程体的创建
存储过程的使用是命令对象得到应用的一个领
域。存储过程(有时也称存储查询)是 存储在数据
库中预先定义的 SQL查询语句。存储过程逻辑驻留
在存储过程体中。
(1) 存储过程的优点
使用命令对象有一个主要的优点, 就是可以和
命令对象一起使用 SQL存储过程 。
当建设好一个站点后,应尽可能的把 SQL命令
转换为存储过程。与其在 ASP网页内部执行 SQL查
询,不如调用包含这些查询的存储过程。
使用 SQL存储过程的理由有很多,
1) 存储过程被数据库编译过 。 这样可以产生一个
,执行计划,, 因此数据库确切地知道它将做什么,
从而加快了过程的执行速度 。 当一个 SQL语句包含
在存储过程中时, 服务器不必每次执行它都要分析
和编译它, SQL存储过程执行起来比 SQL命令文本
快得多 。
2) 存储过程通常被数据库高速缓存, 这样使它们
运行得更快, 因为此时不需要从磁盘中读取它们 。
并非所有的数据库都支持这种缓存机制, 比如微软
的 Access就不支持, 而 SQL Server却支持 。
3) 通过指定数据库中的表只能被存储过程修改,
可以确保数据更安全。这意味着具有潜在危险的
SQL操作不会执行。
4) 可以避免将 ASP代码和冗长的 SQL语句混在一
起, 从而使 ASP代码更易于维护 。
5) 可以将所有 SQL代码集中存放于服务器 。
6) 可以在存储过程中使用输出参数, 允许返回记
录集或其它的值 。
7) 可以在多个网页中调用同一个存储过程, 这使
得站点易于维护 。 如果一个 SQL语句需要做某些改
动, 只要做一次即可 。
8) 可以在存储过程中利用 Transact-SQL的强大功
能 。 一个 SQL存储过程可以包含多个 SQL语句, 可
以使用变量和条件, 可以在一个存储过程内引用
其它存储过程 。 这就意味着可以用存储过程建立
非常复杂的查询, 以非常复杂的方式更新
数据库 。
由于存储过程有着极大的优点,因此,在实
际中能用存储过程就要用存储过程。
(2) 存储过程的基本语法规则
1) 局部变量
局部变量保持存储过程的中间值 。 当一个值在存储
过程中需要多次使用, 或者某个查询的结果需要在随后
的查询中使用时, 需要使用局部变量 。 在这些情形下,
值被存储在局部变量中, 可以用于以后的使用 。 本地变
量的名称以, @” 符号开头, 名称中可以包含字符和数
值 。
局部变量在使用前需要进行类型声明。对局部变量
进行赋值需要使用 SELECT语句。 SELECT可以从一个表
中检索出值并将其赋给某个变量,也可以给变量赋一个
常量值。一个简单的 SELECT语句可以给多个局部变量赋
值。
例如,
DECLARE @var1 integer,@var2 varchar(20)
SELECT @var1 = 32,@var2 = 'MyAge'
如果从 SELECT查询中没有返回任何数据, 而
SELECT又要将数据的值赋予局部变量, 则该局部
变量的值将不会发生改变 。
2) 条件语句
存储过程中提供的条件语句包括,IF… ELSE
语句和 WHILE语句 。
在 IF… ELSE语句中包含三个部分:布尔运算
表达式, IF语句块和 ELSE语句块 。 语法如下,
IF (boolen_expr)
{statements}
ELSE
{statements}
在 IF或 ELSE语句块中可以有多条语句, 用语句
BEGIN和 END来标志语句块 。
WHILE语句可用于处理直到某个条件为 TRUE前重
复执行的语句 。 语法如下,
WHILE (boolen_expr)
BEGIN
statement(s)
BREAK
Statement(s)
CONTINUE
END
BEGIN和 END语句标志循环体,BREAK语
句结束循环的执行(即走到 END语句之后),
CONTINUE语句将控制处理过程回到循环的开始
处(即 BEGIN语句的右边)。
注意:如果有两个或多个 WHILE循环被嵌套,
则内部的 BREAK退出的是次外层的循环。内部
循环结束之后的所有语句在内部循环执行之后才
能继续执行 。
3) GOTO 语句
在存储过程的执行中, 语句是顺序执行的 。
GOTO语句则是用来打破这种语句执行的顺序, 它
立即跳到某条语句上执行, 而这条语句往往不紧
跟在前一语句之后 。 GOTO 语 句 与 一个 标 志
( Label) 一起使用, 该标志用来标识一条语句 。
4) RETURN语句
RETURN语句用于无条件的退出存储过程 。
RETURN之后的任何语句都不再执行 。 RETURN
语句可以给调用语句返回一个值, 但不能返回
NULL值 。 SQL Server经常为存储过程返回一个状
态值 。 如果成功地执行, 则返回一个 0,如果出现
了错误, 则返回一个为负数的错误码 。
5) 使用游标 ( CURSOR)
在需要一行一行处理时, 游标十分有用 。 游
标可以打开一个结果集合 ( 按照指定的标准选择
的行 ), 并提供在结果集中一行一行处理的功能 。
基于游标的类型, 可以对其进行回滚或者前进 。
一个存储过程体中可以包含任意条 Transact
SQL语句 。 但是, 下面的 Transact SQL语句不能
在任何存储过程体中出现,
?CREATE DEFAULT
?CREATE TRIGGER
?CREATE PROCEDURE
?CREATE RULE
?CREATE VIEW
在存储过程中可以使用参数, 可以传送和返
回参数, 还可以得到一个返回值 ( 从 SQL
RETURN语句 ) 。
(3) 建立新的存储过程
新建存储过程的过程和方法在第 7章中已经介
绍过。例如,从 Microsoft SQL Sever程序组中启动
ISQL/w。 然后,在查询窗口中即可输入以下的文
本,
CREATE PROCEDURE sp_myproc AS
SELECT * FROM member
单击执行查询按钮(看起来象一个绿色三角
形)后,就建立了这个存储过程。该存储过程的
名字是 sp_myproc。
另外还可使用 ASP脚本来创建存储过程, 例
如下面程序用来创建存储过程, 返回节目单
playbill表中节目编号为 1的节目名称 。
程序 sample11-04.asp
<% @LANGUAGE = VBScript %>
<!--#include file="adovbs.inc"-->
<%
Dim StrSQL
Set Conn=Server.CreateObject("ADODB.Connection")
Conn.open"driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
StrSQL="CREATE PROCEDURE outjmmc ( @jmmc varchar OUTPUT)
AS select @jmmc=jmmc from playbill where jmbh=1"
Conn.Execute StrSQL
Response.Write "创建存储过程成功 "
Conn.close
Set Conn = Nothing %>
3,使用命令对象调用存储过程
如果想以尽可能高效的方式从会员信息表
member中取出所有记录, 并在一个 ASP网页中显示
会员信息, 就应该使用存储过程 。 将存储过程的名
字作为命令文本, 并设置相应的类型 。
在下面的程序中调用 sp_myproc以显示所有会
员名单 。
程序 sample11-05.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.commandText="sp_myproc"
Set RS=MyCommand.Execute()
DO WHILE NOT RS.EOF
Response.Write RS("hy_name")&"<BR>,
RS.MoveNext
LOOP
RS.Close
MyConn.Close
%>
这段脚本通过调用存储过程 sp_myproc取出
记录, 并显示表 member中的所有记录 。 当用命令
对象调用存储过程时, 应该把该命令对象的
CommandType 属性设为 adCMDStoredProc。
CommandText属性用来指定要调用的存储过程 。
如果不调用 ADOVBS.inc文件, 也可以根据
使用的 ADO版本的不同在 global.asa文件中引入
<!--METADATA...--> 参数 。 对照参数如下,
( 1) ADO2.7版本
<!--METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.7 Library"
UUID="{EF53050B-882E-4776-B643-EDA472E8E3F2}"
VERSION="2.7"-->
( 2) ADO2.6版本
<!--METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.6 Library"
UUID="{00000206-0000-0010-8000-00AA006D2EA4}"
VERSION="2.6"-->
( 3) ADO2.5版本
<!--METADATA
TYPE="TypeLib"
iveX Data Objects 2.5 Library"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
VERSION="2.5"-->
4,使用返回状态值
用命令对象可以从一个存储过程得到返回状
态值 。 例如, 要统计 member表中的会员总数, 效
率最高的方法是建立一个存储过程, 如,
CREATE PROCEDURE sp_Counthy AS
RETURN(SELECT COUNT(*) FROM member)
该存储过程用 SQL集合函数 COUNT()计算
member表中的会员总数, 并用 RETURN语句返回
这个数 。
要得到一个存储过程的返回状态值, 必须为
命令对象建立一个参数, Parameters集合即为参数
对象集合 。 可以用命令对象的 CreateParameter()方
法建立一个参数, 再用 Append方法把这个参数
添加到命令对象的 Parameters集合中 。 如,
程序 sample11-06.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open
"driver={SQL Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_Counthy"
Set
MyParam=Mycommand.CreateParameter("RetVal",adInteger,adParamRe
turnValue)
MyCommand.Parameters.Append MyParam
MyCommand.Execute
%>
一共有 <%=MyCommand(“RetVal”)%>个会员注
册,
<%
MyConn.Close
%>
在这个脚本中, 用 CreateParameter()方法建立
了一个参数对象 。 此例中 CreateParameter()方法有
三个参数,
?第一个参数为新参数指定一个名字 。
?第二个参数指定数据类型 。
?最后, 第三个参数指定新参数的类型 。 在此例中,
常量 adParamReturnValue指明该参数是一个返回参
数 。
建立了任何新参数之后, 都必须把它添加到
命令对象的 Parameters集合中 。 Append方法用来把
新参数添加到这个集合中 。
命令执行后, 参数的值可以被取出 。 因为该
参数是命令对象的 Parameters集合中的一员, 用
MyCommand("RetVal")可以返回该参数的值 。 实际
上, 用以下的任何一个表达式都可以得到这个值:
MyCommand("RetVal")
MyCommand(0)
MyCommand.Parameters("RetVal")
MyCommand.Parameters(0)
MyCommand.Parameters.Item("RetVal")
MyCommand.Parameters.Item(0)
对所有的集合, 都可以通过名字或顺序号指
定一个参数 。
5,参数集合和参数对象
命令对象最好的应用就是向内驻程序或数据提供
者的查询命令发送参数 。 为了提供这一功能, 命
令对象包括一个参数对象的命令 。 使用
CreateParameter方法, 就能够非常方便地利用内驻
程序提高运行速度 。
(1) 使用输出参数
上一节中的程序 sample8-17.asp演示了如何得到
返回状态值 。 从一个存储过程取出输出参数值
与此非常相似 。 使用输出参数的好处是输出参数可
以有一个或多个, 而且可以是任何数据类型 。
例如, 要输出会员消费记录表 consumption中最
高点播次数和最低点播次数, 可以使用下面的存储
程序,
CREATE PROCEDURE sp_HighandLow1
(@High int OUTPUT,@Low int OUTPUT)
AS
SELECT @High=MAX(dbcs) FROM consumption
SELECT @Low=MIN(dbcs) FROM consumption
这个存储过程有两个参数 @High和 @Low。 @High
为会员最高点播次数, @Low为会员最低点播次数 。
调用该存储过程, 可以使用如下的脚本,
程序 sample8-18.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_HighandLow1"
Set MyFirstParam=
Mycommand.CreateParameter("High",adInteger,adParamOutPut)
MyCommand.Parameters.Append MyFirstParam
Set MySecondParam=
Mycommand.CreateParameter("Low",adInteger,adParamOutPut)
MyCommand.Parameters.Append MySecondParam
MyCommand.Execute
%>
<p>点播次数最多为,<%=MyCommand("High")%>次
<p>点播次数最少为,<%=MyCommand("Low")%>次
<%
MyConn.Close
%>
在这个脚本中, 用 CreateParameter()方法创建
了两个参数对象, 两个参数都被定义为 INT型 。 为
了 指 明 它 们 是 输 出 参 数, 使 用 了 常 量
adParamOutput。
又如, 要输出会员消费记录表 consumption中点
播次数最多和点播次数最少的会员账号 ( 假定会员
点播次数均不相同 ), 可以使用下面的存储程序,
CREATE PROCEDURE sp_HighandLow2
(@Highhy VARCHAR(30) OUTPUT,@Lowhy VARCHAR(30) OUTPUT)
AS
SELECT @Highhy=hy_id FROM consumption where dbcs in (SELECT
MAX(dbcs) FROM consumption)
SELECT @Highhy=hy_id FROM consumption where dbcs in (SELECT
MIN(dbcs) FROM consumption)
GO
调用该存储过程, 可以使用如下的脚本,
程序,sample8-19.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open
"driver={SQL Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_HighandLow2"
Set
MyFirstParam=Mycommand.CreateParameter("Highhy",adVarChar,adParam
OutPut,30)
MyCommand.Parameters.Append MyFirstParam
Set MySecondParam=
Mycommand.CreateParameter("Lowhy",adVarChar,adParamOutPut,30)
MyCommand.Parameters.Append MySecondParam
MyCommand.Execute
%>
<p>点播次数最多为会员,<%=MyCommand("Highhy")%>
<p>点播次数最少为会员,<%=MyCommand("Lowhy")%>
<% MyConn.Close
%>
这个脚本的结构与上一个非常相似。在这个
脚本中,用 CreateParameter()方法创建的两个输出
参数对象均被定义为 VARCHAR型,为了指明它们
是输出参数,使用了常量 adParamOutput。 最后在
CreateParameter()方法中指定了每个参数的最大长
度为 30。注意的是当建立的参数是变长度数据类
型,如 VARCHAR型时,必须指定一个最大长度。
(2) 使用输入参数
SQL存储过程可以接收输入参数 。 输入参数
能够把数据传递给存储过程 。
例如, 在会员信息表 member中保存了会员帐
号和密码 。 现在建立一个检查密码的存储过程
sp_CheckPass来检查会员是否输入了合法的密码 。
可在查询分析器窗口中输入以下存储过程,
CREATE PROCEDURE sp_CheckPass
(@CHKid VARCHAR(30),@CHKPass VARCHAR(30),
@ISValid CHAR(8) OUTPUT)
AS
IF EXISTS(SELECT hy_id FROM member
WHERE hy_id=@CHKid AND passwd=@CHKPass)
SELECT @ISValid="pass"
ELSE
SELECT @ISValid="Invalid"
GO
这个存储过程接收两个输入参数:输入参数
@CHKId向存储过程传递会员帐号; @CHKPass向
存储过程传递登陆密码 。 如果会员拥有指定的密
码, 输出参数将返回, pass”,否则, 返回
,Invalid”。
现在用下面的程序调用存储过程 sp_CheckPass。
程序 sample8-20.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open
"driver={SQL Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_CheckPass"
'存储过程名称
Set MyFirstParam=
Mycommand.CreateParameter("CHKid",adVarChar,adParamInput,30)
'创建输入参数对象
MyCommand.Parameters.Append MyFirstParam
'把参数加到参数集合
Set MySecondParam=
Mycommand.CreateParameter ("CHKPass",adVarChar,adParamInput,30)
MyCommand.Parameters.Append MySecondParam
Set MyThirdParam=
Mycommand.CreateParameter ("ISValid",adChar,adParamOutput,8)
'创建返回参数对象
MyCommand.Parameters.Append MyThirdParam
MyCommand("CHKId")="0001"
'取得输入参数
MyCommand("CHKPass")="marry"
MyCommand.Execute
'执行存储过程
%>
The Check Result is <%=MyCommand ("ISValid")%>
<%
MyConn.Close
'关闭数据库连接
%>
本例中用 CreateParameter()方法建立了三个参
数对象, 其中两个输入参数, 一个输出参数 。 建
立了任何新参数之后, 都必须把它添加到命令对
象的 Parameters集合中 。 Append方法用来把新参数
添加到这个集合中 。 最后, 调用 Execute方法执行
存储过程 。 在这个例子中, 帐号, 0001” 和密码
,marry”被传递给存储过程 。 如果表中存在这个名
字 ——密码组合, 则报告该密码为 Pass,否则报告
该密码为 Invalid。
6,取出参数信息
当需要用到一个存储过程, 但是又不知道该
存储过程需要什么参数时, 例如不知道参数的数
据类型或参数的大小, 那么如何确定这些信息呢?
下面的脚本可以得到一个存储过程 sp_myproc
所使用的参数的有关信息。
程序 sample8-21.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_myproc"
MyCommand.Parameters.Refresh
%>
<HTML>
<HEAD>
<TITLE>Parameter Information </TITLE>
</HEAD>
<BODY>
<TABLE BORDER=1>
<CAPTION> Parameter Information</CAPTION>
<TR>
<TH>Parameter Name</TH>
<TH>DATATYPE</TH>
<TH>DIRECTION</TH>
<TH>SIZE</TH>
</TR>
<% for i=0 to MyCommand.Parameters.count-1 %>
<TR>
<TD><%=MyCommand.Parameters(i).name %></TD>
<TD><%=MyCommand.Parameters(i).type%></TD>
<TD><%=MyCommand.Parameters(i).direction%></TD>
<TD><%=MyCommand.Parameters(i).value%></TD>
</TR>
<%
Next
MyConn.Close
%>
</TABLE>
</BODY>
</HTML>
这个例子显示了存储过程 sp_myproc的所有参
数的有关信息 。 每个参数的名字, 数据类型, 说
明和大小被显示在一个表中 ( 一个参数的说明指
明了该参数是输入参数, 输出参数或是返回状态
值 ) 。 要显示另一个存储过程的信息, 只要替换
存储过程名即可 。
这 个 例 子 中 的 重 要 语 句
MyCommand.Parameters.Refresh。 当这个语句执行
时, 该存储过程的参数的有关信息被从数据库中取
出 。 该程序运行结果见图 8-18。
这个脚本不返回常量, 它返回的是原始值 。
要解释这个脚本的返回值, 需要参考包含文件
ADOVBS.inc。 在这个文件中, 原始值与正确的常
量相对应 。
图 8-18 sample8-20.asp运行结果
本 章 小 结
本章简要描述了 Activex数据对象 ( ADO),
Connection对象, Recordset对象及 Command
对象的属性, 方法和集合, 以及如何在 ASP中使用
这三大对象来访问和操作数据库 。
ActiveX数据对象 ( ADO) 可用来将数据库访
问添加到 Web页中, 编写简洁和可升级脚本以连接
到与应用程序编程接口 OLE DB兼容的数据源 。 连
接对象 Connection用来建立和管理应用程序与数据
源之间的连接 。 通过连接对象的 Open方法打开与
数据库的连接, Close方法关闭与数据库的连接,
Eexecute方法执行指定的 SQL语句和存储过程
等。由于 Recordset对象含有从数据存储中提取
的数据集,因此,可以在 ASP网页中使用该对
象来显示表中的数据。 Command对象是对数
据存储执行命令的对象,是特别为处理命令的
各方面问题而创建的,而存储过程的使用是命
令对象得到应用的又一领域。
习 题
1,ASP访问数据库有几种方式? 它们各有什么优
缺点?
2,简述 ADO七个对象和四个集合的关系及主要功
能 。
3,简述 DSN在数据库连接过程当中的作用 。
4.操作数据库要经过哪些步骤?实现过程当中各
有哪些方法?
5,连接对象有哪些功能? 写出使用连接对象与指
定数据库进行连接的各种不同方法 。
6,删除 VOD数据库中所建表 consumption中剩余
费用字段 yfy少于 1元的会员记录, 不需要返回
Recordset记录集 。
7.按消费额 zfy从多到少的顺序,返回 VOD数
据库中所建表 consumption中的所有会员消费记
录,需要返回 Recordset记录集。
8,如何利用 Recordset对象从指定数据库中检
索, 更新和删除记录 。
9.从本章进行分页显示的例子中可看出,记录
分页显示的基本思想是什么?
10,命令对象有哪些功能?
11,简述调用存储过程的主要优点。
12,试用存储过程实现记录的检索功能。
实 训
题目
利用命令对象调用存储过程 。
目的和要求
1,进一步熟悉命令对象的方法和参数 。
2,通过建立和调用命令对象的存储过程来实
现参数的输入和输出 。
实训内容
编写一存储过程, 并通过调用该存储过程实
现从 playbill表中检索出指定会员的所点播的所有
节目的详细信息 。
参考程序
建立存储过程,
CREATE PROCEDURE sp_Checkrec
@para_hyid varchar(30)
AS
SELECT * FROM playbill a,order_log b
WHERE a.jmbh=b.jmbh AND b.hy_id =@para_hyid
GO
调用存储过程,(假设指定会员帐号为 0001)
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText=" sp_Checkrec" '存储过程名称
Set Param=Mycommand.CreateParameter
("para_hyid",adVarChar,adParamInput,30) '创建输入 '参数对象
MyCommand.Parameters.Append Param '把参数加到参数集合
MyCommand("para_hyid")="0001" '取得输入参数
set Rs=MyCommand.Execute()
%>
<TABLE BORDER=1>
<CAPTION> 点播节目清单 </CAPTION>
<TR>
<TH>节目编号 </TH>
<TH>节目名称 </TH>
<TH>节目长度 </TH>
<TH>点播时间 </TH>
</TR>
<% DO WHILE NOT RS.EOF %>
<TR>
<TD><%=RS(0) %></TD>
<TD><%=RS(1)%></TD>
<TD><%=RS(2)%></TD>
<TD><%=RS(9)%></TD>
</TR>
<% RS.MoveNext
LOOP
%>
<%
MyConn.Close
'关闭数据库连接
%>
注:其中 RS(0),RS(1),RS(2),RS(9)为进行
表连接查询操作后所要显示的对应字段序列号。
在 8.12节中曾经提到命令对象负责对
数据库提供请求,也就是说它定义了将对
数据源执行的指定命令,这些命令可以是
SQL语句、表或存储过程。命令对象提供
了一种简单有效的方法来处理查询或存储
过程,通过该对象可以方便地查询数据库
并返回记录集,并对该记录集执行有关操
作。
8.4.1 命令对象的属性和方法
命令对象既可以利用已经创建的连接对象
来创建, 也可以不用先创建连接对象就直接使
用 命 令 对 象, 只 需 设 置 命 令 对 象 的
ActiveConnection属性为一个连接字串即可, 这
时 ADO将自动创建一个隐含的连接对象, 但不
会分配一个对象变量给它 。 因此如果多个命令
对象要使用相同的连接, 则应明确地创建并打
开一个连接对象, 这样就可将连接对象赋给该
变量 。
1,创建命令对象
使 用 命 令 对 象 之 前, 必 须 先 用
Server.Createobject方法创建该对象 。 可以使用下
列脚本创建命令对象,
<% '创建命令对象
Set comm=Server.Createobject("ADODB.Command")
%>
2,命令对象的属性
通常在使用命令对象之前需要对命令对象的
属性进行必要的设置,以便对该对象进行相应的
操作。下面分别介绍命令对象的属性。
( 1) ActiveConnection属性
在执行命令对象的命令之前, 必须先设置
ActiveConnection属性, 否则将发生错误 。
ActiveConnection属性设置或返回命令对象所
使用的连接对象 。 可以将 ActiveConnection属性设
置为一个已经存在并打开的连接对象, 也可以为
其定义一个连接使用的有效字串 。
( 2) CommandText属性
将命令对象与连接对象关联后, 可以使用
CommandText属性设置数据库查询字串, 并在执
行命令对象的 Execute方法时将该字串提交给数据
提供者处理 。
通常该属性为 SQL语句,但也可以是一个表名
或是一个 StoredProcedure名。
设置了 CommandText属性后, 就可调用命令对
象的 Execute方法来执行由 CommandText属性值所
指定的操作 。
( 3) CommandType属性
CommandType 属 性 定 义 如 何 使 用
CommandText,分别为 adCmdText,adCmdTable,
adCmdStoredProc及 adCmdUnknown。 与前面在讲
连接对象的 Execute方法中的相应的选项的含义相
同 。
设置该属性可优化 CommandText属性的计算。
如果没有设置该属性值,则 ADO因不知
CommandText属性值是 SQL语句、表还是存储过
程,需要花时间去识别而影响系统的执行速度。
( 4) CommandTimeOut属性
该属性定义命令对象终止并产生错误之前需
等待的时间, 默认为 30秒 。
( 5) Prepared属性
Prepared属性决定数据提供者在首次执行命
令对象前是否保存命令的编译版本, 该属性是一
个布尔型值 。
当 Prepared属性设置为 True时, 将会把首次执
行 CommandText属性中指定查询的结果编译并保存
下来, 在后继命令的执行中, 数据提供者将直接使
用已编译好的命令版本, 从而提高执行性能 。
如果该属性设置为 False,则将直接执行命令对
象而不创建编译版本 。
在实际使用中有些数据提供者可能不支持命令
的预编译, 此时当该属性设置为 True时, ADO将返
回错误 。
3,命令对象的方法
( 1) CreateParameter方法:用来产生一个新的
Parameter对象,并在执行之前加到命令对象的
Parameters集合中。返回值为创建的 Parameter对象。
Parameter对象表示传递给 SQL语句或存储过程的一
个或多个参数。
CreateParameter方法的语法格式如下,
Set Param=comm.CreateParameter(name,type,direction,size,value)
其中的各个参数均为可选项,具体说明如下,
?Name,是一个字符串, 指定 Parameter对象的名称,
该名称为参数的引用名, 在后面引用参数的值时
会有用 。
?Type,是一个长整型值, 指定 Parameter对象的数
据类型 。 例如整数为 adInteger;
?Direction,是一个长整型值, 指定参数是输入还
是输出, 相应的值为,adParamInput( 指示输入
参数 ), adParamOutput( 指示为输出参数 ),
adParamReturnValue( 指 示 为 返 回 值 ),
adParamUnknown( 指示参数类型无法确定 ),
adParamInputOutput( 指示为输入 /输出参数 ) ;
?Size,是一个长整型值, 指定参数的最大长度或
最大的值 。
?Value,是一个变体型值, 指定参数的值 。
可以将各个选项分开来写, 例如下面的两种写
法是等价的 。
Set param= comm.CreateParameter(name,type,direction,size,value )
或
Set param= comm.CreateParameter(name,type,direction,size)
param.value=value
下面的方法其灵活性更大 。 大家请注意, 在
使用 了 CreateParameter 方 法后 只 是建 立 了新 的
parameter对象, 还需使用 Parameter对象的 Append
方法将该参数传递给命令对象 。
( 2) Execute方法
调用命令对象的 Execute方法用来执行由
CommandText属性值所指定的查询, SQL语句或存
储过程 。 有以下两种格式,
按行返回的格式,
Set Recordset =Command.Execute(RecordsetsAffected,Parameters,Options)
没有返回的格式,
Command.Execute RecordsetsAffected,Parameters,Options
其中参数说明如下,
?RecordsAffected,可选, 为长整型变量, 返回
操作所影响的记录数 。
?Parameters,可选, 为变体整型组, 返回使用
SQL语句传送的参数值 。 ( 用该参数传送时输出
参数将不返回正确值 )
?Options,可选, 为长整型值, 定义数据提供者
如何理解命令对象的 CommandText属性 。
4,命令对象数据集合
命令对象所提供的数据集合包括 Parameters
数据集合及 Properties数据集合 。 前者表示所要
传递的参数, 后者表示命令对象的所有属性集
合 。 命令对象是通过 Parameter对象来传递一个
参数, 而 Parameters数据集合则是此命令对象所
有 Parameter对象的集合 。
(1) Parameters数据集合
Parameters数据集合所提供的方法与属性有
Count属性, Append方法, Delete方法, Refresh方
法与 Item方法等, 分述如下,
?Count属性:该属性可用来取得 Parameters数据集
合中所包含的 Parameter对象个数 。
? Append方法:该方法可以增加一个 Parameter对象
到 Parameters数据集合中。
?Delete方法:该方法可以从 Parameters数据集合
中删除一个 Parameter对象 。
?Refresh方法:该方法可以重新取得 Parameters数
据集合中所包含的所有 Parameter对象 。
?Item方法:该方法可以用来取得 Parameters数据
集合中所包含的所有 Parameter对象 。 该方法有一
个参数, 表示所要取得的 Parameter对象索引值,
这个索引值通常介于 0到 Count属性值 -1之间 。
需 要 注 意 的 是 使 用 Command 对 象 的
Parameters集合上的 Refresh方法可为在 Command
对象中指定的存储过程或者参数化查询检索提供
者端参数信息 。 对于不支持存储过程调用或参数
化查询的提供者来说, 集合将为空 。
在调用 Refresh方法之前应该将 Command对象
的 ActiveConnection属性设置为有效的 Connection
对象,将 CommandText属性设置为有效命令,并且
将 CommandType属性设置为 adCmdStoredProc。
如果在调用 Refresh 方法之前访问 Parameters
集合, ADO 将自动调用方法并填充集合 。
(2) Parameter对象
Parameter对象负责所要传递参数的相关属性,
Name属性,Value属性,Type属性及 Attribute属性
等,分述如下,
?Name属性:该属性表示对象属性的名称 。
?Value属性:该属性表示表示参数的设置初
值 。
?Type属性:该属性表示对象属性的数据类
型, 与 Property对象的 Type属性相同 。
?Attribute属性:表示表示对象的特性 。
8.4.2 命令对象的使用
1,使用命令对象执行 SQL语句
命令对象代表一个命令(例如,一
个 SQL查询或一个 SQL存储过程)。在第
8章, Activex数据对象, 和第 10章, 使用
记录集, 中,分别介绍了如何用连接对
象的 Execute方法和记录集对象的 Open方
法执行命令字符串。考虑下面这两个例
子,
RS.Open "SELECT * FROM consumption",MyConn
MyConn.Execute "UPDATE consumption SET yjfy=50"
这两个例子都使用了 SQL命令字符串。在第一
个例子中,用命令字符串打开记录集;在第二个例
子中,执行命令字符串来更新数据。
命令对象是对数据存储执行命令的对象。连接
对象也有这样的功能,但是连接对象在处理命令的
功能上受到一定的限制,而命令对象是特别为处理
命令的各方面问题而创建的。实际上,当从连接对
象中运行一条命令时,已经隐含地创建了一个命令
对象。有时其它对象允许向命令传入参数,但在
连接对象中不能指定参数的任何细节。使用命令
对象允许指定参数以及输出参数和命令执行后的
返回值的精确细节(比如,数据类型和长度)。
代替命令字符串,可以使用命令对象。命令
对象可以用来代表一个专门的命令。用命令对象
的一个实例可以返回记录集或执行一个不返回记
录集的 SQL命令,参看下面程序。
程序 sample8-01.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandText="UPDATE consumption SET yjfy=50"
MyCommand.CommandType=adCMDText
MyCommand.Execute
MyConn.Close
%>
在这个例子中, 创建了命令对象 MyCommand。
接着, ActiveConnection属性把命令和一个打开的
连接联系在一起 。 因为是在分配一个对象, 所以
需要用 Set语句完成 。 CommandText属性指定要执
行什么 SQL语句 。 CommandType属性指明该命令
是一个命令的文本定义 。 最后, 调用 Execute方法
执行这个命令 。
命令对象也可用来返回一个记录集。使用命
令对象,可以通过两种途径返回记录集,上面脚
本中使用的是第一种途径。另一种途径采用了
Execute()方法。如,
程序 sample11-02.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdText
MyCommand.commandText="SELECT * FROM member"
Set RS=MyCommand.Execute()
RS.Close
MyConn.Close
%>
在这段脚本中, 命令对象的 Execute()方法被用来返
回一个记录集 。 注意因为该方法被用来返回结果所
以要使用括号 。 用命令对象创建了记录集对象 RS
后, 就可以用标准的方式对它进行操作 。 也可以和
一个已经存在的记录集一起使用命令对象, 如下面
程序,
程序 sample11-03.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
Set Rs=Server.CreateObject("ADODB.RecordSet")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;,
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdText
MyCommand.commandText="SELECT * FROM member"
RS.Open MyCommand,,3,3
MyConn.Close
%>
用命令对象打开一个已经存在的记录集对象的
好处是可以指定记录集的游标和锁定类型 。 在
这个例子中, 命令对象用来打开一个使用静态
游标和 adLockOptimistic锁定的记录集 。 注意打
开记录集时如果使用了命令对象, 那么就不需
指定连接对象, 命令对象即可决定该使用哪个
连接 。
2,存储过程及存储过程体的创建
存储过程的使用是命令对象得到应用的一个领
域。存储过程(有时也称存储查询)是 存储在数据
库中预先定义的 SQL查询语句。存储过程逻辑驻留
在存储过程体中。
(1) 存储过程的优点
使用命令对象有一个主要的优点, 就是可以和
命令对象一起使用 SQL存储过程 。
当建设好一个站点后,应尽可能的把 SQL命令
转换为存储过程。与其在 ASP网页内部执行 SQL查
询,不如调用包含这些查询的存储过程。
使用 SQL存储过程的理由有很多,
1) 存储过程被数据库编译过 。 这样可以产生一个
,执行计划,, 因此数据库确切地知道它将做什么,
从而加快了过程的执行速度 。 当一个 SQL语句包含
在存储过程中时, 服务器不必每次执行它都要分析
和编译它, SQL存储过程执行起来比 SQL命令文本
快得多 。
2) 存储过程通常被数据库高速缓存, 这样使它们
运行得更快, 因为此时不需要从磁盘中读取它们 。
并非所有的数据库都支持这种缓存机制, 比如微软
的 Access就不支持, 而 SQL Server却支持 。
3) 通过指定数据库中的表只能被存储过程修改,
可以确保数据更安全。这意味着具有潜在危险的
SQL操作不会执行。
4) 可以避免将 ASP代码和冗长的 SQL语句混在一
起, 从而使 ASP代码更易于维护 。
5) 可以将所有 SQL代码集中存放于服务器 。
6) 可以在存储过程中使用输出参数, 允许返回记
录集或其它的值 。
7) 可以在多个网页中调用同一个存储过程, 这使
得站点易于维护 。 如果一个 SQL语句需要做某些改
动, 只要做一次即可 。
8) 可以在存储过程中利用 Transact-SQL的强大功
能 。 一个 SQL存储过程可以包含多个 SQL语句, 可
以使用变量和条件, 可以在一个存储过程内引用
其它存储过程 。 这就意味着可以用存储过程建立
非常复杂的查询, 以非常复杂的方式更新
数据库 。
由于存储过程有着极大的优点,因此,在实
际中能用存储过程就要用存储过程。
(2) 存储过程的基本语法规则
1) 局部变量
局部变量保持存储过程的中间值 。 当一个值在存储
过程中需要多次使用, 或者某个查询的结果需要在随后
的查询中使用时, 需要使用局部变量 。 在这些情形下,
值被存储在局部变量中, 可以用于以后的使用 。 本地变
量的名称以, @” 符号开头, 名称中可以包含字符和数
值 。
局部变量在使用前需要进行类型声明。对局部变量
进行赋值需要使用 SELECT语句。 SELECT可以从一个表
中检索出值并将其赋给某个变量,也可以给变量赋一个
常量值。一个简单的 SELECT语句可以给多个局部变量赋
值。
例如,
DECLARE @var1 integer,@var2 varchar(20)
SELECT @var1 = 32,@var2 = 'MyAge'
如果从 SELECT查询中没有返回任何数据, 而
SELECT又要将数据的值赋予局部变量, 则该局部
变量的值将不会发生改变 。
2) 条件语句
存储过程中提供的条件语句包括,IF… ELSE
语句和 WHILE语句 。
在 IF… ELSE语句中包含三个部分:布尔运算
表达式, IF语句块和 ELSE语句块 。 语法如下,
IF (boolen_expr)
{statements}
ELSE
{statements}
在 IF或 ELSE语句块中可以有多条语句, 用语句
BEGIN和 END来标志语句块 。
WHILE语句可用于处理直到某个条件为 TRUE前重
复执行的语句 。 语法如下,
WHILE (boolen_expr)
BEGIN
statement(s)
BREAK
Statement(s)
CONTINUE
END
BEGIN和 END语句标志循环体,BREAK语
句结束循环的执行(即走到 END语句之后),
CONTINUE语句将控制处理过程回到循环的开始
处(即 BEGIN语句的右边)。
注意:如果有两个或多个 WHILE循环被嵌套,
则内部的 BREAK退出的是次外层的循环。内部
循环结束之后的所有语句在内部循环执行之后才
能继续执行 。
3) GOTO 语句
在存储过程的执行中, 语句是顺序执行的 。
GOTO语句则是用来打破这种语句执行的顺序, 它
立即跳到某条语句上执行, 而这条语句往往不紧
跟在前一语句之后 。 GOTO 语 句 与 一个 标 志
( Label) 一起使用, 该标志用来标识一条语句 。
4) RETURN语句
RETURN语句用于无条件的退出存储过程 。
RETURN之后的任何语句都不再执行 。 RETURN
语句可以给调用语句返回一个值, 但不能返回
NULL值 。 SQL Server经常为存储过程返回一个状
态值 。 如果成功地执行, 则返回一个 0,如果出现
了错误, 则返回一个为负数的错误码 。
5) 使用游标 ( CURSOR)
在需要一行一行处理时, 游标十分有用 。 游
标可以打开一个结果集合 ( 按照指定的标准选择
的行 ), 并提供在结果集中一行一行处理的功能 。
基于游标的类型, 可以对其进行回滚或者前进 。
一个存储过程体中可以包含任意条 Transact
SQL语句 。 但是, 下面的 Transact SQL语句不能
在任何存储过程体中出现,
?CREATE DEFAULT
?CREATE TRIGGER
?CREATE PROCEDURE
?CREATE RULE
?CREATE VIEW
在存储过程中可以使用参数, 可以传送和返
回参数, 还可以得到一个返回值 ( 从 SQL
RETURN语句 ) 。
(3) 建立新的存储过程
新建存储过程的过程和方法在第 7章中已经介
绍过。例如,从 Microsoft SQL Sever程序组中启动
ISQL/w。 然后,在查询窗口中即可输入以下的文
本,
CREATE PROCEDURE sp_myproc AS
SELECT * FROM member
单击执行查询按钮(看起来象一个绿色三角
形)后,就建立了这个存储过程。该存储过程的
名字是 sp_myproc。
另外还可使用 ASP脚本来创建存储过程, 例
如下面程序用来创建存储过程, 返回节目单
playbill表中节目编号为 1的节目名称 。
程序 sample11-04.asp
<% @LANGUAGE = VBScript %>
<!--#include file="adovbs.inc"-->
<%
Dim StrSQL
Set Conn=Server.CreateObject("ADODB.Connection")
Conn.open"driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
StrSQL="CREATE PROCEDURE outjmmc ( @jmmc varchar OUTPUT)
AS select @jmmc=jmmc from playbill where jmbh=1"
Conn.Execute StrSQL
Response.Write "创建存储过程成功 "
Conn.close
Set Conn = Nothing %>
3,使用命令对象调用存储过程
如果想以尽可能高效的方式从会员信息表
member中取出所有记录, 并在一个 ASP网页中显示
会员信息, 就应该使用存储过程 。 将存储过程的名
字作为命令文本, 并设置相应的类型 。
在下面的程序中调用 sp_myproc以显示所有会
员名单 。
程序 sample11-05.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.commandText="sp_myproc"
Set RS=MyCommand.Execute()
DO WHILE NOT RS.EOF
Response.Write RS("hy_name")&"<BR>,
RS.MoveNext
LOOP
RS.Close
MyConn.Close
%>
这段脚本通过调用存储过程 sp_myproc取出
记录, 并显示表 member中的所有记录 。 当用命令
对象调用存储过程时, 应该把该命令对象的
CommandType 属性设为 adCMDStoredProc。
CommandText属性用来指定要调用的存储过程 。
如果不调用 ADOVBS.inc文件, 也可以根据
使用的 ADO版本的不同在 global.asa文件中引入
<!--METADATA...--> 参数 。 对照参数如下,
( 1) ADO2.7版本
<!--METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.7 Library"
UUID="{EF53050B-882E-4776-B643-EDA472E8E3F2}"
VERSION="2.7"-->
( 2) ADO2.6版本
<!--METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.6 Library"
UUID="{00000206-0000-0010-8000-00AA006D2EA4}"
VERSION="2.6"-->
( 3) ADO2.5版本
<!--METADATA
TYPE="TypeLib"
iveX Data Objects 2.5 Library"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
VERSION="2.5"-->
4,使用返回状态值
用命令对象可以从一个存储过程得到返回状
态值 。 例如, 要统计 member表中的会员总数, 效
率最高的方法是建立一个存储过程, 如,
CREATE PROCEDURE sp_Counthy AS
RETURN(SELECT COUNT(*) FROM member)
该存储过程用 SQL集合函数 COUNT()计算
member表中的会员总数, 并用 RETURN语句返回
这个数 。
要得到一个存储过程的返回状态值, 必须为
命令对象建立一个参数, Parameters集合即为参数
对象集合 。 可以用命令对象的 CreateParameter()方
法建立一个参数, 再用 Append方法把这个参数
添加到命令对象的 Parameters集合中 。 如,
程序 sample11-06.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open
"driver={SQL Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_Counthy"
Set
MyParam=Mycommand.CreateParameter("RetVal",adInteger,adParamRe
turnValue)
MyCommand.Parameters.Append MyParam
MyCommand.Execute
%>
一共有 <%=MyCommand(“RetVal”)%>个会员注
册,
<%
MyConn.Close
%>
在这个脚本中, 用 CreateParameter()方法建立
了一个参数对象 。 此例中 CreateParameter()方法有
三个参数,
?第一个参数为新参数指定一个名字 。
?第二个参数指定数据类型 。
?最后, 第三个参数指定新参数的类型 。 在此例中,
常量 adParamReturnValue指明该参数是一个返回参
数 。
建立了任何新参数之后, 都必须把它添加到
命令对象的 Parameters集合中 。 Append方法用来把
新参数添加到这个集合中 。
命令执行后, 参数的值可以被取出 。 因为该
参数是命令对象的 Parameters集合中的一员, 用
MyCommand("RetVal")可以返回该参数的值 。 实际
上, 用以下的任何一个表达式都可以得到这个值:
MyCommand("RetVal")
MyCommand(0)
MyCommand.Parameters("RetVal")
MyCommand.Parameters(0)
MyCommand.Parameters.Item("RetVal")
MyCommand.Parameters.Item(0)
对所有的集合, 都可以通过名字或顺序号指
定一个参数 。
5,参数集合和参数对象
命令对象最好的应用就是向内驻程序或数据提供
者的查询命令发送参数 。 为了提供这一功能, 命
令对象包括一个参数对象的命令 。 使用
CreateParameter方法, 就能够非常方便地利用内驻
程序提高运行速度 。
(1) 使用输出参数
上一节中的程序 sample8-17.asp演示了如何得到
返回状态值 。 从一个存储过程取出输出参数值
与此非常相似 。 使用输出参数的好处是输出参数可
以有一个或多个, 而且可以是任何数据类型 。
例如, 要输出会员消费记录表 consumption中最
高点播次数和最低点播次数, 可以使用下面的存储
程序,
CREATE PROCEDURE sp_HighandLow1
(@High int OUTPUT,@Low int OUTPUT)
AS
SELECT @High=MAX(dbcs) FROM consumption
SELECT @Low=MIN(dbcs) FROM consumption
这个存储过程有两个参数 @High和 @Low。 @High
为会员最高点播次数, @Low为会员最低点播次数 。
调用该存储过程, 可以使用如下的脚本,
程序 sample8-18.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_HighandLow1"
Set MyFirstParam=
Mycommand.CreateParameter("High",adInteger,adParamOutPut)
MyCommand.Parameters.Append MyFirstParam
Set MySecondParam=
Mycommand.CreateParameter("Low",adInteger,adParamOutPut)
MyCommand.Parameters.Append MySecondParam
MyCommand.Execute
%>
<p>点播次数最多为,<%=MyCommand("High")%>次
<p>点播次数最少为,<%=MyCommand("Low")%>次
<%
MyConn.Close
%>
在这个脚本中, 用 CreateParameter()方法创建
了两个参数对象, 两个参数都被定义为 INT型 。 为
了 指 明 它 们 是 输 出 参 数, 使 用 了 常 量
adParamOutput。
又如, 要输出会员消费记录表 consumption中点
播次数最多和点播次数最少的会员账号 ( 假定会员
点播次数均不相同 ), 可以使用下面的存储程序,
CREATE PROCEDURE sp_HighandLow2
(@Highhy VARCHAR(30) OUTPUT,@Lowhy VARCHAR(30) OUTPUT)
AS
SELECT @Highhy=hy_id FROM consumption where dbcs in (SELECT
MAX(dbcs) FROM consumption)
SELECT @Highhy=hy_id FROM consumption where dbcs in (SELECT
MIN(dbcs) FROM consumption)
GO
调用该存储过程, 可以使用如下的脚本,
程序,sample8-19.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open
"driver={SQL Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_HighandLow2"
Set
MyFirstParam=Mycommand.CreateParameter("Highhy",adVarChar,adParam
OutPut,30)
MyCommand.Parameters.Append MyFirstParam
Set MySecondParam=
Mycommand.CreateParameter("Lowhy",adVarChar,adParamOutPut,30)
MyCommand.Parameters.Append MySecondParam
MyCommand.Execute
%>
<p>点播次数最多为会员,<%=MyCommand("Highhy")%>
<p>点播次数最少为会员,<%=MyCommand("Lowhy")%>
<% MyConn.Close
%>
这个脚本的结构与上一个非常相似。在这个
脚本中,用 CreateParameter()方法创建的两个输出
参数对象均被定义为 VARCHAR型,为了指明它们
是输出参数,使用了常量 adParamOutput。 最后在
CreateParameter()方法中指定了每个参数的最大长
度为 30。注意的是当建立的参数是变长度数据类
型,如 VARCHAR型时,必须指定一个最大长度。
(2) 使用输入参数
SQL存储过程可以接收输入参数 。 输入参数
能够把数据传递给存储过程 。
例如, 在会员信息表 member中保存了会员帐
号和密码 。 现在建立一个检查密码的存储过程
sp_CheckPass来检查会员是否输入了合法的密码 。
可在查询分析器窗口中输入以下存储过程,
CREATE PROCEDURE sp_CheckPass
(@CHKid VARCHAR(30),@CHKPass VARCHAR(30),
@ISValid CHAR(8) OUTPUT)
AS
IF EXISTS(SELECT hy_id FROM member
WHERE hy_id=@CHKid AND passwd=@CHKPass)
SELECT @ISValid="pass"
ELSE
SELECT @ISValid="Invalid"
GO
这个存储过程接收两个输入参数:输入参数
@CHKId向存储过程传递会员帐号; @CHKPass向
存储过程传递登陆密码 。 如果会员拥有指定的密
码, 输出参数将返回, pass”,否则, 返回
,Invalid”。
现在用下面的程序调用存储过程 sp_CheckPass。
程序 sample8-20.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open
"driver={SQL Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_CheckPass"
'存储过程名称
Set MyFirstParam=
Mycommand.CreateParameter("CHKid",adVarChar,adParamInput,30)
'创建输入参数对象
MyCommand.Parameters.Append MyFirstParam
'把参数加到参数集合
Set MySecondParam=
Mycommand.CreateParameter ("CHKPass",adVarChar,adParamInput,30)
MyCommand.Parameters.Append MySecondParam
Set MyThirdParam=
Mycommand.CreateParameter ("ISValid",adChar,adParamOutput,8)
'创建返回参数对象
MyCommand.Parameters.Append MyThirdParam
MyCommand("CHKId")="0001"
'取得输入参数
MyCommand("CHKPass")="marry"
MyCommand.Execute
'执行存储过程
%>
The Check Result is <%=MyCommand ("ISValid")%>
<%
MyConn.Close
'关闭数据库连接
%>
本例中用 CreateParameter()方法建立了三个参
数对象, 其中两个输入参数, 一个输出参数 。 建
立了任何新参数之后, 都必须把它添加到命令对
象的 Parameters集合中 。 Append方法用来把新参数
添加到这个集合中 。 最后, 调用 Execute方法执行
存储过程 。 在这个例子中, 帐号, 0001” 和密码
,marry”被传递给存储过程 。 如果表中存在这个名
字 ——密码组合, 则报告该密码为 Pass,否则报告
该密码为 Invalid。
6,取出参数信息
当需要用到一个存储过程, 但是又不知道该
存储过程需要什么参数时, 例如不知道参数的数
据类型或参数的大小, 那么如何确定这些信息呢?
下面的脚本可以得到一个存储过程 sp_myproc
所使用的参数的有关信息。
程序 sample8-21.asp
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "dsn=vod;uid=sa;pwd=ser;"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText="sp_myproc"
MyCommand.Parameters.Refresh
%>
<HTML>
<HEAD>
<TITLE>Parameter Information </TITLE>
</HEAD>
<BODY>
<TABLE BORDER=1>
<CAPTION> Parameter Information</CAPTION>
<TR>
<TH>Parameter Name</TH>
<TH>DATATYPE</TH>
<TH>DIRECTION</TH>
<TH>SIZE</TH>
</TR>
<% for i=0 to MyCommand.Parameters.count-1 %>
<TR>
<TD><%=MyCommand.Parameters(i).name %></TD>
<TD><%=MyCommand.Parameters(i).type%></TD>
<TD><%=MyCommand.Parameters(i).direction%></TD>
<TD><%=MyCommand.Parameters(i).value%></TD>
</TR>
<%
Next
MyConn.Close
%>
</TABLE>
</BODY>
</HTML>
这个例子显示了存储过程 sp_myproc的所有参
数的有关信息 。 每个参数的名字, 数据类型, 说
明和大小被显示在一个表中 ( 一个参数的说明指
明了该参数是输入参数, 输出参数或是返回状态
值 ) 。 要显示另一个存储过程的信息, 只要替换
存储过程名即可 。
这 个 例 子 中 的 重 要 语 句
MyCommand.Parameters.Refresh。 当这个语句执行
时, 该存储过程的参数的有关信息被从数据库中取
出 。 该程序运行结果见图 8-18。
这个脚本不返回常量, 它返回的是原始值 。
要解释这个脚本的返回值, 需要参考包含文件
ADOVBS.inc。 在这个文件中, 原始值与正确的常
量相对应 。
图 8-18 sample8-20.asp运行结果
本 章 小 结
本章简要描述了 Activex数据对象 ( ADO),
Connection对象, Recordset对象及 Command
对象的属性, 方法和集合, 以及如何在 ASP中使用
这三大对象来访问和操作数据库 。
ActiveX数据对象 ( ADO) 可用来将数据库访
问添加到 Web页中, 编写简洁和可升级脚本以连接
到与应用程序编程接口 OLE DB兼容的数据源 。 连
接对象 Connection用来建立和管理应用程序与数据
源之间的连接 。 通过连接对象的 Open方法打开与
数据库的连接, Close方法关闭与数据库的连接,
Eexecute方法执行指定的 SQL语句和存储过程
等。由于 Recordset对象含有从数据存储中提取
的数据集,因此,可以在 ASP网页中使用该对
象来显示表中的数据。 Command对象是对数
据存储执行命令的对象,是特别为处理命令的
各方面问题而创建的,而存储过程的使用是命
令对象得到应用的又一领域。
习 题
1,ASP访问数据库有几种方式? 它们各有什么优
缺点?
2,简述 ADO七个对象和四个集合的关系及主要功
能 。
3,简述 DSN在数据库连接过程当中的作用 。
4.操作数据库要经过哪些步骤?实现过程当中各
有哪些方法?
5,连接对象有哪些功能? 写出使用连接对象与指
定数据库进行连接的各种不同方法 。
6,删除 VOD数据库中所建表 consumption中剩余
费用字段 yfy少于 1元的会员记录, 不需要返回
Recordset记录集 。
7.按消费额 zfy从多到少的顺序,返回 VOD数
据库中所建表 consumption中的所有会员消费记
录,需要返回 Recordset记录集。
8,如何利用 Recordset对象从指定数据库中检
索, 更新和删除记录 。
9.从本章进行分页显示的例子中可看出,记录
分页显示的基本思想是什么?
10,命令对象有哪些功能?
11,简述调用存储过程的主要优点。
12,试用存储过程实现记录的检索功能。
实 训
题目
利用命令对象调用存储过程 。
目的和要求
1,进一步熟悉命令对象的方法和参数 。
2,通过建立和调用命令对象的存储过程来实
现参数的输入和输出 。
实训内容
编写一存储过程, 并通过调用该存储过程实
现从 playbill表中检索出指定会员的所点播的所有
节目的详细信息 。
参考程序
建立存储过程,
CREATE PROCEDURE sp_Checkrec
@para_hyid varchar(30)
AS
SELECT * FROM playbill a,order_log b
WHERE a.jmbh=b.jmbh AND b.hy_id =@para_hyid
GO
调用存储过程,(假设指定会员帐号为 0001)
<!--#INCLUDE VIRTUAL="ADOVBS.inc"-->
<%
Set MyConn=Server.CreateObject("ADODB.Connection")
Set MyCommand=Server.CreateObject("ADODB.Command")
MyConn.Open "driver={SQL
Server};server=localhost;uid=sa;pwd=ser;database=vod"
Set MyCommand.ActiveConnection=MyConn
MyCommand.CommandType=adCMdStoredProc
MyCommand.CommandText=" sp_Checkrec" '存储过程名称
Set Param=Mycommand.CreateParameter
("para_hyid",adVarChar,adParamInput,30) '创建输入 '参数对象
MyCommand.Parameters.Append Param '把参数加到参数集合
MyCommand("para_hyid")="0001" '取得输入参数
set Rs=MyCommand.Execute()
%>
<TABLE BORDER=1>
<CAPTION> 点播节目清单 </CAPTION>
<TR>
<TH>节目编号 </TH>
<TH>节目名称 </TH>
<TH>节目长度 </TH>
<TH>点播时间 </TH>
</TR>
<% DO WHILE NOT RS.EOF %>
<TR>
<TD><%=RS(0) %></TD>
<TD><%=RS(1)%></TD>
<TD><%=RS(2)%></TD>
<TD><%=RS(9)%></TD>
</TR>
<% RS.MoveNext
LOOP
%>
<%
MyConn.Close
'关闭数据库连接
%>
注:其中 RS(0),RS(1),RS(2),RS(9)为进行
表连接查询操作后所要显示的对应字段序列号。