SQL SERVER 表變數和臨時表
一、表變數
1. 表變數定義
表變數,是SQL Server 2000以來引入的概念,表變數本質是一個變數,它具有正式表物件的很多屬性。如:它有表字段、欄位資料型別、欄位寬度、主鍵、唯一約束、NULL、NOT NULL約束、CHECK和DEFAULT約束。但是,表變數不支援約束命名,不支援索引,不支援外來鍵,不支援表變數定義後的任何表變數結構的修改,僅可做資料的DML操作。
2. 表變數的使用場景
需要在當前會話臨時快取少量的中間資料結果集,供當前會話多次使用這同一資料集或者同一資料結果集的一部分時,我們可以考慮使用表變數,表變數中的資料是快取在記憶體中(大部分情況下如此,也會儲存到物理磁碟中)。注意這裡是少量資料集,不是大量結果集,建議是最好不要超過1000條資料記錄。
3. 表變數使用範例
DECLARE @stuinfo TABLE (id INT IDENTITY(1,1) PRIMARY KEY,sname NVARCHAR(20),gender NVARCHAR(1),sgroup INT,salary DECIMAL) insert into @stuinfo select '張三','m',1,10000 union all select '李四','f',1,13000 union all select '王五','f',2,8500 union all select '趙六','m',3,12000 union all select '黃七','m',3,5000 SELECT * FROM @stuinfo SELECT id,sname,CASE gender WHEN 'm' THEN '男' WHEN 'f' THEN '女' END AS '性別' FROM @stuinfo SELECT sname ,CASE WHEN gender='m' AND sgroup = '1' THEN '第一組男生' WHEN gender='f' AND sgroup = '1' THEN '第一組女生' WHEN gender='m' AND sgroup = '2' THEN '第二組男生' WHEN gender='f' AND sgroup = '2' THEN '第二組女生' WHEN gender='m' AND sgroup = '3' THEN '第三組男生' WHEN gender='f' AND sgroup = '3' THEN '第三組女生' END FROM @stuinfo DECLARE @ordertype VARCHAR(1) = 'f' SELECT * FROM @stuinfo ORDER BY CASE WHEN @ordertype = 'm' THEN gender END DESC,CASE WHEN @ordertype = 'f' THEN gender END ASC; SELECT SUM(CASE gender WHEN 'm' THEN 1 ELSE 0 END) AS '男生', SUM(CASE gender WHEN 'f' THEN 1 ELSE 0 END) AS '女生' FROM @stuinfo UPDATE @stuinfo SET salary = CASE gender WHEN 'm' THEN salary*0.9 WHEN 'f' THEN salary*1.2 END WHERE 1=1 SELECT * FROM @stuinfo
二、臨時表
1. 臨時表定義
SQL Server的臨時表是一種特殊的表,表名字是以#或者##打頭。無論臨時表在哪個資料庫下建立,SQL Server均把臨時表結構資訊和資料儲存在Tempdb資料庫下。以#打頭的臨時表稱為區域性臨時表,這種型別的臨時表僅當前程序可見,其他程序不可訪問,生命週期會隨著當前連線程序的關閉而消亡。以##打頭的臨時表稱為全域性,此型別的臨時表對所有程序可見,當前程序和其他程序均可訪問,生命週期是所有使用到全域性臨時表的連線完全關閉後,臨時表消亡。
2.臨時表的作用
臨時表的作用和表變數類似,均是用於暫時快取資料。臨時表中的資料會被儲存在Tempdb的物理檔案磁碟上,當需要資料讀取時,SQL Server會將臨時表中資料從磁碟檔案讀入SQL Server Buffer Pool中,然後返回給客戶端。因此,臨時表對資料的儲存和讀取會有物理的IO Write和IO Read的。臨時表相較於表變數可以儲存稍微大量一些的資料,比如資料量超過10萬條記錄數,資料空間佔用量超過100MB。
3.臨時表的使用
IF OBJECT_ID('tempdb..#tb_table','U') IS NOT NULL DROP TABLE #tb_table GO CREATE TABLE #tb_table( RowID INT IDENTITY(1,1) NOT NULL PRIMARY KEY ,ProductName NVARCHAR(50) NOT NULL UNIQUE ,Length DECIMAL(4,2) NOT NULL CHECK(Length>0.0) ,Windth DECIMAL(4,2) NOT NULL ,Height DECIMAL(4,2) NOT NULL CHECK(Height>0.0) ,Dimension AS (Length * Windth * Height) ,Indate DATETIME NOT NULL CONSTRAINT DF_tbTable DEFAULT(GETDATE()) ,CONSTRAINT CK_Windth CHECK(Windth>0.0) ); CREATE INDEX IX_ProductName ON #tb_table(ProductName); GO INSERT INTO #tb_table(ProductName, Length, Windth, Height) VALUES('A', 0.1, 0.2, 0.3); INSERT INTO #tb_table(ProductName, Length, Windth, Height) VALUES('B', 0.4, 0.5, 0.6); INSERT INTO #tb_table(ProductName, Length, Windth, Height) VALUES('C', 0.7, 0.8, 0.9); IF OBJECT_ID('tempdb..##tb_table','U') IS NOT NULL DROP TABLE ##tb_table GO SELECT * INTO ##tb_table FROM #tb_table; UPDATE A SET Length = 2.5 FROM #tb_table AS A WHERE RowID = 1; DELETE TOP(1) AF ROM #tb_table AS AWHERE RowID = 2; SELECT * FROM #tb_table; SELECT * FROM ##tb_table