1. 程式人生 > >SQLServer 臨時表的使用

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;