SQLServer 臨時表的使用
臨時表在Sqlserver資料庫中,是非常重要的,下面就詳細介紹SQL資料庫中臨時表的特點及其使用,僅供參考。
臨時表與永久表相似,但臨時表儲存在tempdb中,當不再使用時會自動刪除。臨時表有兩種型別:本地和全域性。它們在名稱、可見性以及可用性上有區別。
對於臨時表有如下幾個特點:
- 本地臨時表就是使用者在建立表的時候添加了“#”字首的表,其特點是根據資料庫連線獨立。只有建立本地臨時表的資料庫連線有表的訪問許可權,其它連線不能訪問該表;
- 不同的資料庫連線中,建立的本地臨時表雖然“名字”相同,但是這些表之間相互並不存在任何關係;在SQLSERVER中,通過特別的命名機制保證本地臨時表在資料庫連線上的獨立性。
- 真正的臨時表利用了資料庫臨時表空間,由資料庫系統自動進行維護,因此節省了表空間。並且由於臨時表空間一般利用虛擬記憶體,大大減少了硬碟的I/O次數,因此也提高了系統效率。
- 臨時表在事務完畢或會話完畢資料自動清空,不必記得用完後刪除資料。
本地臨時表
本地臨時表的名稱以單個數字元號 (#) 打頭;它們僅對當前的使用者連線(也就是建立本地臨時表的connection)是可見的;當用戶從 SQL Server 例項斷開連線時被刪除。
例如我們在一個數據庫連線中用如下語句建立本地臨時表#Temp
資料庫連線1:
CREATE TABLE #Temp ( id int, customer_name nvarchar(50), age int )
然後同時啟動資料庫連線2,執行查詢#Temp的操作
資料庫連線2:
select * from #Temp
我們來看看資料庫連線2的結果是什麼?
資料庫連線2:
結果顯示,資料庫連線2找不到表#Temp。這說明#Temp這張臨時表,只是對建立它的資料庫連線1可見,而對於資料庫連線2來說是不可見的。
全域性臨時表
全域性臨時表的名稱以兩個數字符號 (##) 打頭,建立後對任何資料庫連線都是可見的,當所有引用該表的資料庫連線從 SQL Server 斷開時被刪除。
例如我們在一個數據庫連線中用如下語句建立全域性臨時表##Temp,然後插入三行資料
資料庫連線1:
CREATE TABLE##Temp ( id int, customer_name nvarchar(50), age int ) INSERT INTO ##Temp VALUES(1,'老王',20),(2,'老張',30),(3,'老李',25)
接著我們在資料庫連線2中,查詢##Temp的資料
資料庫連線2:
select * from ##Temp
資料庫連線2結果如下
資料庫連線2:
可以看到,資料庫連線2可以成功訪問到資料庫連線1建立的全域性臨時表##Temp,但是如果我們現在關閉資料連線1,然後再執行資料庫連線2的##Temp查詢語句會發生什麼呢?結果如下:
關閉資料庫連線1,然後資料庫連線2再次執行:
select * from ##Temp
我們發現關閉資料庫連線1後,資料庫連線2就找不到全域性臨時表##Temp了。這是因為資料庫連線1被關閉後,資料庫連線2此時也沒有語句正在使用臨時表##Temp,所以Sqlserver認為此時已經沒有資料庫連線在引用全域性臨時表##Temp了,就將##Temp釋放掉了。
接下來,我們嘗試在資料庫連線2中對全域性臨時表##Temp持有事務中的排他鎖(X鎖)後,然後關閉資料庫連線1.
資料庫連線1:
CREATE TABLE ##Temp ( id int, customer_name nvarchar(50), age int ) INSERT INTO ##Temp VALUES(1,'老王',20),(2,'老張',30),(3,'老李',25)
資料庫連線2:
BEGIN TRAN select * from ##Temp with(xlock)
關閉資料庫連線1,然後資料庫連線2執行:
select * from ##Temp
結果顯示我們儘管關閉了資料庫連線1,但是由於資料庫連線2在事務中一直持有全域性臨時表##Temp的排他鎖(X鎖),所以臨時表##Temp並沒有隨著資料庫連線1的關閉而被釋放掉,只要資料庫連線2中啟動的事務沒有被回滾或提交,那麼資料庫連線2會一直持有臨時表##Temp的排他鎖,這時Sqlserver會認為還有資料庫連線正在引用全域性臨時表##Temp,所以##Temp不會被釋放掉。
查詢資料並寫入臨時表:
select * into #tab from table;
刪除臨時表:
drop table #tab;