网风's profile网风空间PhotosBlogLists Tools Help

Blog


    June 26

    asp与存储过程的使用

    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

    注释
    当 SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。当 SET NOCOUNT 为 OFF 时,返回计数。
    即使当 SET NOCOUNT 为 ON 时,也更新 @@ROWCOUNT 函数。
    当 SET NOCOUNT 为 ON 时,将不给客户端发送存储过程中的每个语句的 DONE_IN_PROC 信息。当使用 Microsoft SQL Server 提供的实用工具执行查询时,在 Transact-SQL 语句(如 SELECT、INSERT、UPDATE 和 DELETE)结束时将不会在查询结果中显示"nn rows affected"。
    如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。
    SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。
    权限
    SET NOCOUNT 权限默认授予所有用户。
    以上存储过程取得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对象调用,但我没有试成过)。

     

    返回值其实是一种特殊的输出参数。在大多数情况下,我们用到的是同时有输入及输出参数的存储过程,比如我们想取得用户信息表中,某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

     

    有时候,我们需要存储过程同时返回参数和记录集,比如在利用存储过程分页时,要同时返回记录集以及数据总量等参数。以下给出一个进行分页处理的存储过程:
    /*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中调用存储过程的一些粗浅的经验形成了文字。这其中,有些是我只知其果而不明其因的,有些可能是错误的,但是,这些都是经过我亲身实践的。各位看官批判地接受吧。有不同意见,希望一定向我指明,先谢了

    June 24

    弹出窗口技术

    <script language="JavaScript">
     
    function pop(pageurl){
    var popwin=window.open(pageurl,"popWin","scrollbars=yes,toolbar=no,location=no,directories=no,status=no,menubar=no,resizable=no,width=500,height=200,left=0,top=0");return false;
    }
    </script>
    <!--上面的代码放在<head></head>中,可以更改属性,参数见下面注释;
    -->
    <!--说明:你可以设置打开窗口的更多属性,参数如下:
    toolbar=yes, 是否显示工具条
    location=yes,十分显示网址栏
    directories=no,导航条
    status=no,状态条
    menubar=yes,菜单
    scrollbars=yes,滚动条
    resizable=no,是否可以改变大小
    copyhistory=yes,历史按钮
    width=350,宽
    height=500'高
    left=100,距离左边100
    top=100,距离顶端100-->
    例如:<a href="a.htm" onclick="return pop(this.href)">winner</a>
    据对没有问题,请你验证!!不明白的请你再联系!!
     
     
    =======================================================================================================
    直接打开某个文件:
    function openwin(id) {
    window.open("artread.asp?id="+id,"blank","left=280,top=200,height=300,width=400,toolbar=no, menubar=no,scrollbars=yes,resizable=no,location=no,status=no")
    }
    =======================================================================================================
    确定打开新窗口的位置:
    function openwin(id,left,top,height,width){
    window.open ("artread.asp?id="+id,"blank","left="+left+",top="+top+",height="+height+",width="width",toolbar=no, menubar=no,scrollbars=yes,resizable=no,location=no,status=no")
    }
    这样就可以根据给函数的参数来顶置窗口大小及位置了.

    ======================================================================================================
    function MM_openBrWindow(theURL,winName,features) { //v2.0
      var w=screen.availWidth/2-245;
      var h=screen.availHeight/2-220;
      pop=window.open(theURL,winName,features);
      pop.moveTo(w,h);
    }
     
     
    style="LEFT: 0px; WIDTH: 800px; POSITION: absolute; TOP: 20px" div
    style="FONT-SIZE: 10.4pt; LEFT: 120px; WIDTH: 300px; POSITION: absolute"  span
     
     
     
    //屏蔽地址,工具兰
    Page.Response.Write("<script>window.open('网页',null,'height=400,width=780,top=140,left=200,resizable=no,status=yes,toolbar=no,menubar=no,location=no'); </script>");
    Response.Write("<script Language='JavaScript'>window.open('xjgl_jbxx_zp.aspx','照片','width=90,height=105,top=280,left=580,toolbar=no,status=yes,location=no,menubar=no,directories=no,scrollbars=no,resizable=no');window.opener=null;</script>")
    Page.Response.Write("<script>window.open('你要',null,'height=400,width=780,top=140,left=200,resizable=no,status=yes,toolbar=no,menubar=no,location=no'); </script>");
    Response.Write("<script Language='JavaScript'>window.open('xjgl_jbxx_zp.aspx','照片','width=90,height=105,top=280,left=580,toolbar=no,status=yes,location=no,menubar=no,directories=no,scrollbars=no,resizable=no');window.opener=null;</script>")
    -------------------------------------------------------------------------------
    <body  onContextmenu="return false;" onselectstart="return false;">
    onContextmenu="return false;"这个是没有右键
    onselectstart="return false;"这个是不能选
    //弹出错消息的2中方法
    <1>Page.RegisterStartupScript("error","<script>alert('自定义')</script>");
    <2>Page.Response.Redirect("http://127.0.0.1/default2.asp");
    <3>Page.Response.Write("<script>alert('提示信息');</script>");
     
    <!--<SCRIPT language=javascript>
    window.open("pop/0351.htm","通告",'resizable=0,scrollbars=0,status=no,toolbar=no,location=no,menu=no,width=400,height=380,top=0,left=0');
    ..
    script language="javasript">
    <--!
        if(s.isNAN)
       {
              //isNAN 意思是“is not a number”
       }
    //-->
     

    把用户控件拖到web页后 到web页的代码编辑里的page_load() 或你要调用的事件里写:
    TextBox2.Attributes("onblur") = "checkEmail(TextBox2)"
    我这个是在js文件中写了个检查textbox里用户输入的Email是否合法的function在textBox1的onblur事件时就调用js中的方法,onblur事件的意思就是当
    textbox失去焦点时触发 在C#中是:
    TextBox2.Attributes["onblur"] = "checkEmail(TextBox2)"
     
     

    //设置为主页
    <td vAlign="bottom" width="61%">
    <IE:HOMEPAGE id="objHomepage" style="BEHAVIOR: url(#default#homepage)" />
    <P align="right">
    <asp:hyperlink id="Hyperlink2" runat="server" NavigateUrl="Help/h_login.htm" Target="new">帮助</asp:hyperlink>
    <FONT color="#0000ff">-</FONT>
    <A href="javascript:window.external.addfavorite(window.location,'燃气设计')">
    <FONT color="#0000ff">收藏</FONT></A><FONT color="#0000ff">-</FONT>
    <A href="javascript:objHomepage.setHomepage(window.location)">
    <FONT color="#0000ff">设置主页</FONT></A><FONT color="#0000ff">
    </FONT>
    </P>
    </td>
    //分页
    private void CustomerGrid_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
      {
       CustomerGrid.CurrentPageIndex = e.NewPageIndex;
       Display();
      }
    --------------------------------------------------------------------------------------------
    //错误消息的方法
    public class Message
     {
      public string Mess(string msg)
      {
       return "<script language=javascript>alert('"+msg+"');</script>";   **************
      }
     }
    ---------------------------------------------------------------------------------------------
    //用javascript关闭web 页
    Response.Write("<script language=\"javascript\">window.close();opener=null;</"+"script>");
    ///
    ---------------------------------------------------------------------------------------------
    在DataGird中插入一行
    public void AddColumn(DataView dv)
      {
                            int nColCount=0;
       nColCount=dv.Table.Columns.Count;
       string strName="";
       strName=dv.Table.Columns[10].ColumnName;
       BoundColumn NumberColumn = new BoundColumn();
       NumberColumn.HeaderText=strName;
       NumberColumn.DataField=strName;
                dgTotalList.Columns.AddAt(1,NumberColumn);
       
      }
    private int Asc(String s)
    {
     return (int)Encoding.ASCII.GetBytes(s)[0];
    }
    private Char Chr(int i)
    {
     return Convert.ToChar(i); 
    }
    ------------------------------------------------------------------------------------------------
    //根据表名称查询
    create  PROCEDURE usp_CeShi
     @tableName varchar(100)
    as
     declare @charSQL varchar(500)
     set @charSQL='select * from ' + @tableName

     execute (@charSQL)
    -------------------------------------------------------------------------------------------------
     
    加载时候几屏蔽  
       if (Request.Cookies["Headless"] == null || Request.Cookies["Headless"].Value == "")
       {
        HttpCookie hc = new HttpCookie("Headless","yes");
        Response.Cookies.Add(hc);
                    Page.Response.Write("<script>window.open('WebForm1.aspx',null,'resizable=no,status=no,toolbar=no,menubar=no,location=no');window.opener=null; window.close(); </script>");
      
       }
     
     
     
     
     

    <1>怎样计算在网页上的停留时间?
    <2>怎样计算客户浏览网页的顺序?
    <3>怎样获得客户的IP
    ------------------------------------------------------------------------------------
    -----------------------------------------------------------------------------------
    <1>使用在刚刚访问网站时Session["yourtiem"]=DateTime.Now;
         然后和当前的时间DateTime.Now比较
    ********************************************************************
    <1>计算网页停留时间:
    <script LANGUAGE="Javascript">
    <!-- Begin
    pageOpen = new Date();
    function bye() {
    pageClose = new Date();
    minutes = (pageClose.getMinutes() - pageOpen.getMinutes());
    seconds = (pageClose.getSeconds() - pageOpen.getSeconds());
    time = (seconds + (minutes * 60));
    if (time == 1) {
    time = (time + " 秒");
    }
    else {
    time = (time + " 秒");
    }
    alert('您在本页停留了' + time + '.谢谢!!');
    }
    // End -->
    </script>
    <2>浏览顺序
        利用session来记录
    <3>获取ip
         Request.UserHostAddress
    ***************************************************************************************
    1)
    js:

    <html>
    <head>
    <title>停留时间</title>
    <script language="Javascript">
    <!-- Begin
    pageOpen = new Date();
    function bye() {
    pageClose = new Date();
    minutes = (pageClose.getMinutes() - pageOpen.getMinutes());
    seconds = (pageClose.getSeconds() - pageOpen.getSeconds());
    time = (seconds + (minutes * 60));
    if (time == 1) {
    time = (time + " 秒钟");
    }
    else {
    time = (time + " 秒钟");
       }
    alert('您在这儿呆了' + time + '.欢迎再来!');
    }
    // End -->
    </script>
    </head>
    <body onunload="bye()">
    </body>
    </html>
    3)Request.ServerVariables["HTTP_CLIENT_IP"]
    设置成缺省的主页:
    <A onclick="this.style.behavior='url(#default#homepage)';this.setHomePage('http://www.dotNETTools.org');" title="Set as Homepage") href="javascript:"> set as homepage</a>
    ----------
    mp3网址  http//mp3.vv66.com/
    ----------
    屏蔽后退
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
     

    ===============================================
    //关闭窗口的时候没有提示
    写一函数调用:
    <script language=javascript>
    function cc(){
    window.opener="";
    window.close();
    }
    </script>
    <input type=button value="关闭" onclick="cc()"> //经过测试没有问题
    June 20

    类在asp中的用法

    <%
    '在 Class 块中,成员通过相应的声明语句被声明为 Private(私有成员,只能在类内部调用) 或 Public(公有成员,可以在类内外部调用) 。
    '被声明为 Private 的将只在 Class 块内是可见的。被声明为 Public 不仅在 Class 块的内部是可见的,对 Class 块之外的代码也是可见的。
    '没有使用 Private 或 Public 明确声明的被默认为 Public。在类的块内部被声明为 Public 的过程(Sub 或 Function)将成为类的方法。
    'Public 变量将成为类的属性,同使用 Property Get、Property Let 和 Property Set 显式声明的属性一样。
    '类的缺省属性和方法是在它们的声明部分用 Default 关键字指定的。
    Class myClass
    '//----声明(声明就是定义)myClass类的类内部(私有的[Private])变量
    Private strAuthor
    Private strVersion
    Private strExample
    '//---------------------------定义类的事件-------------------------------//
    '//----Class_Initialize()是类的初始化事件,只要一开始使用该类,首先会触发该部分的执行.
    '下面我们会在该成员中初始化该类的作者和版本以在屏幕上显示一下该类已经开始了
    Private Sub Class_Initialize()
    strAuthor = "思源"
    strVersion = "1.0"
    Response.Write "<br/>myClass开始了<br/>"
    End Sub
    '//----Class_Terminate()是类的结束事件,只要一退出该类,就会触发该事件.
    '下面我们会该事件中设定退出该类时会在屏幕上显示该类已结束了。
    Private Sub Class_Terminate()
    Response.Write "<br/>myClass结束了<br/>"
    End Sub
    '//---------------------------用户自己定义的方法-------------------------------//
    '//----该方法返回一个版本信息
    Public Sub Information()
    Response.Write "<br/>Coding By <a href='mailto:coder@sinobe.com'>Maxid_Zen</a> @ <a href='http://www.design60s.com'>www.design60s.com</a>.<br/>"
    End Sub
    '//---------------------------定义类的输出属性-------------------------------//
    '//----定类的属性,该属性是让用户初始化strExample变量
    Public Property Let setExample(ByVal strVar)
    strExample = strVar
    End Property
    '//---------------------------定义类的输出属性-------------------------------//
    '//----定义类的属性,该属性是返回一个版本号
    Public Property Get Version
    Version = strVersion
    End Property
    '//----定义类的属性,该属性是返回该类的作者号
    Public Property Get Author
    Author = strAuthor
    End Property
    '//----定义类的属性,该属性是返回用户自定义信息
    Public Property Get Example
    Example = strExample
    End Property

    End Class
    %>
    <%
    '//-------这里是使用该类的例子
    Dim oneNewClass
    Set oneNewClass = new myClass
    Response.Write "作者:" & oneNewClass.Author & "<br/>"
    Response.Write "版本:" & oneNewClass.Version & "<br/>"
    oneNewClass.setExample = "这是一个简单类的例子"
    Response.Write "用户自定义:" & oneNewClass.Example & "<br/>"
    oneNewClass.Information
    Set oneNewClass = Nothing
    %>
    =======================================================================
    Property Get 语句
    在 Class 块中,声明构成用来取得(返回)的值的属性过程的主体的名称、参数和代码。
     [Public [Default]| Private] Property Get name [(arglist)]
        [statements]
        [[Set] name = expression]
        [Exit Property]
        [statements]
        [[Set] name = expression]
    End Property
    参数
    Public
    表明Property Get 过程可以被所有脚本中的其他过程访问。
    Default
    只与 Public 关键字一起使用,表明 Property Get 过程中定义的属性为类的缺省属性。
    Private
    表明 Property Get 过程只对定义它的 Class 块中的其他过程是可以访问的。
    name
    Property Get 过程的名称;遵守标准的变量命名规则,区别仅仅在于它可以与同一Class块中的Property Let 或 Property Set过程。
    arglist
    该变量列表代表了 Property Get 过程被调用时传递给它的参数。多个参数之间用逗号分隔开。Property Get 过程中的每个参数的名称必须与 Property Let 过程中的相应参数相同(如果有的话)。
    statements
    任意的一组语句,将在 Property Get 过程的主体中执行。
    Set
    在将对象作为 Property Get 过程的返回值时使用的关键字。
    expression
    Property Get 过程的返回值。
    说明
    如果未使用 Public 或 Private明确声明,则 Property Get 过程被缺省为公有的,即它们对于脚本中的其他所有过程都是可见的。Property Get过程中的局部变量的值在不同的过程调用之间是不保存的。
    在其他任何过程(例如 Function 或 Property Let) 内部都不能定义 Property Get 过程。
    Exit Property 语句将导致立即从 Property Get 过程中退出。程序将继续执行调用 Property Get 过程的语句之后的程序。Exit Property 语句可以出现在 Property Get 过程中的任何位置,次数不限。
    与Sub 和 Property Let 过程类似,Property Get 过程是能够接受参数的过程,可以执行一系列的语句,以及改变参数的值。然而,与Sub 和 Property Let 不同的是,Property Get 过程可以被用于表达式的右侧,用与使用Function 或属性名称相同的方式来返回属性的值。
    ==============================================================================
    Property Let 语句
    在 Class 块中,声明名称、参数和代码等,它们构成了赋值(设置)的 Property 过程的主体。
     [Public | Private] Property Let name (
      [arglist,] value
    )
        [statement]
        [Exit Property]
        [statement]
    End Property
    参数
    Public
    表明 Property Let 过程可以被所有脚本中的其他所有过程访问。
    Private
    表明 Property Let 过程只能被定义之的 Class 块内的其他过程访问。
    name
    Property Let 过程的名称;遵守标准的变量命名规则,区别仅仅在于其名称可以与相同 Class 块中的 Property Get 或 Property Set 过程相同。
    arglist
    该变量列表代表了在调用时被传递到 Property Let 过程的参数。多个参数之间用逗号隔开。Property Let 过程的每个参数的名字必须与 Property Get 过程中的相应参数相同。此外, Property Let 过程的参数比相应的 Property Get 过程总要多一个。该参数为被赋予属性的值。
    value
    该变量中包含要赋予属性的值。当过程被调用时,该参数将出现在调用表达式的右侧。
    statement
    任意的一组语句,将在 Property Let 过程的主体内执行。
    注意每个 Property Let 语句必须为所定义的属性定义至少一个参数。该参数(在存在多个参数时的最后一个参数)包含了当 Property Let 语句被调用时要赋予属性的值。该参数在前面的语法中被称为value。
    说明
    如果未明确地使用 Public 或 Private进行指定,Property Let 过程被缺省设置为公有的,即它们对于脚本内的其他所有过程都是可见的。Property Let过程中的局部变量的值在不同的过程调用之间是不被保存的。
    在其他任何过程(例如 Function 或 Property Get)的内部不能够定义 Property Let 过程。
    Exit Property 语句将导致立即从 Property Let 过程中退出。程序将从调用 Property Let 过程的语句之后的点继续执行。Exit Property 语句可以出现在 Property Let 过程中的任何位置,次数不限。
    与 Function 和 Property Get 过程类似,Property Let 过程是一个单独的过程,它可以接受参数,执行一系列的语句,还可以改变参数的值。不过,与Function 和 Property Get 过程不同的是,它们两者都返回一个值,而Property Let过程只能用于属性赋值表达式的左侧。

    ===================================================================================
    Property Set 语句
    在 Class 块中,声明名称、参数和代码,这些构成了将引用设置到对象的 Property 过程的主体。
     [Public | Private] Property Set name(
      [arglist,] reference
    )
        [statement]
        [Exit Property]
        [statement]
    End Property
    参数
    Public
    表明 Property Set 过程可以被所有脚本中的其他所有过程访问。
    Private
    表明 Property Set 过程只能被声明之的同一 Class 块中的其他过程访问。
    name
    Property Set 过程的名称;遵守标准的变量命名规则,不过该名称可以与同一个 Class 块中的 Property Get 或 Property Let 过程相同。
    arglist
    变量列表,代表在 Property Set 过程被调用时传递给它的参数。多个参数之间用逗号分隔开。此外,Property Set 过程将总是比它相应的 Property Get 过程多一个参数。这个多出来的参数是被赋予的对象。
    reference
    变量,其中包含被用于对象引用赋值的右侧的对象引用。
    statement
    将要在 Property Set 过程主体中执行的任何一组语句。
    注意每个 Property Set 语句都必须为所定义的过程定义至少一个参数。当 Property Set 语句所定义的过程被调用时,该必需参数(在多个参数时为最后一个参数)中将为属性提供实际的对象引用。在前面的语法中,该参数被称为引用。
    说明
    除非使用 Public 或 Private 明确地进行指定,否则 Property Set 过程被设置为缺省的公有模式,即脚本中的其他所有过程都是可见的。在不同的过程调用时,Property Set 过程中的局部变量是不保存的。
    在其他任何过程(例如Function或Property Let)中都不能够定义Property Set过程。
    Exit Property 语句将导致立即从 Property Set 过程中退出。程序将继续执行调用 Property Set 过程之后的语句。Exit Property 语句的数量不受限制,可以出现在 Property Set 过程中的任何位置。
    与 Function 和 Property Get 过程类似,Property Set 过程是一个单独的过程,它可以有若干参数,执行一系列的语句,还可以改变参数的值。然而,与 Function 和 Property Get 过程不同的是,函数和过程都可以返回值,而 Property Set 过程对象引用赋值(Set 语句)的左侧。

    全正则的检测IP是否合法的函数


    function checkIP2(sIPAddress)
    {
        var exp=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
        var reg = sIPAddress.match(exp);
        var ErrMsg="你输入的是一个非法的IP地址段!\nIP段为::xxx.xxx.xxx.xxx(xxx为0-255)!"   
        var Msg="你输入的是一个合法的IP地址段!"   
        if(reg==null)
        {
            alert(ErrMsg);
        }
        else
        {
            alert(reg);
        }
    }

    判断一个access数据库中某个表是否存在的方法

    <%
    rem x=0 表示不存在,x=1 表示存在
    strConn="DBQ="+server.mappath("zw.mdb")+";DefaultDir=;DRIVER={Microsoft Access Driver (*.mdb)};"
    set objConn=server.createobject("Adodb.connection")
    objConn.open strConn
    set rsSchema=objConn.openSchema(20)
    rsSchema.movefirst
    tablename="gd111"
    x=0
    Do Until rsSchema.EOF
       if rsSchema("TABLE_TYPE")="TABLE" then
        if  rsSchema("TABLE_NAME")=tablename then
            x=1
            exit do
        end if
       end if

       rsSchema.movenext
    Loop
    if x=0 then response.write"没有找到!!!"
    if x=1 then response.write"找到了"

    set objConn=nothing
    %>

    一段在asp中加密与解密对应的函数

    在ASP中加密方法有对应的解密方法好象不多,现在根据前辈资料整理出在asp中加密与解密函数
    rsa.asp
    <%
    rem 在ASP中实现加密与解密,加密方法:根据RSA
    rem 联系:hnsoso@sina.com
    Class clsRSA
      Public PrivateKey
      Public PublicKey
      Public Modulus
      
      
      
      Public Function Crypt(pLngMessage, pLngKey)
        On Error Resume Next
        Dim lLngMod
        Dim lLngResult
        Dim lLngIndex
        If pLngKey Mod 2 = 0 Then
          lLngResult = 1
          For lLngIndex = 1 To pLngKey / 2
            lLngMod = (pLngMessage ^ 2) Mod Modulus
            ' Mod may error on key generation
            lLngResult = (lLngMod * lLngResult) Mod Modulus
            If Err Then Exit Function
          Next
        Else
          lLngResult = pLngMessage
          For lLngIndex = 1 To pLngKey / 2
            lLngMod = (pLngMessage ^ 2) Mod Modulus
            On Error Resume Next
            ' Mod may error on key generation
            lLngResult = (lLngMod * lLngResult) Mod Modulus
            If Err Then Exit Function
          Next
        End If
        Crypt = lLngResult
      End Function
     
      Public Function Encode(ByVal pStrMessage)
        Dim lLngIndex
        Dim lLngMaxIndex
        Dim lBytAscii
        Dim lLngEncrypted
        lLngMaxIndex = Len(pStrMessage)
        If lLngMaxIndex = 0 Then Exit Function
        For lLngIndex = 1 To lLngMaxIndex
          lBytAscii = Asc(Mid(pStrMessage, lLngIndex, 1))
          lLngEncrypted = Crypt(lBytAscii, PublicKey)
          Encode = Encode & NumberToHex(lLngEncrypted, 4)
        Next
      End Function
      
      Public Function Decode(ByVal pStrMessage)
        Dim lBytAscii
        Dim lLngIndex
        Dim lLngMaxIndex
        Dim lLngEncryptedData
        Decode = ""
        lLngMaxIndex = Len(pStrMessage)
        For lLngIndex = 1 To lLngMaxIndex Step 4
          lLngEncryptedData = HexToNumber(Mid(pStrMessage, lLngIndex, 4))
          lBytAscii = Crypt(lLngEncryptedData, PrivateKey)
          Decode = Decode & Chr(lBytAscii)
        Next
      End Function
      
      Private Function NumberToHex(ByRef pLngNumber, ByRef pLngLength)
        NumberToHex = Right(String(pLngLength, "0") & Hex(pLngNumber), pLngLength)
      End Function
      Private Function HexToNumber(ByRef pStrHex)
        HexToNumber = CLng("&h" & pStrHex)
      End Function
    End Class
    %>
     
    test.asp
    <!--#INCLUDE FILE="RSA.asp"-->
    <%
    function Encryptstr(Message)
    Dim LngKeyE
    Dim LngKeyD
    Dim LngKeyN
    Dim StrMessage
    Dim ObjRSA

      LngKeyE = "32823"
      LngKeyD = "20643"
      LngKeyN = "29893"
      StrMessage = Message
      
      Set ObjRSA = New clsRSA
      
     
          ObjRSA.PublicKey = LngKeyE
          ObjRSA.Modulus = LngKeyN
          Encryptstr = ObjRSA.Encode(StrMessage)
      Set ObjRSA = Nothing
    end function
     

    function decryptstr(Message)
    Dim LngKeyE
    Dim LngKeyD
    Dim LngKeyN
    Dim StrMessage
    Dim ObjRSA

      LngKeyE = "32823"
      LngKeyD = "20643"
      LngKeyN = "29893"
      StrMessage = Message
      
      Set ObjRSA = New clsRSA
          ObjRSA.PrivateKey =LngKeyD
          ObjRSA.Modulus=LngKeyN
          decryptstr=ObjRSA.Decode(StrMessage)
      Set ObjRSA = Nothing
    end function
     
    dim last,first
    first="sohu"
    Response.Write "加密前为:"&first
    last=Encryptstr(first)
    Response.Write "加密后为"&last
    Response.Write "解密后为" &decryptstr(last)
    %>
    June 03

    C#中类的访问修饰字

    public 无限制。标记为public的成员对于任何类的方法都是可以访问的。
     private 标记为private的类A中的成员,只对类A的方法是可以访问的。
     protected标记为protected的类A中的成员,只对类A的和从类A派生的类的方法而言是可以访问的。
     internal标记为internal的类A中的成员,对A所处配件中的任何类的方法都是可以访问的。
     protected internal带此标记的类A中的成员,对类A和从类A派生的类的方法,以及A所处配件中的任何类的方法而言都是可访问的。实际等效于internal或protected.(没有interanl与protected的概念)
    June 02

    如果让一个页面load的时候,自动跳到一个锚点上

    <body onload="window.scrollTo(0,document.body.scrollHeight)">
     
     
     
    <body onload="location='#tag'">
    网页内容
    <a name="tag">你想跳的位置</a>
    </body>