主頁 > 資料庫 > T-SQL編程

T-SQL編程

2020-09-11 03:07:29 資料庫

    T-SQL(Transact-SQL)是一種 SQL 擴展語言,由微軟實作,運行在 Ms SQL Server 平臺上,T-SQL 主要用來和SQL Server 交流,而查詢陳述句則主要用來告訴服務器該做什么,T-SQL 是標準 SQL 語言的擴展,自然也繼承了其基本功能:DDL、DML,DCL,DQL,另外,T-SQL 擴展了標準 SQL 不具備的編程特性,比如:運算子、文本字串處理、流程控制、存盤程序、API,自定義函式等,

 

  一  T-SQL是什么

    T-SQL 并沒有被作為一種編程語言設計,雖然 T-SQL 經過多年的發展,已經加入了不少編程語言的特性,但其仍然缺少真正的編程語言所具備的能力和靈活性,

    T-SQL 被設計的目的是實作資料的檢索和操縱,雖然其具有一定的編程能力,但其性能不能被很好的得到保證,當你希望把 T-SQL 當做編程語言使用時,你會不可避免的遇到性能問題,所以,在使用它時,請在心里牢記,T-SQL 是操縱資料集的,這才是它發揮真正作用的地方,

 

  二  編程特性

 

    1,語法約束

    T-SQL 命令不區分大小寫,但建議使用大寫,陳述句不強制使用 ; 結束,

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 CASE2     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 ,

 

    7,自定義排序

     默認的排序方式在實際生產中難免有失靈活,

    比如在查詢汽車品牌表時,如果通過常規 order by 通過品牌名稱排序無非得到:1:Astom-Martin,2:Bugatti,3:Ferrari,4:Lamborghini,5:McLaren,或 1:McLaren,2:Lamborghini,3:Ferrari,4:Bugatti,5:Astom-Martin 這樣的結果,如果現在的要求是:1:Lamborghini,2:McLaren,3:Ferrari,4:Bugatti,5:Astom-Martin 這樣的順序呢?

    在 SQL Server 中我們通過 case 陳述句來實作自定義排序,

 1 select * from car
 2 order by case car_brand
 3                 when 'Lamborghini' then 1
 4                 when 'McLaren' then 2
 5                 when 'Ferrai' then 3
 6                 when 'Bugatti' then 4
 7                 when 'Astom-Martin' 5
 8                 else 6
 9                 end
10 -- 如果還有沒指定的值,將按默認順序排在這5個品牌之后

 

 

  四  編程物件

 

    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 RETURNS INT
 4 AS
 5 BEGIN
 6     RETURN DATEDIFF(DAY,@Birthday,@Today)/365
 7 END
 8 GO
 9 --根據提供的生日和現在的日期,計算年齡
10 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,

    在 SELECT 查詢陳述句之后,還可以通過 FOR 關鍵字指定哪些列可更新或者只讀,語法規則:[ FOR { READ ONLY | UPDATE [ OF column_name [ ,...n ] ] } ]

    游標的主要作用在于,允許程式對由查詢陳述句 SELECT 回傳的行集合中的每一行執行相同或不同的操作,而不是對整個行集合執行同一個操作,并且它還提供對基于游標位置而對表中資料進行洗掉或更新的能力,

    使用游標雖然可以帶來一定程度的靈活性,但它是以犧牲性能和效率為代價的,所以游標一般作為最后的開發選項,畢竟,即使不對資料做任何特殊操作,也需要必要的五個步驟,

    

    2,觸發器

    觸發器實際上是一類特殊的存盤程序,它能被 DDL 和 DML 觸發,并自動運行,不能被用戶顯式的觸發,

    如果我們為表或視圖的某些操作設定觸發器后,那么,當我們在資料庫中針對這些表或視圖執行這些操作時,觸發器內的程式代碼將被執行,

    基本語法(DML觸發器):

1 CREATE TRIGGER 觸發器名稱
2 ON 表或視圖
3 觸發器型別(FOR|AFTER|INSTEAD OF4 操作型別(INSERTUPDATEDELETE5 AS
6     陳述句塊

    基本語法(DDL觸發器):

1 CREATE TRIGGER 觸發器名稱
2 ONALL SERVER|DATEBASE)
3 觸發器型別(FOR|AFTER)
4 操作型別(CREATEALTERDROP...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表相同的資料

 

  

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/4141.html

標籤:SQL Server

上一篇:sqlserver分組排序取前三條資料

下一篇:SQL Pretty Printer 一款值得你擁有的MSSQL格式化插件

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more