我是SQL小菜鸟---SQL全局临时表防止用户重复登录
先介绍一下什么是sql临时表及使用方法
临时表
SQL Server 支持临时表。临时表就是那些名称以井号 (#) 开头的表。如果当用户断开连接时没有除去临时表,SQL Server 将自动除去临时表。临时表不存储在当前数据库内,而是存储在系统数据库 tempdb 内。
临时表有两种类型:
本地临时表
以一个井号 (#) 开头的那些表名。只有在创建本地临时表的连接上才能看到这些表。
全局临时表
以两个井号 (##) 开头的那些表名。在所有连接上都能看到全局临时表。如果在创建全局临时表的连接断开前没有显式地除去这些表,那么只要所有其它任务停止引用它们,这些表即被除去。当创建全局临时表的连接断开后,新的任务不能再引用它们。当前的语句一执行完,任务与表之间的关联即被除去;因此通常情况下,只要创建全局临时表的连接断开,全局临时表即被除去。
--应用本地临时表
declare @sql varchar(100)
set @sql='select ''123'' as a,''abasdf'' as b into #t'
exec(@sql)
select * from #t
go
/*发现不能正确显示临时表的数据
提示:
服务器: 消息 208,级别 16,状态 1,行 5
对象名 '#t' 无效。
*/
--修改为全局临时表
declare @sql varchar(100)
set @sql='select ''123'' as a,''abasdf'' as b into ##t'
exec(@sql)
select * from ##t
drop table ##t
go
/*可以正确显示临时表的数据
分析原因:exec(@sql) 相当于重新建立一个数据库对话,所以对于本地临时表,使用exec(@sql)创建临时表,
在exec外部不能正确访问;而使用全局临时表就ok了
*/
- SQL code
-
exec ('select top 10 * into ##temp from syhouse'); exec ('select * from ##temp');
为了防止用户的重复登录,在一开始想到的一种方法:
在用户表中添加一个字段,登录后写1,退出后写0.这样子在用户登录进行检查的时候判断这个字段是否为0,如果是0那么就可以登录;但是这样子就又带来了新的问题,如果在用户正在登录的过程中突然断电,那么表中写入的是1,也就是说用户在以后的登录中都不能能够登录系统了。
另外一种方法:在SQL Server中建立全局临时表,如果用户没有登录就建立一个临时表来存放用户,如果已经登录那么就提醒用户此账号已经登录;临时表相比较上面一个方法的好处就在于:当系统与SQL Server数据库的连接断开以后,临时表是可以被系统自动收回的,这样子用户下次登录的时候会再次建立一个临时表并且可以登录成功!
依据第二种思路我们建立一个存储过程:
- create proc PROC_FindTemptable
- /*
- * 寻找以操作员工号命名的全局临时表
- * 如无则将out参数置为0并创建该表,如有则将out参数置为1
- * 在connection断开连接后,全局临时表会被SQL Server自动回收
- * 如发生断电之类的意外,全局临时表虽然还存在于tempdb中,但是已经失去活性
- * 用object_id函数去判断时会认为其不存在.
- */
- @View_userID char(20),--输入参数 操作员账号
- @outResult int out --输出参数( 0:没有登录 1:已经登录)
- as
- declare @View_sql varchar(100)
- --object_id函数判断操作员账号不存在(没有的登录)
- if OBJECT_ID ('tempdb.dbo.##'+@View_userID )is null
- begin
- --创建临时表
- set @View_sql ='create table ##'+@View_userid+'(userid char(20))'
- exec(@View_sql)
- --out参数设置为0(账号没有登录)
- set @outResult =0
- end
- --账号存在
- else
- --out参数为1
- set @outResult =1
- --在这个过程中,我们看到如果以用户工号命名的全局临时表不存在时过程会去创建一张并把out参数置为0,如果已经存在则将out参数置为1。
- --这样,应用程序中调用该过程时,如果取得的out参数为1时,我们可以毫不客气地跳出一个message告诉用户说”对不起,此工号正被使用!”
在系统中调用存储过程来实现用户登录的代码:将与数据库的连接和执行存储过程写在一个函数中,然后在客户端调用即可!
- Public Function ExecuteProcTestID(ByVal strID As String, ByVal strProc As String) As Integer
- Dim myConnection As New SqlConnection(CmdString) '定义连接
- Dim Cmd As New SqlCommand '表示SQL命令语句的执行
- '连接数据库将存储名称和参数传递给cmd
- Cmd.Connection = myConnection
- '指明为存储过程
- Cmd.CommandType = CommandType.StoredProcedure
- Cmd.CommandText = strProc
- Cmd.Parameters.Add("@View_userID", SqlDbType.VarChar, 20).Value = strID
- Cmd.Parameters.Add("@outResult", SqlDbType.VarChar, 20).Direction = ParameterDirection.Output
- Try
- '执行存储过程
- Cmd.ExecuteNonQuery()
- Return Cmd.Parameters(1).Value()
- Catch e As Exception
- Return False
- End Try
- End Function
此贴说明以上方法是行不通的 http://bbs.csdn.net/topics/340244117 呵呵