Submitted by on 2006, December 31, 7:54 AM
两个页面:一个注册页,一个验证页
reg.html
| 代码: |
<script language="JavaScript">
function GetResult(str)
{
/*
*--------------- GetResult(str) -----------------
* GetResult(str)
* 功能:通过XMLHTTP发送请求,返回结果.
* 参数:str,字符串,发送条件.
* 实例:GetResult(document.all.userid.value);
* update:2006-12-26
*--------------- GetResult(str) -----------------
*/
var exitdos = new ActiveXObject("Microsoft.XMLHTTP");
//特殊字符:+,%,&,=,?等的传输解决办法.字符串先用escape编码的.
//Update:2006-12-26 12:22
exitdos.open("POST","server.asp?userid="+escape(str),false);
exitdos.send();
//服务器端处理返回的是经过escape编码的字符串.
document.all.useridtip.innerHTML=unescape(exitdos.responseText)
}
</script>
userid:<input type="text" name="userid" onblur="GetResult(document.all.userid.value)"><span id="useridtip"></span> |
server.asp
| 代码: |
<% @Language="JavaScript" %>
<%
function OpenDB(sdbname)
{
var connstr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source="+Server.MapPath(sdbname);
var conn = Server.CreateObject("ADODB.Connection");
conn.Open(connstr);
return conn;
}
var sResult = "";
var oConn = OpenDB("data.mdb");
//特殊字符:+,%,&,=,?等的传输解决办法.客户端字符是经过escape编码的
//所以服务器端先要经过unescape解码.
//Update:2004-6-1 12:22
var userid = unescape(Request("userid"));
var sql = "select username from users where userid=""+userid+""";
var rs = oConn.Execute(sql);
if(!rs.EOF)
{
sResult = "Sorry,该用户名已存在"
}
else
{
//加入容错.2006-12-25 10:15
sResult = "该用户可以注册"
}
//escape解决了XMLHTTP。中文处理的问题.
Response.Write(escape(sResult));
%> |
vbscript版server.asp
| 代码: |
<!--#include file="conn.asp"-->
<%
dim sResult,sql
sql="select themail from members where themail = "" & request.QueryString("themail") &"""
set rsc = conn.execute(sql)
if not rsc.eof then
sResult = "<font color=red>Sorry,该用户Email已存在</font>"
else
sResult = "该Email可以添加"
end if
rsc.close
set rsc = nothing
response.Write(escape(sResult))
response.End()
|
顺便感叹一下,当初学asp的时候,用js多好。那样的话,现在搞php也会习惯很多。痛苦ing……
vb脚本是我以后加上的,一个项目中正好用到。顺便贴出来
Tags: AJAX
网站|ASP备忘 | 评论:3
| Trackbacks:0
| 阅读:3044
Submitted by on 2006, December 20, 4:52 PM
有很多才用xp 建web服务器的朋友大多都是在为无法被局域网其他机子访问的问题困扰吧!!
淡水河边这厮昨日也遇到此问题.[eek]
困扰我们的原因是由于xp默认安全性设置很高,关闭了很多网络功能web服务器就在这之列。
解决方法就是打开防火墙-->选择(高级)-->点击(本地连接旁边的[设置]按钮)-->我们就可以看到"web 服务器(http)"前面是空白框,我们直接勾选他然后点确定就搞定了.ftp服务器也是这样解决的.
多说一点,xp的iis只有10个链接数.自己本机调试都不一定够用.让局域网其他机子访问就更不足了.推荐微软的Eetaedit2.2 .可以修改IIS链接数.
Tags: iis, xp
网站|ASP备忘 | 评论:2
| Trackbacks:0
| 阅读:2487
Submitted by on 2006, December 16, 8:00 AM
1 。打开您的Microsoft Visual Basic:
点击确定,以下就按照蓝色的数字步骤.
2 。修改工程名和类模块的名称:
点3,把4改成bi,再点5:
6处改成cjjer.
3。增加到引用asp:
点击引用,然后选择其中的Microsoft Active Server Pages Object Library.
点9确定.
4。编写代码:
Option Explicit
Private Context As ScriptingContext
Private Application As Application
Private Response As Response
Private Request As Request
Private Session As Session
Private Server As Server
Public Sub OnStartPage(PassedscriptContext As ScriptingContext)
Set Context = PassedscriptContext
Set Application = Context.Application
Set Request = Context.Request
Set Response = Context.Response
Set Server = Context.Server
Set Session = Context.Session
End Sub
Public Sub showsuc()
Response.Write "我是蓝色理想的老农,您好"
End Sub
" 释放内部对象
Public Sub OnEndPage()
Set Application = Nothing
Set Request = Nothing
Set Response = Nothing
Set Server = Nothing
Set Session = Nothing
Set Context = Nothing
End Sub
其中,除10处,其他都是必须的.
10处是我们自己要表现的程序.
ctrl+s保存在d:\mylib\cjjer.cls
在把工程保存为d:\mylib\bi.vbp
5 。编译,注册成dll:
点击生成bi.dll
没啥警告的话那就ok了,路径保存在d:\mylib\bi.dll.
然后开始--------->运行-->
regsvr32 d:\mylib\bi.dll
这就注册成功了.
6。使用bi.dll:
新建asp文件,输入:
<%
Dim bicjjer
Set bicjjer=Server.CreateObject("bi.cjjer")
bicjjer.showsuc()
%>
浏览器,预览,显示如下:
注意:对已经存在的组建名称或这修改了dll文件,必须先停止IIS,再重启注册使用,否则会一直在原来的基础上.
另外补充一点:生成的dll文件不注册到服务器也可以使用:
<% @ language="vbscript" %>
<!--METADATA TYPE="typelib" FILE="e:\web\web\asp\bi\bi.dll"-->
<%
Dim bicjjer
Set bicjjer=Server.CreateObject("bi.cjjer")
bicjjer.showsuc()
%>
这绝对是个好消息,有人说这个没什么价值,那我说"您还是固陋寡闻或者您技术高的藐视dll...",哈哈哈,当然是玩笑了,注意,METADATA的file路径是绝对的物理路径,否则无法装载.
Tags: dll
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1272
Submitted by on 2006, December 16, 7:26 AM
ERR对象
err对象使用的时候不需要创建实例,就是说你要用的时候随便拿来使用,就像session一样,不需要像ADODB对象使用的时候Set conn=Server.CreateObject("ADODB.Connection")来创建实例,它返回一个错误代码,但是Err!=Err.Number,可以用Clear方法清除,以利于下次使用.它主要的是个Description方法,返回的是简要错误说明,这里一个很经典的例子:
| 代码: |
<%@ LANGUAGE="VBscript" %>
<%Response.Buffer = True
On Error Resume Next
%>
<%
s="sa"
response.write(Int(s))
If Err.Number <> 0 Then
Response.Clear
response.write"发生错误:"%>
<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY>
错误 Number: <%= Err.Number %><br/>
错误信息: <%= Err.Description %><br/>
出错文件: <%= Err.Source %><br/>
出错行: <%= Err.Line %><br/>
<%= Err %>
</BODY>
</HTML>
<%End If%> |
运行一看,呓,Err.Line 为空,为啥?因为asp的vb编写的里面line方法不被支持.值得注意的是要使用err对象的时候,必须加上On Error Resume Next,原来越过asperror对象的异常抛出.
ERROR对象
在链接数据库的时候可以使用error对象: Count属性:用来统计Errors集合的数目,Item方法:用来指定特定的一个错误,语法为Error.Item(number),其中number为一数字。由于Item为默认的方法,所以Error(number)的写法与前面的写法是等价的。下面是一段程序。用来列举Error对象:
| 代码: |
<%
On Error Resume next
Set conn=Server.CreateObject("ADODB.Connection")
Dim i,your_databasepath:your_databasepath="no.mdb"
connstr="Provider=Microsoft.Jet.OLEDB.4.0;Data Source="&server.mappath(your_databasepath)&""
conn.open connstr
if conn.errors.count<>0 then
response.write "链接数据库失败<hr/>"
for i =0 to conn.errors.count-1
response.write conn.errors.item(i)&"<hr>"
response.write Err.Description
next
else
response.write "链接数据库成功"
end if
conn.close
%> |
没啥差别和err对象,看到比较结果了么?寒死了,直接用err对象简单.
一般建议在调试的时候用asperror对象(就相当于不处理,出错是网页上显示的默认信息就是),就是把On Error Resume next 这行rem了,就默认用asperror抛出了.在正式运行的时候,除非特殊要求,可以使用err对象做点事情.
Tags: err, error
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1779
Submitted by on 2006, December 16, 1:17 AM
【摘要】
防止用户频繁刷新页面,可以起到一点点的作用。
【全文】
方法1,session技术:
| 代码: |
<%
Dim SplitReflashPage
Dim DoReflashPage
dim shuaxin_time
DoReflashPage=true
shuaxin_time=10
ReflashTime=Now()
if (not isnull(session("ReflashTime"))) and cint(shuaxin_time)>0 and DoReflashPage then
if DateDiff("s",session("ReflashTime"),Now())<cint(shuaxin_time) then
response.write "<META http-equiv=Content-Type content=text/html; charset=gb2312><meta HTTP-EQUIV=REFRESH CONTENT=3>本页面起用了防刷新机制,请不要在<b><font color=ff0000>"&shuaxin_time&"</font></b>秒内连续刷新本页面<BR>正在打开页面,请稍候……"
response.end
else
session("ReflashTime")=Now()
end if
elseif isnull(session("ReflashTime")) and cint(shuaxin_time)>0 and DoReflashPage then
Session("ReflashTime")=Now()
end if
randomize timer
regjm=int(rnd*8998)+1000
%> |
方法2,cookie技术:
| 代码: |
<%
Dim URL
If DateDiff("s",Request.Cookies("oesun")("vitistime"),Now())<2 Then
URL=Request.ServerVariables("Http_REFERER")
Response.Write("<meta http-equiv=""refresh"" content=""2;URL="&URL&""">")
Response.Write("防刷新,两秒后自动跳转")
Response.End
End IF
Response.Cookies("oesun")("vitistime")=Now()
%> |
Tags: session, cookie, 刷新
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1382
Submitted by on 2006, December 14, 6:49 PM
而现今支持ASP的主机一般都采用微软OS,而这些OS一般都是win2k server及以上系统,就算不安装XML PARSER同样会支持XML parser解析。
而XMLDOM也有个".save"方法.通过这样我们就可以来在不FSO的主机上生成HTML文件了.
首先,说明一点.注意HTML与XML代码的规范化.例:
在HTML里可以这样写,<input name=t1> 这是没有问题的,标准的写法应该是 <input name="t1">;但是如果是xml里<input name=t1>肯定是错误的,因为XML的节点属性值要求在引号之内.同样 <input name="t1">也是错误的,因为XML需要封闭的结点,你可以写成 <input name="t1"></input>,但 <input name="t1"></Input> 也是错误的,因为XML区分大小写。对于 input 这个XML节点,它的TEXT值为空,从而可以写成 <input name="t1" /> 。这样就符合XML规范了.特殊字符",>,<,",&,节点不允许交叉等等,先说这么多了,至于XML文档的规范化不是本文重点,请参阅相关资料.
如果用FSO,你的意愿是要生成这样的HTML文件.
| 代码: |
<html>
<head>
<title>test</title>
<body>
<p><img src="test.gif">
</body>
</html> |
这里少写了</HEAD>,对于HTML来说,浏览器可以容忍.
但是要生成具有XML规范的文档,就必须是
| 代码: |
<html>
<head>
<title>test</title>
</head>
<body>
<p><img src="test.gif" /></p>
</body>
</html> |
如何将这一段XML格式化的文档存入服务器呢?
| 代码: |
<%
dim xmlString
xmlString="<html>" & chr(10) & "<head>" & chr(10) & "<title>test</title>" & chr(10) & "</head>" & chr(10) & "<body>" & chr(10) & "<p><img src="test.gif" /></p>" & chr(10) & "</body>" & chr(10) & "</html>"
dim xmlDoc
set xmlDoc = server.createObject("Msxml2.DOMDocument")
xmlDoc.loadXml(xmlString)
xmlDoc.save(server.mappath("test.htm"))
set xmlDoc=nothing
%> |
这里用到了 "xmlDOM.loadXml()" 方法,它加载一段XML DOCUMENT到对象中.
为什么要大家将准备生成的HTML写成XML规范的的原因也在于此,因为LOADXML()方法只支持符合XML规范的文本字串.
河边这厮啰嗦一下,需要有对目录的写权限
Tags: tohtml, XMLHTTP
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1399
Submitted by on 2006, December 14, 12:58 AM
ASP与存储过程(Stored Procedures)的文章不少,但是我怀疑作者们是否真正实践过。我在初学时查阅过大量相关资料,发现其中提供的很多方法实际操作起来并不是那么回事。对于简单的应用,这些资料也许是有帮助的,但仅限于此,因为它们根本就是千篇一律,互相抄袭,稍微复杂点的应用,就全都语焉不详了。
现在,我基本上通过调用存储过程访问SQL Server,以下的文字虽不敢保证绝对正确,但都是实践的总结,希望对大家能有帮助。
存储过程就是作为可执行对象存放在数据库中的一个或多个SQL命令。
定义总是很抽象。存储过程其实就是能完成一定操作的一组SQL语句,只不过这组语句是放在数据库中的(这里我们只谈SQL Server)。如果我们通过创建存储过程以及在ASP中调用存储过程,就可以避免将SQL语句同ASP代码混杂在一起。这样做的好处至少有三个:
第一、大大提高效率。存储过程本身的执行速度非常快,而且,调用存储过程可以大大减少同数据库的交互次数。
第二、提高安全性。假如将SQL语句混合在ASP代码中,一旦代码失密,同时也就意味着库结构失密。
第三、有利于SQL语句的重用。
在ASP中,一般通过command对象调用存储过程,根据不同情况,本文也介绍其它调用方法。为了方便说明,根据存储过程的输入输出,作以下简单分类:
1. 只返回单一记录集的存储过程
假设有以下存储过程(本文的目的不在于讲述T-SQL语法,所以存储过程只给出代码,不作说明):
/*SP1*/
Create PROCEDURE dbo.getUserList
as
set nocount on
begin
select * from dbo.[userinfo]
end
go
以上存储过程取得userinfo表中的所有记录,返回一个记录集。通过command对象调用该存储过程的ASP代码如下:
"**通过Command对象调用存储过程**
DIM MyComm,MyRst
Set MyComm = Server.CreateObject("ADODB.Command")
MyComm.ActiveConnection = MyConStr "MyConStr是数据库连接字串
MyComm.CommandText = "getUserList" "指定存储过程名
MyComm.CommandType = 4 "表明这是一个存储过程
MyComm.Prepared = true "要求将SQL命令先行编译
Set MyRst = MyComm.Execute
Set MyComm = Nothing
存储过程取得的记录集赋给MyRst,接下来,可以对MyRst进行操作。
在以上代码中,CommandType属性表明请求的类型,取值及说明如下:
-1 表明CommandText参数的类型无法确定
1 表明CommandText是一般的命令类型
2 表明CommandText参数是一个存在的表名称
4 表明CommandText参数是一个存储过程的名称
还可以通过Connection对象或Recordset对象调用存储过程,方法分别如下:
"**通过Connection对象调用存储过程**
DIM MyConn,MyRst
Set MyConn = Server.CreateObject("ADODB.Connection")
MyConn.open MyConStr "MyConStr是数据库连接字串
Set MyRst = MyConn.Execute("getUserList",0,4) "最后一个参断含义同CommandType
Set MyConn = Nothing
"**通过Recordset对象调用存储过程**
DIM MyRst
Set MyRst = Server.CreateObject("ADODB.Recordset")
MyRst.open "getUserList",MyConStr,0,1,4
"MyConStr是数据库连接字串,最后一个参断含义与CommandType相同
2. 没有输入输出的存储过程
请看以下存储过程:
/*SP2*/
Create PROCEDURE dbo.delUserAll
as
set nocount on
begin
delete from dbo.[userinfo]
end
go
该存储过程删去userinfo表中的所有记录,没有任何输入及输出,调用方法与上面讲过的基本相同,只是不用取得记录集:
"**通过Command对象调用存储过程**
DIM MyComm
Set MyComm = Server.CreateObject("ADODB.Command")
MyComm.ActiveConnection = MyConStr "MyConStr是数据库连接字串
MyComm.CommandText = "delUserAll" "指定存储过程名
MyComm.CommandType = 4 "表明这是一个存储过程
MyComm.Prepared = true "要求将SQL命令先行编译
MyComm.Execute "此处不必再取得记录集
Set MyComm = Nothing
当然也可通过Connection对象或Recordset对象调用此类存储过程,不过建立Recordset对象是为了取得记录集,在没有返回记录集的情况下,还是利用Command对象吧。
3. 有返回值的存储过程
在进行类似SP2的操作时,应充分利用SQL Server强大的事务处理功能,以维护数据的一致性。并且,我们可能需要存储过程返回执行情况,为此,将SP2修改如下:
/*SP3*/
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
go
以上存储过程,在delete顺利执行时,返回1,否则返回0,并进行回滚操作。为了在ASP中取得返回值,需要利用Parameters集合来声明参数:
"**调用带有返回值的存储过程并取得返回值**
DIM MyComm,MyPara
Set MyComm = Server.CreateObject("ADODB.Command")
MyComm.ActiveConnection = MyConStr "MyConStr是数据库连接字串
MyComm.CommandText = "delUserAll" "指定存储过程名
MyComm.CommandType = 4 "表明这是一个存储过程
MyComm.Prepared = true "要求将SQL命令先行编译
"声明返回值
Set Mypara = MyComm.CreateParameter("RETURN",2,4)
MyComm.Parameters.Append MyPara
MyComm.Execute
"取得返回值
DIM retValue
retValue = MyComm(0) "或retValue = MyComm.Parameters(0)
Set MyComm = Nothing
在MyComm.CreateParameter("RETURN",2,4)中,各参数的含义如下:
第一个参数("RETURE")为参数名。参数名可以任意设定,但一般应与存储过程中声明的参数名相同。此处是返回值,我习惯上设为"RETURE";
第二个参数(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: 返回值
以上给出的ASP代码,应该说是完整的代码,也即最复杂的代码,其实
Set Mypara = MyComm.CreateParameter("RETURN",2,4)
MyComm.Parameters.Append MyPara
可以简化为
MyComm.Parameters.Append MyComm.CreateParameter("RETURN",2,4)
甚至还可以继续简化,稍后会做说明。
对于带参数的存储过程,只能使用Command对象调用(也有资料说可通过Connection对象或Recordset对象调用,但我没有试成过)。
4. 有输入参数和输出参数的存储过程
返回值其实是一种特殊的输出参数。在大多数情况下,我们用到的是同时有输入及输出参数的存储过程,比如我们想取得用户信息表中,某ID用户的用户名,这时候,有一个输入参数----用户ID,和一个输出参数----用户名。实现这一功能的存储过程如下:
/*SP4*/
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
go
调用该存储过程的ASP代码如下:
"**调用带有输入输出参数的存储过程**
DIM MyComm,UserID,UserName
UserID = 1
Set MyComm = Server.CreateObject("ADODB.Command")
MyComm.ActiveConnection = MyConStr "MyConStr是数据库连接字串
MyComm.CommandText = "getUserName" "指定存储过程名
MyComm.CommandType = 4 "表明这是一个存储过程
MyComm.Prepared = true "要求将SQL命令先行编译
"声明参数
MyComm.Parameters.append MyComm.CreateParameter("@UserID",3,1,4,UserID)
MyComm.Parameters.append MyComm.CreateParameter("@UserName",200,2,40)
MyComm.Execute
"取得出参
UserName = MyComm(1)
Set MyComm = Nothing
在以上代码中,可以看到,与声明返回值不同,声明输入参数时需要5个参数,声明输出参数时需要4个参数。声明输入参数时5个参数分别为:参数名、参数数据类型、参数类型、数据长度、参数值。声明输出参数时,没有最后一个参数:参数值。
需要特别注意的是:在声明参数时,顺序一定要与存储过程中定义的顺序相同,而且各参数的数据类型、长度也要与存储过程中定义的相同。
如果存储过程有多个参数,ASP代码会显得繁琐,可以使用with命令简化代码:
"**调用带有输入输出参数的存储过程(简化代码)**
DIM MyComm,UserID,UserName
UserID = 1
Set MyComm = Server.CreateObject("ADODB.Command")
with MyComm
.ActiveConnection = MyConStr "MyConStr是数据库连接字串
.CommandText = "getUserName" "指定存储过程名
.CommandType = 4 "表明这是一个存储过程
.Prepared = true "要求将SQL命令先行编译
.Parameters.append .CreateParameter("@UserID",3,1,4,UserID)
.Parameters.append .CreateParameter("@UserName",200,2,40)
.Execute
end with
UserName = MyComm(1)
Set MyComm = Nothing
假如我们要取得ID为1到10,10位用户的用户名,是不是要创建10次Command对象呢?不是的。如果需要多次调用同一存储过程,只需改变输入参数,就会得到不同的输出:
"**多次调用同一存储过程**
DIM MyComm,UserID,UserName
UserName = ""
Set MyComm = Server.CreateObject("ADODB.Command")
for UserID = 1 to 10
with MyComm
.ActiveConnection = MyConStr "MyConStr是数据库连接字串
.CommandText = "getUserName" "指定存储过程名
.CommandType = 4 "表明这是一个存储过程
.Prepared = true "要求将SQL命令先行编译
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 + MyComm(1) + "," "也许你喜欢用数组存储
next
Set MyComm = Nothing
通过以上代码可以看出:重复调用同一存储过程时,只需为值发生改变的输入参数重新赋值即可,这一方法在有多个输入输出参数,且每次调用时只有一个输入参数的值发生变化时,可以大大减少代码量。
5. 同时具有返回值、输入参数、输出参数的存储过程
前面说过,在调用存储过程时,声明参数的顺序要与存储过程中定义的顺序相同。还有一点要特别注意:如果存储过程同时具有返回值以及输入、输出参数,返回值要最先声明。
为了演示这种情况下的调用方法,我们改善一下上面的例子。还是取得ID为1的用户的用户名,但是有可能该用户不存在(该用户已删除,而userid是自增长的字段)。存储过程根据用户存在与否,返回不同的值。此时,存储过程和ASP代码如下:
/*SP5*/
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
go
"**调用同时具有返回值、输入参数、输出参数的存储过程**
DIM MyComm,UserID,UserName
UserID = 1
Set MyComm = Server.CreateObject("ADODB.Command")
with MyComm
.ActiveConnection = MyConStr "MyConStr是数据库连接字串
.CommandText = "getUserName" "指定存储过程名
.CommandType = 4 "表明这是一个存储过程
.Prepared = true "要求将SQL命令先行编译
"返回值要最先被声明
.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 MyComm(0) = 1 then
UserName = MyComm(1)
else
UserName = "该用户不存在"
end if
Set MyComm = Nothing
6. 同时返回参数和记录集的存储过程
有时候,我们需要存储过程同时返回参数和记录集,比如在利用存储过程分页时,要同时返回记录集以及数据总量等参数。以下给出一个进行分页处理的存储过程:
/*SP6*/
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
go
在上面的存储过程中,输入当前页号及每页记录数,返回当前页的记录集,总页数及记录总数。为了更具典型性,将记录总数以返回值的形式返回。以下是调用该存储过程的ASP代码(具体的分页操作略去):
"**调用分页存储过程**
DIM pagenow,pagesize,pagecount,recordcount
DIM MyComm,MyRst
pagenow = Request("pn")
"自定义函数用于验证自然数
if CheckNar(pagenow) = false then pagenow = 1
pagesize = 20
Set MyComm = Server.CreateObject("ADODB.Command")
with MyComm
.ActiveConnection = MyConStr "MyConStr是数据库连接字串
.CommandText = "getUserList" "指定存储过程名
.CommandType = 4 "表明这是一个存储过程
.Prepared = true "要求将SQL命令先行编译
"返回值(记录总量)
.Parameters.Append .CreateParameter("RETURN",2,4)
"出参(总页数)
.Parameters.Append .CreateParameter("@iPageCount",3,2)
"入参(当前页号)
.Parameters.append .CreateParameter("@iPage",3,1,4,pagenow)
"入参(每页记录数)
.Parameters.append .CreateParameter("@iPageSize",3,1,4,pagesize)
Set MyRst = .Execute
end with
if MyRst.state = 0 then "未取到数据,MyRst关闭
recordcount = -1
else
MyRst.close "注意:若要取得参数值,需先关闭记录集对象
recordcount = MyComm(0)
pagecount = MyComm(1)
if cint(pagenow)>=cint(pagecount) then pagenow=pagecount
end if
Set MyComm = Nothing
"以下显示记录
if recordcount = 0 then
Response.Write "无记录"
elseif recordcount > 0 then
MyRst.open
do until MyRst.EOF
......
loop
"以下显示分页信息
......
else "recordcount=-1
Response.Write "参数错误"
end if
对于以上代码,只有一点需要说明:同时返回记录集和参数时,若要取得参数,需先将记录集关闭,使用记录集时再将其打开。
7. 返回多个记录集的存储过程
本文最先介绍的是返回记录集的存储过程。有时候,需要一个存储过程返回多个记录集,在ASP中,如何同时取得这些记录集呢?为了说明这一问题,在userinfo表中增加两个字段:usertel及usermail,并设定只有登录用户可以查看这两项内容。
/*SP7*/
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
go
以下是ASP代码:
"**调用返回多个记录集的存储过程**
DIM checklg,UserID,UserName,UserTel,UserMail
DIM MyComm,MyRst
UserID = 1
"checklogin()为自定义函数,判断访问者是否登录
checklg = checklogin()
Set MyComm = Server.CreateObject("ADODB.Command")
with MyComm
.ActiveConnection = MyConStr "MyConStr是数据库连接字串
.CommandText = "getUserInfo" "指定存储过程名
.CommandType = 4 "表明这是一个存储过程
.Prepared = true "要求将SQL命令先行编译
.Parameters.append .CreateParameter("@userid",3,1,4,UserID)
.Parameters.append .CreateParameter("@checklogin",11,1,1,checklg)
Set MyRst = .Execute
end with
Set MyComm = Nothing
"从第一个记录集中取值
UserName = MyRst(0)
"从第二个记录集中取值
if not MyRst is Nothing then
Set MyRst = MyRst.NextRecordset()
UserTel = MyRst(0)
UserMail = MyRst(1)
end if
Set MyRst = Nothing
以上代码中,利用Recordset对象的NextRecordset方法,取得了存储过程返回的多个记录集。
至此,针对ASP调用存储过程的各种情况,本文已做了较为全面的说明。最后说一下在一个ASP程序中,调用多个存储过程的不同方法。
在一个ASP程序中,调用多个存储过程至少有以下三种方法是可行的:
1. 创建多个Command对象
DIM MyComm
Set MyComm = Server.CreateObject("ADODB.Command")
"调用存储过程一
......
Set MyComm = Nothing
Set MyComm = Server.CreateObject("ADODB.Command")
"调用存储过程二
......
Set MyComm = Nothing
......
2. 只创建一个Command对象,结束一次调用时,清除其参数
DIM MyComm
Set MyComm = Server.CreateObject("ADODB.Command")
"调用存储过程一
.....
"清除参数(假设有三个参数)
MyComm.Parameters.delete 2
MyComm.Parameters.delete 1
MyComm.Parameters.delete 0
"调用存储过程二并清除参数
......
Set MyComm = Nothing
此时要注意:清除参数的顺序与参数声明的顺序相反,原因嘛,我也不知道。
3. 利用Parameters数据集合的Refresh方法重置Parameter对象
DIM MyComm
Set MyComm = Server.CreateObject("ADODB.Command")
"调用存储过程一
.....
"重置Parameters数据集合中包含的所有Parameter对象
MyComm.Parameters.Refresh
"调用存储过程二
.....
Set MyComm = Nothing
一般认为,重复创建对象是效率较低的一种方法,但是经测试(测试工具为Microsoft Application Center Test),结果出人意料:
方法2 >= 方法1 >> 方法3
方法2的运行速度大于等于方法1(最多可高4%左右),这两种方法的运行速度远大于方法3(最多竟高达130%),所以建议在参数多时,采用方法1,在参数较少时,采用方法2。
花了一天的时间,终于把我对于在ASP中调用存储过程的一些粗浅的经验形成了文字。这其中,有些是我只知其果而不明其因的,有些可能是错误的,但是,这些都是经过我亲身实践的。各位看官批判地接受吧。有不同意见,希望一定向我指明,先谢了。
Tags: 存储过程
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1182
Submitted by on 2006, December 13, 5:26 PM
此篇还是asp相关的(不是PHP =.=).当数据上到好几万多条时,要调用几条数据在页面显示,ASP就会慢如蜗牛.最糟糕的是,当n多用户打开页面访问的时候,每个用户每次都要读取数据库一次,这无疑降低了效率,很明显, 如果能把数据能保存在内存上,然后读取,无疑加快了速度.
所谓缓存其实就是在内存中开辟一个用来保存数据的空间.
使用缓存你就不用频繁的访问你保存在硬盘上的数据了,因为这些数据我们希望每个用户都能看到效果一样,考虑使用的是application对象,因为它是所有访问者的共用的对象,存储的信息和定义的事件能够为所有者访问者使用,这里要使用asp内置对象application了.
关于application:
2个方法[lock 和 unlock],
2个集合[content 和 staticobjects],
2个事件[开始的application_onstart 和 application_end]
application变量不会因为用户的离开而消失,一旦建立,一直等到网站关闭和程序卸载为止,正因为如此,使用的时候要特别小心!,否则会占用内存(虚拟主机提供商很不高兴了).
我们是把数据写入一个自定义的application里面,在制定的时间读取刷新的,大体思路就是这样.
实例演示.先建立一个简单的数据库,写个function读取一下,写入一个dim变量temp中:
| 代码: |
<% Function DisplayRecords()
"这个函数原来给一个变量temp付上记录的值
Dim sql, conn, rs
"符合条件的sql语句
sql = "Select id, [szd_f], [szd_t] FROM admin"
"打开数据库连接
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ="&Server.MapPath("db.mdb")
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open sql, conn, 1, 3
"当符合sq语句l的数据没有显示完毕时
If Not rs.EOF Then
"给temp变量赋值
Dim temp
temp = "<table width=""90%"" align=""center"""
temp = temp & " border=""1"" bordercolor=""silver"""
temp = temp & " cellspacing=""2"" cellpadding=""0"">"
temp = temp & "<tr bgcolor=""#CCDDEE""><td width=""5%"""
temp = temp & ">ID</td><td>操作</td>"
temp = temp & "<td>数值</td></tr>"
While Not rs.EOF
temp = temp & "<tr><td bgcolor=""#CCDDEE"">"
temp = temp & rs("ID") & "</td><td>" & rs("szd_f")
temp = temp & "</td><td>" & rs("szd_t")
temp = temp & "</td></tr>"
rs.MoveNext
Wend
temp = temp & "</table>"
"temp赋值完毕,把它再返回给函数
DisplayRecords = temp
Else
DisplayRecords = "Data Not Available."
End If
"释放内存
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
End Function %> |
ok,上面的函数改造完毕,调用的时候就是DisplayRecords.
下面是application大显身手了:
| 代码: |
<%"该函数是写入缓存
Function DisplayCachedRecords(Secs)
Dim retVal, datVal, temp1
"Secs是每次要刷新数据的时间, retVal是数据,datVal是剩余时间
retVal = Application("cache_demo") "取得appliction的值
datVal = Application("cache_demo_date") "取得appliction的值
"判断datVal 的值,也就是要计算时间过去了没
If datVal = "" Then
"如果是空,datVal值为当前时间按秒加上secs定义的时间
datVal = DateAdd("s",Secs,Now)
End If
"temp1是判断当前时间和datVal的秒差
temp1 = DateDiff("s", Now, datVal)
"如果retVal已经是上面函数的返回值且时间大于0
If temp1 > 0 And retVal <> "" Then
"本函数返回记录数
DisplayCachedRecords = retVal
Response.Write "<b><font color=""green"">利用缓存读取数据"
Response.Write " ... (" & temp1 & " 秒剩余)</font></b>"
Response.Write "<br><br>"
Else
"retVal 是空的话,就赋予DisplayRecords的值给变量temp2
Dim temp2
temp2 = DisplayRecords()
"保存到Application.------------------>重点
Application.Lock
Application("cache_demo") = temp2
Application("cache_demo_date") = DateAdd("s",Secs,Now)
Application.UnLock
DisplayCachedRecords = temp2
" 这里随便写上了记录的缓存的过去时间,相对总秒数倒差 :
Response.Write "<b><font color=""red"">刷新缓存显示 ..."
Response.Write "</font></b><br><br>"
End If
End Function
%> |
说明完毕.
调用方法:<%=DisplayCachedRecords(20)%>
写在后面的话:如果你感觉你的服务器内存不够大的话,不要大量使用缓存.若是虚拟主机的话小心被提供商T.
Tags: 效率, application, 缓存
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1253
Submitted by on 2006, December 4, 4:52 PM
不知道大家对Buffer了解多少,很多人对这个概念都比较模糊,尤其是在asp中。很多初学者在编写asp程序时很少用到这条语句,下面我就来说说Buffer的用途以及它在asp程序中的作用。
一、Buffer
Buffer从英文直译过来的意思是“缓冲区”,这里我们将它称为缓冲,因为它不仅是个名词,还是个动词。
缓冲区是存储一系列的数据的地方,客户端所获得的数据可以从程序的执行结果直接输出,也可以从缓冲区输出。但是这两种方式在速度上是有差异的:在web中,当一个asp程序被请求的次数不多时,二者基本上没有什么差异,至少我们感觉不出来。但是当有很多人请求一个asp程序时,速度可就不一样了。如果没有缓冲区,那么每个请求asp程序的人的客户端所得到的结果都是asp程序执行一次所得到的结果,而如果预先将asp程序缓冲,那么每个客户端所得到的结果就是缓冲区的结果,不是执行一次程序的结果。比如有1000个用户同时访问一个asp页面,如果这个asp程序没有缓冲,那么程序将被执行一千次,这样服务器的负荷就回加大,从而导致客户端打开页面速度变慢;如果这个asp程序被缓冲了,那么结果就不一样了,每个客户端直接从缓冲区获得数据,服务器将不会因为访问增加而增加程序执行次数,因此客户端打开页面的速度也就比上一种情况要快。这就是Buffer的好处。
二、如何将asp程序缓冲
这个问题其实很简单,只要在asp程序的第一行加上:
<% Response.Buffer = True %>
就可以了。
这句话的意思就是指明输出页面是否被缓冲,当属性值为True时,服务器将不会向客户端发送任何信息,直到所有程序执行完或者遇到
<% Response.Flush %>或<% Response.End %>
语句,才会释放缓冲区的信息。
三、总结
Response的Buffer属性虽然能够提高页面显示速度,但是也要分什么情况。如果你正在制作一个普通的个人主页,访问量不是很高,并且没有什么复杂的执行程序,那么用不用这个属性就不是很重要,因为将数据缓冲也需要一段时间,只不过我们感觉不到罢了;但是如果你正在制作一个大型论坛或者一个产品展示或其他的商务站点,并且访问量很高,那么我建议在程序的第一行加入
<% Response.Buffer = True %>
这句话,因为这样能够让客户在有效的时间内获得更多的数据。
Tags: Buffer, 缓冲
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1179
Submitted by on 2006, December 4, 4:12 AM
在做电子商务站点的时候,经常要求浏览器在https和http之间转化
下面我给出相应的代码:
让一个ASP页面以https开始,请在该ASP页面顶部添加如下代码:
| 代码: |
<%
Response.Buffer = True
If (Request.ServerVariables("HTTPS") = "off") Then
Dim xredir__, xqstr__
xredir__ = "https://" & Request.ServerVariables("SERVER_NAME") & _
Request.ServerVariables("SCRIPT_NAME")
xqstr__ = Request.ServerVariables("QUERY_STRING")
if xqstr__ <> "" Then xredir__ = xredir__ & "?" & xqstr__
Response.redirect xredir__
End if
%> |
相反的,强迫以Http开始
请添加如下代码
| 代码: |
<%
Response.Buffer = True
If (Request.ServerVariables("HTTPS") = "on") Then
Dim xredir__, xqstr__
xredir__ = "http://" & Request.ServerVariables("SERVER_NAME") & _
Request.ServerVariables("SCRIPT_NAME")
xqstr__ = Request.ServerVariables("QUERY_STRING")
if xqstr__ <> "" Then xredir__ = xredir__ & "?" & xqstr__
Response.redirect xredir__
End if
%> |
Tags: https
网站|ASP备忘 | 评论:0
| Trackbacks:0
| 阅读:1339