當前位置:首頁 » 編程語言 » sqlserver表變數和臨時表
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

sqlserver表變數和臨時表

發布時間: 2022-07-02 12:27:15

sql Server 表變數和臨時表的區別

一、臨時表

臨時表表名長度:
不能大於116位元組
臨時表分為以下兩種:
1.1 全局臨時表
全局臨時表,需要使用 ##做為前綴,全局臨時表當表被創建時,在整個資料庫中都可以使用,所以創建全局表時,首先需要檢測對象是否存在。
如果我們不手動的清理和刪除全局臨時表,那麼當我們當前會話或連接關閉時,全局臨時表會自動被drop掉
1.2 局部臨時表
局部臨時表創建以 #前綴開頭,局部臨時表被創建後,只有當前資料庫的會話中可以查看和使用
如果不手動清理和刪除表,那麼當我們當前會話關閉時,系統會自動將臨時表drop
全局臨時表和局部臨時表的區別:

創建表時,所使用的前綴不同
表的作用范圍不同

二、表變數

表變數:是定義一個變數,這個變數的類型是一張表,在表定義的時候,我們可以指定列 列名 數據類型 約束(外鍵約束除外) 索引。。。
表變數的定義方式:
declare @tableName table(列名)

表變數的特點

表變數的作用域非常有限,通常在一個批處理中,

例:在一個存儲過程中
create proc pr_test
as
begin
declare @t table(a varchar(60)
declare @sql varchar(2000)
set @sql =』insert into @t(」ss」)』
exec(@sql) ——-此時就獲取不表變數
end

表變數同臨時表一樣,在系統內存足夠支持的時候,將數據存於內存中
使用變數,避免程序做過多的編譯,提高性能
不能使用 truncate 刪除表變數
表變數雖然是一個變數,但是不能賦值給另外一個表變數

三、何時使用表變數 何時使用臨時表

當需要操作的行數超過100行時,此時應該採用臨時表。
請採納!

② 在sql Server,臨時表和表變數之間的區別

表變數在SQL Server 2000中首次被引入。表變數的具體定義包括列定義,列名,數據類型和約束。而在表變數中可以使用的約束包括主鍵約束,唯一約束,NULL約束和CHECK約束(外鍵約束不能在表變數中使用)。定義表變數的語句是和正常使用Create Table定義表語句的子集。只是表變數通過DECLARE @local_variable語句進行定義。

表變數的特徵:

  • 表變數擁有特定作用域(在當前批處理語句中,但不在任何當前批處理語句調用的存儲過程和函數中),表變數在批處理結束後自動被清除。

  • 表變數較臨時表產生更少的存儲過程重編譯。

  • 針對表變數的事務僅僅在更新數據時生效,所以鎖和日誌產生的數量會更少。

  • 由於表變數的作用域如此之小,而且不屬於資料庫的持久部分,所以事務回滾不會影響表變數。

  • 表變數可以在其作用域內像正常的表一樣使用。更確切的說,表變數可以被當成正常的表或者表表達式一樣在SELECT,DELETE,UPDATE,INSERT語句中使用,但是表變數不能在類似"SELECT select_listINTOtable_variable"這樣的語句中使用。而在SQL Server2000中,表變數也不能用於INSERTINTOtable_variable EXEC stored_procere這樣的語句中。

    表變數不能做如下事情:

  • 雖然表變數是一個變數,但是其不能賦值給另一個變數。

  • check約束,默認值和計算列不能引用自定義函數。

  • 不能為約束命名。

  • 不能Truncate表變數。

  • 不能向標識列中插入顯式值(也就是說表變數不支持SET IDENTITY_INSERT ON)

③ SQL Server 表變數和臨時表的區別

沒怎麼排版,是用的電腦話,看這里吧=》www.cnblogs.com/kissdodog/archive/2013/07/03/3169470.html


表變數與臨時表的區別

關於表變數是什麼(和表變數不是什麼),以及和臨時表的比較讓很多人非常困惑。雖然網上已經有了很多關於它們的文章,但我並沒有發現一篇比較全面的。在本篇文章中,我們將探索表變數和臨時表是什麼(以及不是什麼),然後我們通過使用臨時表和表變數對其解密。

表變數

表變數在SQL Server 2000中首次被引入,那麼,什麼是表變數呢?微軟在BOL (Declare @local_variable)中定義其為一個類型為表的變數。它的具體定義包括列定義,列名,數據類型和約束。而在表變數中可以使用的約束包括主鍵約束,唯一約束,Null約束和Check約束(外鍵約束不能在表變數中使用).定義表變數的語句是和正常使用Create table定義表語句的子集。只是表變數通過DECLARE @local_variable 語句進行定義。

通過參考1可以知道:

1) 表變數擁有特定作用域(在當前批處理語句中,但不在任何當前批處理語句調用的存儲過程和函數中),表變數在批處理結束後自動被清除。

2)參考6中在"Recompilations Due to Certain Temporary Table Operations" 環節討論了臨時表在會導致存儲過程強制被重復編譯的各種原因,但這些原因並不適用於表變數。表變數和臨時表比起來會產生更少的存儲過程重編譯。

3) 針對表變數的事務僅僅在更新數據時生效,所以鎖和日誌產生的數量會更少。

4) 由於表變數的作用域如此之小,而且不屬於資料庫的持久部分,所以事務回滾不會影響表變數。

表變數可以在其作用域內像正常的表一樣使用。更確切的說,表變數可以被當成正常的表或者表表達式一樣在select,delete,update,insert語句中使用。但是表變數不能在類似「SELECT select_list INTO table_variable」 這樣的語句中使用。而在SQL Server 2000中,表變數也不能被用於「INSERT INTO table_variable EXEC stored_procere」這樣的語句中。

表變數不能做如下事情:

1.雖然表變數是一個變數,但是其不能賦值給另一個變數。
2.check約束,默認值,和計算列不能引用自定義函數。
3.不能為約束命名。
4.不能Truncate表變數
5.不能向標識列中插入顯式值(也就是說表變數不支持SETIDENTITY_INSERTON)


臨時表

在深入臨時表之前,我們首先需要討論一下會話(Session),一個會話僅僅是一個客戶端到數據引擎的連接。在SQL Server Management Studio(SSMS)中,每一個查詢窗口都會和資料庫引擎建立連接。一個應用程序可以和資料庫建立一個或多個連接,除此之外,應用程序還可能建立連接後一直不釋放直到應用程序結束,也可能使用完釋放連接需要時建立連接。

那麼,什麼是臨時表?在BOL (CREATE TABLE)中,我們可以知道臨時表和以Create table語句創建的表有著相同的物理構成,但臨時表與正常的表不同之處有:

1) 臨時表的名字不能超過116個字元,這是由於資料庫引擎為了辨別不同會話建立不同的臨時表,所以會自動在臨時表的名字後附加一串

2) 局部臨時表(以「#」開頭命名的)作用域僅僅在當前的連接內,從在存儲過程中建立局部臨時表的角度來看,局部臨時表會在下列情況被Drop:

a.顯式調用DROP Table語句

b.當局部臨時表在存儲過程內被創建時,存儲過程結束也就意味著局部臨時表被DROP

c.當前會話結束,在會話內創建的所有局部臨時表都會被Drop

3) 全局臨時表(以「##」開頭命名的)在所有的會話內可見,所以在創建全局臨時表之前首先檢查其是否存在,否則如果已經存在,你將會得到重復創建對象的錯誤.

a.全局臨時表會在創建其的會話結束後被DROP,其它會話將不能對全局臨時表進行引用。

b.引用是在語句級別進行,比如說下面例子:

i.建立新的查詢窗口,運行如下語句:

create table ##temp (RowID int)

ii.再次開啟一個新的查詢創建,使用如下語句每5秒中對全局臨時表進行引用

while 1=1 begin
select * from ##temp
waitfor delay '00:00:05'
end

iii.回到第一個窗口,關閉窗口

iv.在下一個循環引用全局臨時表時,將產生錯誤

4) 不能對臨時表進行分區。

5) 不能對臨時表加外鍵約束

6) 臨時表內列的數據類型不能定義成沒有在TempDb中沒有定義自定義數據類型(自定義數據類型是資料庫級別的對象,而臨時表屬於TempDb),由於TempDb在每次SQL Server重啟後會被自動創建,所以你必須使用startup stored procere來為TempDb創建自定義數據類型。你也可以通過修改Model資料庫來達到這一目標。

7) XML列不能定義成XML集合的形式,除非這個集合已經在TempDb中定義

臨時表既可以通過Create Table語句創建,也可以通過」SELECT <select_list> INTO #table」語句創建。你還可以針對臨時表使用」INSERT INTO #table EXEC stored_procere」這樣的語句。

臨時表可以擁有命名的約束和索引。但是,當兩個用戶在同一時間調用同一存儲過程時,將會產生」There is already an object named 『<objectname>』 in the database」這樣的錯誤。所以最好的做法是不用為建立的對象進行命名,而使用系統分配的在TempDb中唯一的。6

參考6談論了很多由於臨時表而導致的存儲過程重編譯的原因以及避免的方法。

誤區

誤區1.表變數僅僅在內存中。

誤區2.臨時表僅僅存儲在物理介質中

這兩種觀點都是明顯的誤區,在參考1的Q4節。表變數都是在TempDb資料庫中創建,因為表變數存儲的數據有可能超過物理內存。除此之外,我們發現只要內存足夠,表變數和臨時表都會在內存中創建和處理。它們也同樣可以在任何時間被存入磁碟。

如何證明這點?請看下面代碼(在SQL Server 2000到2008中都有效)

--
--TempDBdatabase
ifobject_id('tempdb..#tempTables')isnotnulldroptable#tempTables
selectnameinto#tempTablesfromtempdb..sysobjectswheretype='U'
--.
--.
select*from#tempTableswherenamelike'#tempTables%'
GO
--createatablevariable
declare@MyTableVariabletable(RowIDint)
--.
selectnamefromtempdb..sysobjects
wheretype='U'andnamenotin(selectnamefrom#tempTables)

還有一些「證明」臨時表僅僅存在於內存中謬誤,下面我來指出其中一個:

注意表變數的名字是系統分配的,表變數的第一個字元」@」並不是一個字母,所以它並不是一個有效的變數名。系統會在TempDb中為表變數創建一個系統分配的名稱,所以任何在sysobjects或sys.tables查找表變數的方法都會失敗。

正確的方法應該是我前面例子中的方法,我看到很多人使用如下查詢查表變數:

select * from sysobjects where name like'#tempTables%'


上述代碼看上去貌似很好用,但會產生多用戶的問題。你建立兩個連接,在第一個連接中創建臨時表,在第二個窗口中運行上面的語句能看到第一個連接創建的臨時表,如果你在第二個連接中嘗試操作這個臨時表,那麼可能會產生錯誤,因為這個臨時表不屬於你的會話。

誤區3.表變數不能擁有索引。

這個誤區也同樣錯誤。雖然一旦你創建一個表變數之後,就不能對其進行DDL語句了,這包括Create Index語句。然而你可以在表變數定義的時候為其創建索引)比如如下語句.

declare @MyTableVariable table (RowID intPRIMARY KEY CLUSTERED)

這個語句將會創建一個擁有聚集索引的表變數。由於主鍵有了對應的聚集索引,所以一個系統命名的索引將會被創建在RowID列上。

下面的例子演示你可以在一個表變數的列上創建唯一約束以及如何建立符合索引。

declare@tempTABLE(
RowIDintNOTNULL,
ColAintNOTNULL,
ColBchar(1)UNIQUE,
PRIMARYKEYCLUSTERED(RowID,ColA))

1) SQL 並不能為表變數建立統計信息,就像其能為臨時表建立統計信息一樣。這意味著對於表變數,執行引擎認為其只有1行,這也意味著針對表變數的執行計劃並不是最優。雖然估計的執行計劃對於表變數和臨時表都為1,但是實際的執行計劃對於臨時表會根據每次存儲過程的重編譯而改變(看參考1,Q2部分).如果臨時表不存在,在生成執行計劃的時候會產生錯誤。

2) 前面提到,一定建立表變數後就無法對其進行DDL語句操作。因此如果需要為表建立索引或者加一列,你需要臨時表。

3) 表變數不能使用select …into語句,而臨時表可以

4) 在SQL Server 2008中,你可以將表變數作為參數傳入存儲過程。但是臨時表不行。在SQL Server 2000和2005中表變數也不行。

5) 作用域:表變數僅僅在當前的批處理中有效,並且對任何在其中嵌套的存儲過程等不可見。局部臨時表只在當前會話中有效,這也包括嵌套的存儲過程。但對父存儲過程不可見。全局臨時表可以在任何會話中可見,但是會隨著創建其的會話終止而DROP,其它會話這時就不能再引用全局臨時表。

6) 排序規則:表變數使用當前資料庫的排序規則,臨時表使用TempDb的排序規則。如果它們不兼容,你還需要在查詢或者表定義中進行指定(參考7.Table Variables and Temporary Tables)

7) 你如果希望在動態SQL中使用表變數,你必須在動態SQL中定義表變數。而臨時表可以提前定義,在動態SQL中進行引用。

說了這么多,那麼,我該如何選擇呢?

微軟推薦使用表變數(看參考4),如果表中的行數非常小,則使用表變數。很多」網路專家」會告訴你100是一個分界線,因為這是統計信息創建查詢計劃效率高低的開始。但是我還是希望告訴你針對你的特定需求對臨時表和表變數進行測試。很多人在自定義函數中使用表變數,如果你需要在表變數中使用主鍵和唯一索引,你會發現包含數千行的表變數也依然性能卓越。但如果你需要將表變數和其它表進行join,你會發現由於不精準的執行計劃,性能往往會非常差。

為了證明這點,請看本文的附件。附件中代碼創建了表變數和臨時表.並裝入了AdventureWorks資料庫的Sales.SalesOrderDetail表。為了得到足夠的測試數據,我將這個表中的數據插入了10遍。然後以ModifiedDate 列作為條件將臨時表和表變數與原始的Sales.SalesOrderDetail表進行了Join操作,從統計信息來看IO差別顯著。從時間來看錶變數做join花了50多秒,而臨時表僅僅花了8秒。

如果你需要在表建立後對表進行DLL操作,那麼選擇臨時表吧。

臨時表和表變數有很多類似的地方。所以有時候並沒有具體的細則規定如何選擇哪一個。對任何特定的情況,你都需要考慮其各自優缺點並做一些性能測試。下面的表格會讓你比較其優略有了更詳細的參考。

④ SQL Server 表變數和臨時表的區別

表變數是一種特殊的數據類型,用於存儲結果集以進行後續處理。table 主要用於臨時存儲一組作為表值函數的結果集返回的行。其作用域為一個語句批。臨時表有兩種類型:本地表和全局表。在與首次創建或引用表時相同的 SQL Server 實例連接期間,本地臨時表只對於創建者是可見的。當用戶與 SQL Server 實例斷開連接後,將刪除本地臨時表,所以局部臨時表的作用域為當前連接。全局臨時表在創建後對任何用戶和任何連接都是可見的,當引用該表的所有用戶都與 SQL Server 實例斷開連接後,將刪除全局臨時表,所以全局臨時表的作用域為所有連接。

⑤ sql2005中臨時表#table和表變數@table有什麼不同呀

我記得以前在哪些地方看到過。

表變數和臨時表是兩個不同的東西,但是他們是可以用於一些共同的用途的。不過要注意一下使用的場景。
臨時表
臨時表有兩種類型:本地表和全局表。本地臨時表的名稱都是以「#」為前綴,全局臨時表的名稱都是以「##」為前綴。臨時表的訪問是有可能造成物理IO的。臨時表可以有索引、數據統計這些。
表變數
表變數是變數的一種,表變數也分為本地及全局的兩種。表變數存放在內存中,但是並不是沒有限制而是有一定限制的,如果表變數數據量超過閾值,會把內存耗盡,然後使用硬碟空間,這時再訪問他就會增加了內存調入調出的機會,反而降低速度。表變數是不能有索引的。
大概就是這些,其他的記不住了。

⑥ sqlserver怎麼建臨時表

網上其實很多相關文章,你可以搜一下,並不一定需要在這里提問。
轉帖一篇給你吧

drop table #Tmp --刪除臨時表#Tmp
create table #Tmp --創建臨時表#Tmp
(
ID int IDENTITY (1,1) not null, --創建列ID,並且每次新增一條記錄就會加1
WokNo varchar(50),
primary key (ID) --定義ID為臨時表#Tmp的主鍵
);
Select * from #Tmp --查詢臨時表的數據
truncate table #Tmp --清空臨時表的所有數據和約束

相關例子:

Declare @Wokno Varchar(500) --用來記錄職工號
Declare @Str NVarchar(4000) --用來存放查詢語句
Declare @Count int --求出總記錄數
Declare @i int
Set @i = 0
Select @Count = Count(Distinct(Wokno)) from #Tmp
While @i < @Count
Begin
Set @Str = 'Select top 1 @Wokno = WokNo from #Tmp Where id not in (Select top ' + Str(@i) + 'id from #Tmp)'
Exec Sp_ExecuteSql @Str,N'@WokNo Varchar(500) OutPut',@WokNo Output
Select @WokNo,@i --一行一行把職工號顯示出來
Set @i = @i + 1
End

臨時表
可以創建本地和全局臨時表。本地臨時表僅在當前會話中可見;全局臨時表在所有會話中都可見。
本地臨時表的名稱前面有一個編號符 (#table_name),而全局臨時表的名稱前面有兩個編號符 (##table_name)。

SQL 語句使用 CREATE TABLE 語句中為 table_name 指定的名稱引用臨時表:

CREATE TABLE #MyTempTable (cola INT PRIMARY KEY)
INSERT INTO #MyTempTable VALUES (1)

如果本地臨時表由存儲過程創建或由多個用戶同時執行的應用程序創建,則 SQL Server 必須能夠區分由不同用戶創建的表。為此,SQL
Server 在內部為每個本地臨時表的表名追加一個數字後綴。存儲在 tempdb 資料庫的 sysobjects 表中的臨時表,其全名由
CREATE TABLE 語句中指定的表名和系統生成的數字後綴組成。為了允許追加後綴,為本地臨時表指定的表名 table_name 不能超過
116 個字元。

除非使用 DROP TABLE 語句顯式除去臨時表,否則臨時表將在退出其作用域時由系統自動除去:

當存儲過程完成時,將自動除去在存儲過程中創建的本地臨時表。由創建表的存儲過程執行的所有嵌套存儲過程都可以引用此表。但調用創建此表的存儲過程的進程無法引用此表。

所有其它本地臨時表在當前會話結束時自動除去。

全局臨時表在創建此表的會話結束且其它任務停止對其引用時自動除去。任務與表之間的關聯只在單個 Transact-SQL 語句的生存周期內保持。換言之,當創建全局臨時表的會話結束時,最後一條引用此表的 Transact-SQL 語句完成後,將自動除去此表。

存儲過程或觸發器中創建的本地臨時表與在調用存儲過程或觸發器之前創建的同名臨時表不同。如果查詢引用臨時表,而同時有兩個同名的臨時表,則不定義針對哪
個表解析該查詢。嵌套存儲過程同樣可以創建與調用它的存儲過程所創建的臨時表同名的臨時表。嵌套存儲過程中對表名的所有引用都被解釋為是針對該嵌套過程所
創建的表,例如:

CREATE PROCEDURE Test2
AS
CREATE TABLE #t(x INT PRIMARY KEY)
INSERT INTO #t VALUES (2)
SELECT Test2Col = x FROM #t
GO
CREATE PROCEDURE Test1
AS
CREATE TABLE #t(x INT PRIMARY KEY)
INSERT INTO #t VALUES (1)
SELECT Test1Col = x FROM #t
EXEC Test2
GO
CREATE TABLE #t(x INT PRIMARY KEY)
INSERT INTO #t VALUES (99)
GO
EXEC Test1
GO

下面是結果集:

(1 row(s) affected)

Test1Col
-----------
1

(1 row(s) affected)

Test2Col
-----------
2

當創建本地或全局臨時表時,CREATE TABLE 語法支持除 FOREIGN KEY 約束以外的其它所有約束定義。如果在臨時表中指定
FOREIGN KEY 約束,該語句將返回警告信息,指出此約束已被忽略,表仍會創建,但不具有 FOREIGN KEY 約束。在 FOREIGN
KEY 約束中不能引用臨時表。

考慮使用表變數而不使用臨時表。當需要在臨時表上顯式地創建索引時,或多個存儲過程或函數需要使用表值時,臨時表很有用。通常,表變數提供更有效的查詢處理。

⑦ SQLSERVER 臨時表分為幾種

臨時表有兩種類型:本地和全局。它們在名稱、可見性以及可用性上有區別。本地臨時表的名稱以單個數字元號 (#) 打頭;它們僅對當前的用戶連接是可見的;當用戶從 SQL Server 實例斷開連接時被刪除。全局臨時表的名稱以兩個數字元號 (##) 打頭,創建後對任何用戶都是可見的,當所有引用該表的用戶從 SQL Server 斷開連接時被刪除。

⑧ sql臨時表表變數的使用方法與什麼時候用最好

臨時表、表變數的比較
1、臨時表
臨時表包括:以#開頭的局部臨時表,以##開頭的全局臨時表。
a、存儲
不管是局部臨時表,還是全局臨時表,都會放存放在tempdb資料庫中。
b、作用域
局部臨時表:對當前連接有效,只在創建它的存儲過度、批處理、動態語句中有效,類似於C語言中局部變數的作用域。
全局臨時表:在所有連接對它都結束引用時,會被刪除,對創建者來說,斷開連接就是結束引用;對非創建者,不再引用就是結束引用。
但最好在用完後,就通過drop table 語句刪除,及時釋放資源。
c、特性
與普通的表一樣,能定義約束,能創建索引,最關鍵的是有數據分布的統計信息,這樣有利於優化器做出正確的執行計劃,但同時它的開銷和普通的表一樣,一般適合數據量較大的情況。
有一個非常方便的select ... into 的用法,這也是一個特點。

2、表變數
a、存儲
表變數存放在tempdb資料庫中。
b、作用域
和普通的變數一樣,在定義表變數的存儲過程、批處理、動態語句、函數結束時,會自動清除。
c、特性
可以有主鍵,但不能直接創建索引,也沒有任何數據的統計信息。表變數適合數據量相對較小的情況。
必須要注意的是,表變數不受事務的約束,

⑨ SqlServer裡面視圖View得創建是不是不能用到臨時表和表變數

1 、
視圖是一個虛擬表,同表一樣,視圖包含一系列帶有名稱的列和行數據。

視圖在資料庫中並不是以數據值存儲集形式存在,除非是索引視圖。

行和列數據來自由定義視圖的查詢所引用的表,並且在引用視圖時動態生成。

定義視圖可以來自當前或其他資料庫的一個或多個表,或者其他視圖。

根據以上定義,所以不能使用臨時表和表變數。

2、
只要是select 中有function,都會增中計算量,查詢時間增長。