SQL臨時表(轉)


1、MS SQLSERVER      SQL Server 支持臨時表。臨時表就是那些名稱以井號 (#) 開頭的表。如果當用戶斷開連接時沒有除去臨時表,SQL Server 將自動除去臨時表。臨時表不存儲在當前數據庫內,而是存儲在系統數據庫 tempdb 內。 
     臨時表有兩種類型: 
     本地臨時表:本地臨時表的名稱以單個數字符號 (#) 打頭;它們僅對當前的用戶連接是可見的;當用戶從 Microsoft SQL Server 2000 實例斷開連接時被刪除。 
     全局臨時表:全局臨時表的名稱以數學符號 (##) 打頭,創建后對任何用戶都是可見的。如果在創建全局臨時表的連接斷開前沒有顯式地除去這些表,那么只要所有其它任務停止引用它們,這些表即被除去。當創建全局臨時表的連接斷開后,新的任務不能再引用它們。當前的語句一執行完,任務與表之間的關聯即被除去;因此通常情況下,只要創建全局臨時表的連接斷開,全局臨時表即被除去。 
     例如,如果創建名為 employees 的表,則任何人只要在數據庫中有使用該表的安全權限就可以使用該表,除非它已刪除。如果創建名為 #employees 的本地臨時表,只有您能對該表執行操作且在斷開連接時該表刪除。如果創建名為 ##employees 的全局臨時表,數據表中的任何用戶均可對該表執行操作。如果該表在您創建后沒有其他用戶使用,則當您斷開連接時該表刪除。如果該表在您創建后有其他用戶使用,則 SQL Server在所有用戶斷開連接后刪除該表。 
     現在,臨時表的許多傳統用途可由具有 table 數據類型的變量替換。 


1.SQL SERVER臨時表實用大全
老藍筆記整理:
引子:
            臨時數據表格,我們在存儲的時候經常遇見。
  客戶端可以實用Delphi的ClientDataSet的內存表,但是ClientDataSet類似TABLE,不是支持SQL語言的。
  當然也可以實用臨時表。有時我們避免臨時表的生命周期的麻煩,更多的使用實際表臨時用用。起個什么tempXXX類似的告訴我們他們是臨時表。創建釋放也沒有問題。
  那么臨時表的周期是什么樣子的呢?有什么特殊的用法沒有?
1.全局臨時表和臨時表的區別:視野不同。
   全局臨時表當然就是使用##打頭的表格,普通的臨時表格為#打頭。它們的周期應該隨一個連接也就是Connection的誕生而生,隨着Connection的斷開而死亡。它們的區別不同的地方也就是視野不同。
   全局表,全部授權的Connection都可以看見。但是普通臨時表(局域臨時表)僅僅創建的Connection可以看見。特別說明的是sql server的isql.exe每個連接就是一個Connection。
   例如:一個應用程序app.exe有僅adoconnection連接SQL SERVER數據,那么這個連接中的adoquery或者存儲過程建立的全局表##temp1,另外的一個app.exe或者其它的appx.exe都可以使用該表格。
   不同的是普通臨時表,由app.exe中的連接connection比如adoconnection的Adoquery建立的臨時表#temp,在所有該連接的該程序的app.exe都可以看見並且訪問,但是appx.exe或者其它的就不能看見。
陷阱:如果一個應用程序app.exe有存儲過程和TADOQUERY連接同一個ADOCONNECTION.切記使用存儲過程建立的臨時表(非全局),就不能被這個連接下的TADOQUERY訪問。原因是:存儲過程本身是服務器端執行,應該是服務器的CONNECTION。
2.全局表或者臨時表的存儲和建立。
   估計大家都知道,臨時表或者全局表都是在sql server的tempdb數據庫存儲,表我們訪問的時候使用#,但是實際在進程里面是以在tempdb里面的用戶表以#xxx_________00000000xxx方式存儲(是否是進程標識,不大知道,也不想知道)。可以通過isql.exe的tempdb里面看見它們。
3。頭痛初始化表格
  初始化表格,為什么頭痛,畢竟使用Drop什么的。或者判斷存在比較麻煩。其實也很簡單。另外建立臨時表,都是無聊的SQL 語句,怎么處理。
方法一:當然是使用存儲過程了。可以直接寫SQL語句或者寫exec (@v_sql)。
方法二:把臨時表保存到數據里面MEMO里面,讀取,直接執行。
  判斷方法一:可以采用常用的exists函數。
   例如:if        exists        (select        *        from        tempdb..sysobjects        where        id        =        object_id(@sTmpWareA)        and        type        =        "U")    
  判斷方法二:
  if object_id('tempdb.dbo.##'+@v_userid) is null
應用方法一:(感謝阿滿,迷糊)
    一個統計的臨時表格,使用TADOPROC執行存儲過程,如下:
CREATE PROCEDURE InitCreateCoawardTable AS
BEGIN
    IF not (object_id('tempdb.dbo.#Tmp_Detail') is null)
     drop table tempdb.dbo.#Tmp_Detail
     CREATE TABLE tempdb.dbo.#Tmp_Detail (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[單據類別] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
[單據編號] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
(。。這里多復雜都可以。。。。。省略。。。)
    select * from tempdb.dbo.#Tmp_Detail
END
GO

在客戶端使用TADOPROC執行這個存儲過程,
    with sproc do
    begin
      try
       Close;
       ProcedureName:=spName;
       Parameters.Refresh;
       Prepared;
       ExecProc;
       Open;//這句不能省略要不,就出現忽略了數據庫名稱 ',將引用 tempdb 中的對象錯誤。

       except
         Close;
         Exit;
       end;
       Result:=True;
    end;

這樣,你的TADOPROC就可以任意使用APPEND,INSERT語句了,更好的是不需要清理,而且方法靈活。更好的有點非常有效的處理並發。當然有些人還在使用建立實際表格代替它,使用會話處理該問題,你還得回收。相當麻煩。而且靈活度差多了。

以下是應用范例轉載:
利用SQL Server的全局臨時表防止用戶重復登錄   
在我們開發商務軟件的時候,常常會遇到這樣的一個問題:怎樣防止用戶重復登錄我們的系統?特別是對於銀行或是財務部門,更是要限制用戶以其工號身份多次登入。
        可能會有人說在用戶信息表中加一字段判斷用戶工號登錄的狀態,登錄后寫1,退出時寫0,且登錄時判斷其標志位是否為1,如是則不讓該用戶工號登錄。但是這樣那勢必會帶來新的問題:如發生象斷電之類不可預知的現象,系統是非正常退出,無法將標志位置為0,那么下次以該用戶工號登錄則不可登入,這該怎么辦呢?
        或許我們可以換一下思路:有什么東西是在connection斷開后可以被系統自動回收的呢?對了,SQL Server的臨時表具備這個特性!但是我們這里的這種情況不能用局部臨時表,因為局部臨時表對於每一個connection來說都是一個獨立的對象,因此只能用全局臨時表來達到我們的目的。
        好了,情況已經明朗話了,我們可以寫一個象下面這樣簡單的存儲過程:

create procedure gp_findtemptable -- 2001/10/26 21:36 zhuzhichao in nanjing
/* 尋找以操作員工號命名的全局臨時表
如無則將out參數置為0並創建該表,如有則將out參數置為1 
在connection斷開連接后,全局臨時表會被SQL Server自動回收
* 如發生斷電之類的意外,全局臨時表雖然還存在於tempdb中,但是已經失去活性
* 用object_id函數去判斷時會認為其不存在. */
@v_userid varchar(6), -- 操作員工號
@i_out int out -- 輸出參數 0:沒有登錄 1:已經登錄
as
declare @v_sql varchar(100)
if object_id('tempdb.dbo.##'+@v_userid) is null
begin
        set @v_sql = 'create table ##'+@v_userid+'(userid varchar(6))'
        exec (@v_sql)
        set @i_out = 0
end
else
        set @i_out = 1
        在這個過程中,我們看到如果以用戶工號命名的全局臨時表不存在時過程會去創建一張並把out參數置為0,如果已經存在則將out參數置為1。
        這樣,我們在我們的應用程序中調用該過程時,如果取得的out參數為1時,我們可以毫不客氣地跳出一個message告訴用戶說”對不起,此工號正被使用!”
判斷方法范例:
select        @sTmpWareA="tempdb..[##MARWareA"+        @ComputerName+"]"      

if        exists        (select        *        from        tempdb..sysobjects        where        id        =        object_id(@sTmpWareA)        and        type        =        "U")    
            begin  
                  set        @sTmpWareA="[##MARWareA"+        @ComputerName+"]"      
                  exec(        "drop        table        "        +@sTmpWareA        )    
            end  
else  
                  set        @sTmpWareA="[##MARWareA"+        @ComputerName+"]"      
  
@sTmpWareA        就是臨時表的名稱,過程中使用exec來操作


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM