原創鏈接:https://blog.csdn.net/laizhixue/article/details/79798648
臨時表在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;