T-SQL(Transact-SQL)是一種 SQL 擴展語言,由微軟實現,運行在 Ms SQL Server 平臺上。T-SQL 主要用來和SQL Server 交流,而查詢語句則主要用來告訴服務器該作什麼。T-SQL 是標準 SQL 語言的擴展,天然也繼承了其基本功能:DDL、DML,DCL,DQL。另外,T-SQL 擴展了標準 SQL 不具有的編程特性,好比:運算符、文本字符串處理、流程控制、存儲過程、API,自定義函數等。html
一 T-SQL是什麼sql
T-SQL 並無被做爲一種編程語言設計。雖然 T-SQL 通過多年的發展,已經加入了很多編程語言的特性,但其仍然缺乏真正的編程語言所具有的能力和靈活性。數據庫
T-SQL 被設計的目的是實現數據的檢索和操縱,雖然其具備必定的編程能力,但其性能不能被很好的獲得保證,當你但願把 T-SQL 當作編程語言使用時,你會不可避免的遇到性能問題,因此,在使用它時,請在內心牢記,T-SQL 是操縱數據集的,這纔是它發揮真正做用的地方。編程
二 編程特性服務器
1,語法約束編程語言
T-SQL 命令不區分大小寫,但建議使用大寫。語句不強制使用 ; 結束。ide
1 SELECT * FROM TableName --能夠運行 2 SELECT * FROM TableName;--也能運行
注意縮進和對象命名規範。正確的縮進能保證你的代碼易於閱讀和維護。T-SQL 容許使用字母、數字、下劃線、@、#、$符號來建立你本身的標識符(如變量、表名、視圖名等),但首字母不能是數字和 $ 符號,建議遵循大駝峯命名法則。函數
1 CREATE TABLE MyTable 2 ( 3 M_Name VARCAHR(20) NOT NULL, 4 ...... 5 )
T-SQL 同時支持雙引號和單引號,那麼如何區分呢?雙引號通常用來標識 T-SQL 對象,好比表、視圖,過程等,還有一種表示對象的方式是 [] ,而單引號用來表示字符串數據。性能
1 SELECT "M".* FROM "MyTable" AS "M" 2 WHERE "M".Name='張三'; 3 SELECT "M".* FROM [MyTable];
T-SQL 使用 -- 雙中橫線表示單行註釋,/* */ 表示多行註釋。測試
1 /* 2 這是多行註釋 3 這是多行註釋 4 */ 5 --這是單行註釋
2,運算符
數學運算符:+ 加、- 減、* 乘、/ 除、% 餘。數學運算符返回值時數學計算值。= 既能夠是等號也能夠是賦值。+ 既能夠做爲數學加號也能夠做爲鏈接運算符。
比較運算符:> 大於、< 小於、>= 大於或等於、<= 小於或等於、<> 不等於、!= 不等於、!< 不小於、!> 不大於,比較運算返回的是布爾值。
邏輯運算符:AND、OR、NOT、BETWEEN、LIKE、IN。
3,變量
變量分爲局部變量和全局變量。局部變量用戶能夠自定義,而全局變量由系統管理,用戶可使用,但不能更改。
局部變量使用 DECLARE 關鍵字聲明,以 @ 符號標識。使用 SELECT 或 SET 關鍵之賦值。
1 DECLARE @Age INT 2 DECLARE @Name VARCAHR(20) 3 SET @Age=20 4 SELECT @Name='張三' 5 PRINT @Name+@Age
SET 一次只能爲一個變量賦值,SELECT 一次能夠爲多個變量賦值。在 T-SQL 中,有兩種方式輸出內容,PRINT 和 SELECT。PRINT 一次只能輸出一個值,一般用於向 API 返回值,而 SELECT 能夠以數據集的形式返回多行記錄。
全局變量以 @@ 符號標識,經常使用的全局變量以下:
1 SELECT @@version AS '版本';--返回當前數據庫的版本信息 2 SELECT @@error AS '錯誤ID';--返回上一次T-SQL的錯誤ID,若是正常執行了查詢,error爲0,出錯時error必定大於0 3 SELECT @@identity AS '標示符';--返回最後一次的標識符,如先執行了 4 SELECT @@connections AS '鏈接次數';--返回自上次SQL啓動以來鏈接或試圖鏈接的次數 5 SELECT @@total_errors AS '錯誤總數';--返回至啓動以來的錯誤總數 6 SELECT @@total_read AS '讀取總數';--返回自啓動以來的讀取總數 7 SELECT @@total_write AS '寫入總數';--返回自啓動以來的寫入總數 8 ......
4,流程控制
BEGIN...END:該語句用來標記一個語句塊,一般和其餘流程控制語句一塊兒使用。
IF...ELSE:條件判斷語句。若是 IF 關鍵字後面的條件表達式計算結果爲真,則執行語句塊1,否者執行語句塊2。IF 和 ELSE 之間還能夠存在 ELSE IF 組合關鍵字,表示邏輯上的其餘狀況。
1 IF 條件 2 BEGIN 3 語句塊1 4 END 5 ELSE 6 BEGIN 7 語句塊2 8 END
若是語句塊只有一條語句,那麼BEGIN...END 能夠省略。
WHILE:循環。當 WHILE 關鍵字後面的循壞條件爲真時,執行下面的語句塊,須要注意的是,語句塊中應該有可以左右循壞條件的語句存在,不然這將變成一個死循環。
1 WHILE 循環條件 2 BEGIN 3 語句塊 4 END 5 --若是隻有一條語句,也能夠省略BEGIN...END
BREAK 和 CONTINUE:退出循環。該關鍵字通常和循環配合使用,BREAK 用於結束整個循環,無論循環條件是否爲真。CONTINUE 用於跳過本次循環須要執行的代碼快,直接開始執行下一次須要執行的代碼塊(前提是循環條件還爲真)。
WAITFOR:延時執行。
1 BEGIN 2 WAITFOR TIME '22:00' 3 語句塊 4 END 5 --指定執行語句的具體時間 6 BEGIN 7 WAITFOR DELAY '01:00:00' 8 語句塊 9 END 10 --指定執行語句的延遲時間量
CASE:基於列的計算返回指定的值。CASE 執行的邏輯和 IF ELSE 語句相似,當 WHEN 關鍵字後面的表達式結果爲真時,用 THEN 後面的新值替換列中原來的值。
1 CASE 列 2 WHEN 表達式 THEN 新的值或表達式
3 WHEN 表達式 THEN 新的值或表達式 4 ...... 5 ELSE 其餘未指定匹配值或表達式的新值 6 END
三 函數
1,聚合函數
聚合函數主要包括:SUM() 求和,AVG() 求平均值,MIN() 求最小值,MAX() 求最大值,COUNT() 計數。
以上聚合函數和標準 SQL 中的聚合函數功能同樣,使用方式也同樣,這裏再也不介紹,若有疑問能夠參照個人《SQL入門》。
2,日期函數
T-SQL 提供了功能強大的操做日期類型值的相關函數,經過這些函數你能夠輕鬆實現好比,解析日期類型值的日期與時間部分,比較與操縱日期/時間值等。
A:GETDATE() 和 GETUTCDATE()
1 SELECT GETDATE() AS '標準時間' 2 SELECT GETUTCDATE() AS 'UTC時間'
GETUTCDATE() 經過本地服務器上的時區來求出 UTC 時間,通常使用前一個函數較多。
B:DATEPART() 和 DATENAME()
這兩個函數的做用相似,都是用於返回日期中指定的部分,不通點在於:DATEPART() 返回值類型爲 INT,而DATENAME() 爲 NVARCHAR。
1 DECLARE @MyDate; 2 SET @MyDate=GETDATE(); 3 PRINT DATEPART(year,@mydate);--int 4 PRINT DATENAME(year,@mydate);--nvarcahr 5 PRINT DATEPART(month,@mydate);--int 6 PRINT DATENAME(month,@mydate);--nvarcahr 7 PRINT DATEPART(day,@mydate);--int 8 PRINT DATENAME(day,@mydate);--nvarcahr 9 PRINT DATEPART(dayofyear,@mydate);--int 10 PRINT DATENAME(dayofyear,@mydate);--nvarcahr 11 --可選的參數還有 week,weekday,hour,minute,second,millisecond等,請自行測試返回值
C:YEAR(),MONTH(),DAY()
以 INT 類型值返回指定日期的年,月,日。
1 SELECT YEAR(MyDate)AS YEAR,MONTH(MyDate)AS MONTH,DAY(MyDate)AS DAY
D:DATEADD() 和 DATEDIFF()
DATEADD() 用於計算給定時間間隔後的日期,DATEDIFF() 用於計算兩個日期之間指定單位的時間差。
1 DECLARE @MyDate DATETIME; 2 DECLARE @DateAfter7Days DATETIME; 3 SET @MyDate=GETDATE(); 4 SET @DateAfter7Days=DATEADD(day,7,@MyDate) ;--計算距今7天以後的日期 5 PRINT @DateAfter7Days; 6 PRINT DATEDIFF(day,@MyDate,@DateAfter7Days) ;--7,差7天 7 --第一個參數都是時間單位,可選的有:year,month,day,week,hour,minute,second等,DATEADD()的第二個參數是一個數字,能夠爲負,覺得以前的日期
3,數學函數
T-SQL 數學函數專門用於數學計算,經常使用的數學函數列表請移步《T-SQL 數學函數》,這裏不舉例說明。
4,字符函數
1 SELECT ASCII('ABC');--計算字符串第一個字符的ASCII值 2 SELECT CHAR(65);--把給定ASCII編碼轉換成字符 3 4 SELECT LOWER('AbC');--全轉換爲小寫 5 SELECT UPPER('aBc');--全轉換爲大寫 6 7 SELECT LTRIM(' AAA');--去掉左邊的空格 8 SELECT RTRIM('AAA ');--去掉右邊的空格 9 10 SELECT LEN(' ABC ');--計算字符個數,不包含後面的空格 11 SELECT LEFT('ABCDEFG',3);--從左邊返回指定個數的字符 12 SELECT RIGHT('ABCDEFG',3);--從右邊返回指定個數的字符 13 SELECT SUBSTRING('ABCDEFG',3,2);--從第三個字符開始返回2個字符 14 15 SELECT CHARINDEX('A', 'CCBBAA'); --返回第一個參數字符串在指定字符串中的位置 16 SELECT REPLACE('AABBCC','A','D'); --用第三個參數替換第一個參數中的第二個參數所指定字符串
5,類型轉換函數
T-SQL 中的顯示類型轉換經過 CONVERT() 和 CAST() 實現。
1 SELECT CONVERT(INT,' 123 '); 2 SELECT CAST(' 123 ' AS INT); 3 --把字符串轉換成數字,能夠有空格,但不能有其餘字符 4 5 SELECT CONVERT(DATE,'2020-01-01'); 6 SELECT CAST('2020-01-01' AS DATE); 7 --把字符串表示的日期轉換爲日期格式
CONVERT() 另外一個很重要的應用是:以不一樣的格式顯示日期。這是你須要傳入第三個參數,該參數用來指定格式日期:
1 SELECT CONVERT(VARCHAR(19),GETDATE());--04 27 2020 11:10AM 2 SELECT CONVERT(VARCHAR(10),GETDATE(),110); --04-27-2020 3 SELECT CONVERT(VARCHAR(11),GETDATE(),106);--27 04 2020 4 SELECT CONVERT(VARCHAR(24),GETDATE(),113);--27 04 2020 11:11:07:857
6,排序
ROW_NUMBER() OVER():經過在 OVER 中使用 ORDER BY 字句,對指定列排序,並生成一個標識該行的惟一序號(從1開始)。好比有如學生生源信息表 Person:
id | name | prov |
1001 | 張一 | 四川 |
1002 | 張二 | 湖北 |
1003 | 張三 | 上海 |
1004 | 張四 | 北京 |
1005 | 張五 | 四川 |
1 SELECT ROW_NUMBER() OVER(ORDER BY ID) AS NUM,* FROM Person; --多了一列 NUM,值從1 - 4
1 SELECT ROW_NUMBER() OVER(PARTITION BY PROV ORDER BY ID) AS NUM,* FROM Person; 2 -- 先經過 prov 分組學生信息,而後再經過 id 對學生在組內排序,生成 num 列,張一的 num 爲1,張五的 num 爲 2,其餘的均爲1
RANK() OVER():排序和 ROW_NUMBER() OVER() 類似,區別是它不能分組排序,而且它的排序結果可能會出現相同的序號,且總體可能會不連續。
若是某些行的的值相同,那麼 RANK() OVER() 會爲這些行給出相同的序號,而且,下一行的排序並不會和上一個相鄰。
好比:前兩個學生的成績都是 100 分,那麼他們應該是並列第一名,排序都是 1,第三名學生的成績是 99,應該是第二名,但 RANK() OVER() 的排序會是 3 。
四 編程對象
1,視圖
設計視圖的惟一目的就是簡化代碼,解決代碼重用問題。
視圖是一個邏輯表,它和真正的表在使用上徹底一致,但他不是一個真正的表,視圖的本質是一個複雜的查詢語句。查詢視圖會返回數據,但這些數據並非存儲在視圖中。而是在具體的真實的表中。
語法:
1 CREATE VIEW VIEW_NAME 2 AS 3 語句 4 --建立視圖 5 ALTER VIEW VIEW_NAME 6 AS 7 語句 8 --修改視圖 9 DROP VIEW VIEW_NAME 10 --刪除視圖
建立視圖時能夠在視圖名後使用()來爲視圖的列指定新的名稱,但必須所有提供,不能只指定一部分列的新名稱。
雖然視圖也能夠用來對原始數據進行操做,但不建議這樣作,由於使用視圖簡化查詢纔是它的本職工做。
使用視圖的一個注意點:不能直接使用 order by,若是須要排序,則必須配合 TOP 關鍵字一塊兒使用。
2,存儲過程
存儲過程不只能夠實現返回查詢數據集的功能,並且功能比視圖更進一步,它還提供了不少編程功能,好比:帶參數的視圖,返回標量值,維護記錄,處理業務邏輯等等。
一個存儲過程實現了一個特定的功能,而且別SQL Server 編譯好後存儲在數據庫中,下一次執行不須要從新編譯,提升程序執行效率。
先來看基本語法:
1 CREATE PROCEDURE PROC_NAME 2 AS 3 語句 4 --建立存儲過程 5 ALTER PROCEDURE PROC_NAME 6 AS 7 語句 8 --修改存儲過程 9 DROP PROCDURE PROC_NAME 10 --刪除存儲過程 11 EXECUTE PROC_NAME 12 --執行存儲過程
A:帶參數的存儲過程
1 CREATE PROCEDURE Proc_name 2 @Var_name 3 AS 4 SELECT * FROM Table_name 5 WHERE Some_col = @Var_name 6 --在存儲過程當中,使用變量過濾數據,變量不須要使用 declare 關鍵字 7 EXECUTE Proc_name Something; 8 EXECUTE Proc_name @Var_name=Something; 9 --兩種傳參的方式,多個參數使用逗號隔開
B:返回值
從存儲過程返回值有兩種方式,OUTPUT 修飾符和 RETURN 關鍵字。
先來看 OUTPUT 方式:
1 CREATE PROCEDURE P_TEST 2 @OUT INT OUTPUT 3 AS 4 SET @OUT=1; 5 GO 6 DECLARE @NUM INT; 7 EXECUTE P_TEST @NUM OUTPUT; 8 SELECT @NUM; 9 GO 10 --GO 表示一批 T-SQL 語句結束,GO 以後的 T-SQL 語句屬於另外一個批處理的範圍,GO 不是 T-SQL 命令,它只是一個能被 SQL Server 管理器識別的命令
使用這種方式,在建立存儲過程時,須要定義一個帶有 OUTPUT 修飾符的參數,用於存儲即將被返回的值。在存儲過程的外部,也須要定義一個變量,用來接收返回的值。而且在執行存儲過程時,須要把接收值的變量傳遞到存儲過程當中去,且必須指明修飾符 OUTPUT,不然,存儲過程雖然能正常執行,但不會返回任何數據。
另外一種 RETURN 方式:
1 ALTER PROCEDURE P_TEST 2 AS 3 RETURN 1; 4 GO 5 DECLARE @NUM INT; 6 EXECUTE @NUM = P_TEST; 7 SELECT @NUM; 8 GO
這種方式使用 RETURN 關鍵字顯示的指定須要返回的值,但與 OUTPUT 不一樣的是,它只能返回 INT類型的值。這種方式使用起來更簡單,不準要定義額外的變量,只須要在外部定義一個接收數據的變量,並在執行時賦值,便可拿到存儲過程的返回值。
RETURN 還有一個功能:結束存儲過程的執行。即執行完 RETURN 語句以後,後面的任何語句都不會再被執行了,存儲過程的執行到此結束。
3,自定義函數
和存儲過程很類似,用戶自定義函數也是一組有序的T-SQL語句,用戶自定義函數被預先優化和編譯而且做爲一個單元進行調用。它和存儲過程的主要區別在於返回結果的方式。
用戶自定義函數能夠傳入參數,但傳出參數被返回值概念替代了。用戶自定義函數的返回值能夠是普通的標量值,也能夠是表。
1 CREATE FUNCTION FUN_NAME 2 ( 參數列表 ) 3 RETURNS 數據類型 4 AS 5 BEGIN 6 語句塊 7 END
使用 CREATE FUNCTION 建立用戶自定義函數,函數名後面用()定義傳入的參數,而後使用 RETURNS 定義函數返回值的數據類型,用戶自定義函數的語句塊必須包含在 BEGIN...END中,而且在自定義函數內部,不能調用非肯定性的函數,好比 GETDATE()。這是由於若是在內部出現非肯定性函數,可能致使自定義函數在參數相同的狀況下而返回值不一樣。請看下面的例子:
1 CREATE FUNCTION GetAge 2 (@Birthday DATE,@Today DATE) 3 AS 4 BEGIN 5 RETURN DATEDIFF(DAY,@Birthday,@Today)/365 6 END 7 --根據提供的生日和如今的日期,計算年齡 8 SELECT DBO.GetAge('2000-01-01',GETDATE());
一般狀況下,SQL SERVER 把沒指定全部者或模式的函數調用當作一個系統內置函數,因此在使用用戶自定義函數時,請至少要指定全部者或模式名。
若是要使用用戶自定義函數返回表類型的值,你須要這樣作:
1 CREATE FUNCTION MYFUN(@VAR 數據類型) 2 RETURNS TABLE 3 AS 4 BEGIN 5 RETURN 6 ( 7 SELECT * FROM TABLENAME WHERE 使用@VAR 的條件表達式; 8 ) 9 END 10 11 SELECT * FROM MYFUN(參數值);
使用 SELECT * FROM 函數名這樣的語法,那麼這個函數基本和表具備同樣的功能。
五 其餘
1,遊標
遊標本質上是一個包含多條記錄的結果集,保存在內存中。在 T-SQL 中,聲明一個遊標類型的變量,你就能夠對讀入的結果集進行管理,對每條記錄進行迭代了。因此,遊標其實是一種能從包括多條數據記錄的結果集中,每次提取一條記錄的機制。
遊標基本用法:
1 --1:建立遊標 2 DECLARE Cur_Name CURSOR 3 FOR 4 SELECT Col1,Col2 FROM Tbale_name 5 DECLARE @Var_Name1,@Var_Name2 6 --2:打開遊標 7 OPEN Cur_Name 8 --3:檢索與操做數據 9 FETCH NEXT FROM Cur_Name INTO @Var _Name1,@Var_Name2 10 WHILE @@Fetch_Status=0 11 BEGIN 12 PRINT @Var _Name1+':'+@Var_Name2 13 FETCH NEXT FROM Cur_Name INTO @Var _Name1,@Var_Name2 14 END 15 --4:關閉遊標 16 CLOSE Cur_Name 17 --5:釋放遊標 18 DEALLOCATE Cur_Name
使用遊標必要的五步:建立,打開,檢索,關閉,釋放。缺一不可。
建立遊標時,遊標名和關鍵字 CURSOR 之間能夠有可參數列表:INSENSITIVE,SCROLL,前者表示生成一個結果集的副本,而不是使用數據庫的元數據。後者指定在數據檢索時,全部的提取選項(FIRST(第一條記錄)、LAST(最後一條記錄)、PRIOR(上一條記錄)、NEXT(下一條記錄)、RELATIVE(相對當前移動 n 行的記錄)、ABSOLUTE(第 n 記錄))都可用。通常到了使用遊標的時候,都是須要對每一條數據進行不一樣的操做了,因此提取選項多數狀況都是使用 NEXT。
在查詢語句以後,還能夠經過 FOR 關鍵字指定哪些列可更新或者只讀,語法規則:[ FOR { READ ONLY | UPDATE [ OF column_name [ ,...n ] ] } ]
遊標的主要做用在於,容許程序對由查詢語句 SELECT 返回的行集合中的每一行執行相同或不一樣的操做,而不是對整個行集合執行同一個操做,而且它還提供對基於遊標位置而對錶中數據進行刪除或更新的能力。
使用遊標雖然能夠帶來必定程度的靈活性,但它是以犧牲性能和效率爲代價的,因此遊標通常做爲最後的開發選項,畢竟,即便不對數據作任何特殊操做,也須要必要的五個步驟。
2,觸發器
觸發器其實是一類特殊的存儲過程,它能被 DDL 和 DML 觸發,並自動運行,不能被用戶顯式的觸發。
若是咱們爲表或視圖的某些操做設置觸發器後,那麼,當咱們在數據庫中針對這些表或視圖執行這些操做時,觸發器內的程序代碼將被執行。
基本語法(DML觸發器):
1 CREATE TRIGGER 觸發器名稱 2 ON 表或視圖 3 觸發器類型(FOR|AFTER|INSTEAD OF) 4 操做類型(INSERT,UPDATE,DELETE) 5 AS 6 語句塊
基本語法(DDL觸發器):
1 CREATE TRIGGER 觸發器名稱 2 ON (ALL SERVER|DATEBASE) 3 觸發器類型(FOR|AFTER) 4 操做類型(CREATE,ALTER,DROP...) 5 AS 6 語句塊
觸發器類型 FOR 和 AFTER 都是指在操做成功後執行,區別是 AFTER 類型只支持表,而不支持視圖。
INSTEAD OF 觸發器使用觸發器內部的操做替代指定的操做類型,真正起做用的是觸發器裏面的動做!
3,其餘的
A:MERGE
MERGE 命令的做用是根據與源表的聯接結果在目標表上運行插入,更新或刪除操做。好比,經過對比另外一個表的差別,在一個表中插入、更新或刪除數據,以保證兩個表中的數據同步。
一個簡單的示例:
1 MERGE INTO Target 2 --這裏是目標表,它將要被源表Merge 3 USING Source 4 --這裏是源表 5 ON 匹配條件 6 WHEN MATCHED 7 --匹配條件爲真的記錄,執行下面的then 8 THEN UPDATE --執行更新操做 9 WHEN NOT MATCHED BY TARGET 10 --目標表中不存在,而源表中存在數據,執行下面的then 11 THEN INSERT--執行插入操做 12 WHEN NOT MATCHED BY SOURCE 13 --當目標表中存在,而源表中不存在數據執,執行下面then 14 THEN DELETE--執行刪除操做
MERGE 命令在許多時候均可以替代遊標批量操做數據,下一次你在考慮使用遊標時,不妨先想想,可否用 MERGE 代替呢!
B:臨時表和表變量
臨時表與永久表類似,只是它的建立是在 Tempdb 中,它只有在一個數據庫鏈接結束後或者由SQL命令DROP掉,纔會消失,不然就會一直存在。
臨時表分爲本地和全局兩種,本地臨時表的名稱都是以「#」爲前綴,只有在本地當前的用戶鏈接中才是可見的,當用戶從實例斷開鏈接時被刪除。全局臨時表的名稱都是以「##」爲前綴,建立後對任何用戶都是可見的,當全部引用該表的用戶斷開鏈接時被刪除。
1 --建立臨時表 2 --方式一 3 CREATE TABLE #表名() 4 CREATE TABLE ##表名() 5 --方式二 6 SELECT INTO #表名 FROM TABLE 7 SELECT INTO ##表名 FROM TABLE 8 --查詢和刪除 9 SELECT * FROM #表名 10 DROP * FROM #表名
臨時表還能夠和普通表同樣添加索引,主鍵、外鍵和約束。
表變量本質上仍是變量,因此依然使用 DECLARE 關鍵字聲明,既然是變量,那麼也分爲本地及全局的兩種,本地表變量的名稱都是以「@」爲前綴,只有在本地當前的用戶鏈接中才能夠訪問。全局表變量的名稱都是以「@@」爲前綴,和其餘的系統全局變量同樣。
1 DECLARE @News TABLE()
對於表變量,能夠正常執行 DML。表變量通常存儲在內存中,而且不能添加索引和約束。
不少時候表變量和臨時表的功能是重合的,如何選取徹底取決於應用對內存的壓力,若是數據量比較大,可使用臨時表,不然推薦使用表變量。
C:CTE
共用表表達式 CTE ,你能夠把它理解爲一個臨時的查詢結果集,你能夠在接下來的 SELECT、INSERT、UPDATE等語句中重複引用它。微軟對其的用處評價頗高,說來慚愧,我在實際工做中,主要是爲了在複雜子查詢中減小代碼冗餘和便於維護而使用它。
1 WITH CTEName (col1,col2) 2 AS 3 ( 4 SELECT col1,col2 FROM TableName 5 )
注意,定義的 CTE 只能在緊接着的語句中使用。
D:EXISTS()
EXISTS 用於檢測是否有符合條件的數據存在,它是一種探測機制,它執行時不關注有多少符合條件的記錄,只關注是否存在這樣的記錄。因此,多數時候可使用 EXISTS 子查詢替換 IN 以提升性能。與之相對是 NOT EXISTS(),用於判斷是否不存在。
1 SELECT * FROM TableA A 2 WHERE EXISTS 3 (SELECT * FROM TableB B WHERE A.ID = B.ID ) 4 --查詢A表中那些ID和B表相同的數據