日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

T-SQL 之 表变量和临时表

發(fā)布時間:2025/4/16 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 T-SQL 之 表变量和临时表 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、表變量

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

  表變量的特征:

  • 表變量擁有特定作用域(在當(dāng)前批處理語句中,但不在任何當(dāng)前批處理語句調(diào)用的存儲過程和函數(shù)中),表變量在批處理結(jié)束后自動被清除。
  • 表變量較臨時表產(chǎn)生更少的存儲過程重編譯。
  • 針對表變量的事務(wù)僅僅在更新數(shù)據(jù)時生效,所以鎖和日志產(chǎn)生的數(shù)量會更少。
  • 由于表變量的作用域如此之小,而且不屬于數(shù)據(jù)庫的持久部分,所以事務(wù)回滾不會影響表變量。
  •   表變量可以在其作用域內(nèi)像正常的表一樣使用。更確切的說,表變量可以被當(dāng)成正常的表或者表表達式一樣在SELECT,DELETE,UPDATE,INSERT語句中使用,但是表變量不能在類似"SELECT select_list INTO table_variable"這樣的語句中使用。而在SQL Server2000中,表變量也不能用于INSERT INTO table_variable EXEC stored_procedure這樣的語句中。

      表變量不能做如下事情:

  • 雖然表變量是一個變量,但是其不能賦值給另一個變量。
  • check約束,默認(rèn)值和計算列不能引用自定義函數(shù)。
  • 不能為約束命名。
  • 不能Truncate表變量。
  • 不能向標(biāo)識列中插入顯式值(也就是說表變量不支持SET IDENTITY_INSERT ON)
  •   定義一個表變量,插入一條數(shù)據(jù),然后查詢:

    DECLARE @tb1 Table(Id int,Name varchar(20),Age int)INSERT INTO @tb1 VALUES(1,'劉備',22)SELECT * FROM @tb1

      輸出結(jié)果如下:

      

    二、臨時表

      會話(Session),一個會話僅僅是一個客戶端到數(shù)據(jù)引擎的連接。在SQL Server Management Studio中,每一個查詢窗口都會和數(shù)據(jù)庫引擎建立連接。一個應(yīng)用程序可以和數(shù)據(jù)庫建立一個或多個連接,除此之外,應(yīng)用程序還可能建立連接后一直不釋放直到應(yīng)用程序結(jié)束,也可能使用完釋放連接需要時建立連接。

      臨時表是建立在系統(tǒng)臨時文件夾中的表,如果使用得當(dāng),完全可以像普通表一樣進行各種操作。

    ????? 臨時表分為兩類:本地臨時表 和 全局臨時表:

      [1] 本地臨時表僅在當(dāng)前會話中可見,本地臨時表的名稱前面有一個編號符 (#);

      [2] 全局臨時表在所有會話中都可見,全局臨時表的名稱前面有兩個編號符 (##)。

    ????? 如果本地臨時表由存儲過程創(chuàng)建或由多個用戶同時執(zhí)行的應(yīng)用程序創(chuàng)建,則 SQL Server 必須能夠區(qū)分由不同用戶創(chuàng)建的表。為此,SQL Server 在內(nèi)部為每個本地臨時表的表名追加一個數(shù)字后綴。存儲在 tempdb 數(shù)據(jù)庫的 sysobjects 表中的臨時表,其全名由 Create Table 語句中指定的表名和系統(tǒng)生成的數(shù)字后綴組成。為了允許追加后綴,為本地臨時表指定的表名 table_name 不能超過 116 個字符。

    ????? 除非使用 Drop Table語句顯式除去臨時表,否則臨時表將在退出其作用域時由系統(tǒng)自動刪除。

    ????? 當(dāng)存儲過程完成時,將自動除去在存儲過程中創(chuàng)建的本地臨時表。由創(chuàng)建表的存儲過程執(zhí)行的所有嵌套存儲過程都可以引用此表。但調(diào)用創(chuàng)建此表的存儲過程的進程無法引用此表。

    ????? 所有其它本地臨時表在當(dāng)前會話結(jié)束時自動刪除。

    ????? 全局臨時表在創(chuàng)建此表的會話結(jié)束且其它任務(wù)停止對其引用時自動除去。任務(wù)與表之間的關(guān)聯(lián)只在單個 Transact-SQL 語句的生存周期內(nèi)保持。換言之,當(dāng)創(chuàng)建全局臨時表的會話結(jié)束時,最后一條引用此表的 Transact-SQL 語句完成后,將自動除去此表。?
    ????? 在存儲過程或觸發(fā)器中創(chuàng)建的本地臨時表與在調(diào)用存儲過程或觸發(fā)器之前創(chuàng)建的同名臨時表不同。如果查詢引用臨時表,而同時有兩個同名的臨時表,則不定義針對哪個表解析該查詢。嵌套存儲過程同樣可以創(chuàng)建與調(diào)用它的存儲過程所創(chuàng)建的臨時表同名的臨時表。嵌套存儲過程中對表名的所有引用都被解釋為是針對該嵌套過程所創(chuàng)建的表。

    ????? 當(dāng)創(chuàng)建本地或全局臨時表時,Create Table 語法支持除 Foreign Key 約束以外的其它所有約束定義。如果在臨時表中指定 Foreign Key 約束,該語句將返回警告信息,指出此約束已被忽略,表仍會創(chuàng)建,但不具有 Foreign Key約束。在Foreign Key約束中不能引用臨時表。

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

      1、創(chuàng)建臨時表

    --方法一:直接創(chuàng)建create table #臨時表名( 字段1 約束條件,字段2 約束條件,.....)create table ##臨時表名( 字段1 約束條件,字段2 約束條件,.....)--方法二:插入特定數(shù)據(jù)創(chuàng)建select * into #臨時表名 from 表名;select * into ##臨時表名 from 表名;

      2、臨時表中插入數(shù)據(jù)

    Create Table #臨時表名 (Number int Primary Key) Insert Into #臨時表名 Values (1)

      3、查詢臨時表
    ????? select * from #臨時表名;
    ??????select * from ##臨時表名;

      4、刪除臨時表
    ????? drop table #臨時表名;
    ??????drop table ##臨時表名;

      5、清空臨時表的所有數(shù)據(jù)和約束

    ????? truncate table #臨時表名;
    ????? truncate table ##臨時表名;

    ?

      臨時表和Create Table語句創(chuàng)建的表有著相同的物理工程,但臨時表與正常的表不同之處有:

      1、臨時表的名稱不能超過116個字符,這是由于數(shù)據(jù)庫引擎為了辨別不同會話建立不同的臨時表,所以會自動在臨時表的名字后附加一串。

      2、局部臨時表(以"#"開頭命名的)作用域僅僅在當(dāng)前的連接內(nèi),從在存儲過程中建立局部臨時表的角度來看,局部臨時表會在下列情況下被Drop:
      [1] 顯示調(diào)用Drop Table語句
      [2] 當(dāng)局部臨時表在存儲過程內(nèi)被創(chuàng)建時,存儲過程結(jié)束也就意味著局部臨時表被Drop。
      [3] 當(dāng)前會話結(jié)束,在會話內(nèi)創(chuàng)建的所有局部臨時表都會被Drop。

      3、全局臨時表(以"##"開頭命名的)在所有的會話內(nèi)可見,所以在創(chuàng)建全局臨時表之前首先檢查其是否存在,否則如果已經(jīng)存在,將會返回重復(fù)創(chuàng)建對象的錯誤。
      (1) 全局臨時表會在創(chuàng)建其的會話結(jié)束后被Drop,Drop后其他會話將不能對全局臨時表進行引用。
      (2) 引用是在語句級別進行,如:
      [1] 新建查詢窗口,運行語句:

      CREATE TABLE ##temp(RowID int)INSERT INTO ##temp VALUES(3)

      [2] 再次新建一個查詢窗口,每5秒引用一次全局臨時表

      While 1=1 BEGINSELECT * FROM ##tempWAITFOR delay '00:00:05'END

      [3] 回到第一個窗口,關(guān)閉窗口。
      [4] 下一次第二個窗口引用時,將產(chǎn)生錯誤。

    ?      

      4、不能對臨時表進行分區(qū)。

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

      6、臨時表內(nèi)列的數(shù)據(jù)類型不能定義成在TempDb中沒有定義的自定義數(shù)據(jù)類型(自定義數(shù)據(jù)類型是數(shù)據(jù)庫級別的對象,而臨時表屬于TempDb)。由于TempDb在每次SQL Server重啟后會被自動創(chuàng)建,所以你必須使用startup stored procedure來為TempDb創(chuàng)建自定義數(shù)據(jù)類型。你也可以通過修改Model數(shù)據(jù)庫來達到這一目標(biāo)。

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

      臨時表既可以通過Create Table語句創(chuàng)建,也可以通過"SELECT <select_list> INTO #table"語句創(chuàng)建。你還可以針對臨時表用"INSERT INTO #table EXEC stored_procedure"這樣的語句。
      臨時表可以擁有命名的約束和索引。但是,當(dāng)兩個用戶在同一時間調(diào)用同一存儲過程時,將會產(chǎn)生”There is already an object named ‘<objectname>’ in the database”這樣的錯誤。所以最好的做法是不用為建立的對象進行命名,而使用系統(tǒng)分配的在TempDb中唯一的。

    三、誤區(qū)

      1、表變量僅僅在內(nèi)存中。

      2、臨時表僅僅存儲在物理介質(zhì)中。

      以上兩種觀點都是錯誤的,只有內(nèi)存足夠,表變量和臨時表都會在內(nèi)存中創(chuàng)建和處理。也同樣可以在任何時間被存入磁盤。

      注意表變量的名字是系統(tǒng)分配的,表變量的第一個字符”@”并不是一個字母,所以它并不是一個有效的變量名。系統(tǒng)會在TempDb中為表變量創(chuàng)建一個系統(tǒng)分配的名稱,所以任何在sysobjects或sys.tables查找表變量的方法都會失敗。

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

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

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

      3、表變量不能擁有索引。

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

      declare @MyTableVariable table (RowID intPRIMARY KEY CLUSTERED)

      這個語句將會創(chuàng)建一個擁有聚集索引的表變量。由于主鍵有了對應(yīng)的聚集索引,所以一個系統(tǒng)命名的索引將會被創(chuàng)建在RowID列上。

    ??? 下面的例子演示你可以在一個表變量的列上創(chuàng)建唯一約束以及如何建立復(fù)合索引。

      declare @temp TABLE (RowID int NOT NULL,ColA int NOT NULL,ColB char(1)UNIQUE,PRIMARY KEY CLUSTERED(RowID, ColA))

      1) SQL 并不能為表變量建立統(tǒng)計信息,就像其能為臨時表建立統(tǒng)計信息一樣。這意味著對于表變量,執(zhí)行引擎認(rèn)為其只有1行,這也意味著針對表變量的執(zhí)行計劃并不是最優(yōu)。雖然估計的執(zhí)行計劃對于表變量和臨時表都為1,但是實際的執(zhí)行計劃對于臨時表會根據(jù)每次存儲過程的重編譯而改變。如果臨時表不存在,在生成執(zhí)行計劃的時候會產(chǎn)生錯誤。

      2) 一旦建立表變量后就無法對其進行DDL語句操作。因此如果需要為表建立索引或者加一列,你需要臨時表。

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

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

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

      6) 排序規(guī)則:表變量使用當(dāng)前數(shù)據(jù)庫的排序規(guī)則,臨時表使用TempDb的排序規(guī)則。如果它們不兼容,你還需要在查詢或者表定義中進行指定。

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

    四、情景選擇

      微軟推薦使用表變量,如果表中的行數(shù)非常小,則使用表變量。很多”網(wǎng)絡(luò)專家”會告訴你100是一個分界線,因為這是統(tǒng)計信息創(chuàng)建查詢計劃效率高低的開始。但是我還是希望告訴你針對你的特定需求對臨時表和表變量進行測試。很多人在自定義函數(shù)中使用表變量,如果你需要在表變量中使用主鍵和唯一索引,你會發(fā)現(xiàn)包含數(shù)千行的表變量也依然性能卓越。但如果你需要將表變量和其它表進行join,你會發(fā)現(xiàn)由于不精準(zhǔn)的執(zhí)行計劃,性能往往會非常差。

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

      臨時表和表變量有很多類似的地方。所以有時候并沒有具體的細(xì)則規(guī)定如何選擇哪一個。對任何特定的情況,你都需要考慮其各自優(yōu)缺點并做一些性能測試。

    五、表變量和臨時表的對比

      下面的表格會讓你比較其優(yōu)略有了更詳細(xì)的參考。

    特性表變量臨時表
    作用域當(dāng)前批處理當(dāng)前會話,嵌套存儲過程,全局:所有會話
    使用場景自定義函數(shù),存儲過程,批處理自定義函數(shù),存儲過程,批處理
    創(chuàng)建方式DECLARE statement only.只能通過DECLEARE語句創(chuàng)建

    CREATE TABLE 語句

    SELECT INTO 語句.

    表名長度最多128字節(jié)最多116字節(jié)
    列類型

    可以使用自定義數(shù)據(jù)類型

    可以使用XML集合

    自定義數(shù)據(jù)類型和XML集合必須在TempDb內(nèi)定義
    Collation字符串排序規(guī)則繼承自當(dāng)前數(shù)據(jù)庫字符串排序規(guī)則繼承自TempDb數(shù)據(jù)庫
    索引索引必須在表定義時建立索引可以在表創(chuàng)建后建立
    約束PRIMARY KEY, UNIQUE, NULL, CHECK約束可以使用,但必須在表建立時聲明PRIMARY KEY, UNIQUE, NULL, CHECK. 約束可以使用,可以在任何時后添加,但不能有外鍵約束
    表建立后使用DDL (索引,列)不允許允許.
    數(shù)據(jù)插入方式INSERT 語句 (SQL 2000: 不能使用INSERT/EXEC).

    INSERT 語句, 包括 INSERT/EXEC.

    SELECT INTO 語句.

    Insert explicit values into identity columns (SET IDENTITY_INSERT).不支持SET IDENTITY_INSERT語句支持SET IDENTITY_INSERT語句
    Truncate table不允許允許
    析構(gòu)方式批處理結(jié)束后自動析構(gòu)顯式調(diào)用 DROP TABLE 語句.?
    當(dāng)前會話結(jié)束自動析構(gòu) (全局臨時表: 還包括當(dāng)其它會話語句不在引用表.)
    事務(wù)只會在更新表的時候有事務(wù),持續(xù)時間比臨時表短正常的事務(wù)長度,比表變量長
    存儲過程重編譯會導(dǎo)致重編譯
    回滾不會被回滾影響會被回滾影響
    統(tǒng)計數(shù)據(jù)不創(chuàng)建統(tǒng)計數(shù)據(jù),所以所有的估計行數(shù)都為1,所以生成執(zhí)行計劃會不精準(zhǔn)創(chuàng)建統(tǒng)計數(shù)據(jù),通過實際的行數(shù)生成執(zhí)行計劃。
    作為參數(shù)傳入存儲過程僅僅在SQL Server2008, 并且必須預(yù)定義 user-defined table type.不允許
    顯式命名對象 (索引, 約束).不允許允許,但是要注意多用戶的問題
    動態(tài)SQL必須在動態(tài)SQL中定義表變量可以在調(diào)用動態(tài)SQL之前定義臨時表

    轉(zhuǎn)載于:https://www.cnblogs.com/xinaixia/p/5821548.html

    總結(jié)

    以上是生活随笔為你收集整理的T-SQL 之 表变量和临时表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产视频你懂得 | 99久久精品久久久久久清纯 | 国产精品久久久久久一区二区三区 | 午夜在线播放 | 欧美三级少妇高潮 | 劲爆欧美第一页 | 亚av| 日本公妇乱淫免费视频一区三区 | a级片毛片 | 国产精品久久久久影院 | 人妖天堂狠狠ts人妖天堂狠狠 | 麻豆成人91精品二区三区 | 色亚洲视频 | 91国自啪 | 国产网红无码精品视频 | 日韩在线免费视频 | 国产成人精品亚洲日本在线观看 | 日本免费网 | 精品中出| 伊人影音| 国产免费网 | 日韩精品第一页 | 黄色免费成人 | 日本中文字幕二区 | 午夜精品欧美 | 午夜久久久久久久 | 国产中文字幕在线播放 | 欧美日韩国产区 | 成人精品999 | 日韩性猛交ⅹxxx乱大交 | 成人国产精品一区二区 | 亲子乱aⅴ一区二区三区 | 麻豆影视免费观看 | 色网在线看 | 蜜臀av一区二区三区激情综合 | 欧美激情三级 | 免费看又黄又无码的网站 | 欧美视频第一页 | 国产一级片播放 | 超碰com | 99国产精品久久久久99打野战 | 久久99热精品 | 日韩欧美一区二区三区四区五区 | 成人免费小视频 | 被黑人猛躁10次高潮视频 | 性无码专区无码 | 免费观看的毛片 | 蜜桃传媒一区二区亚洲av | 日本大尺度吃奶做爰久久久绯色 | a成人在线 | 91小宝寻花一区二区三区 | 2023天天操| 日本xxxx人 | 久久国产一区 | 欧美视频第二页 | 欧美日韩成人精品 | 97超碰超碰 | 操日本女人 | 五个女闺蜜把我玩到尿失禁 | 国产精品99在线观看 | 韩日av网站 | 强乱中文字幕av一区乱码 | 肥老熟妇伦子伦456视频 | 在线国产一区二区 | 久热av在线 | 特黄aaaaaaaaa毛片免费视频 | 秘密基地免费观看完整版中文 | 国产精品一区二区av白丝下载 | 国产三级一区二区三区 | 免费久久一级欧美特大黄 | 大肉大捧一进一出好爽动态图 | 探花系列在线观看 | 精品国产乱码久久 | 国产成人免费片在线观看 | 性欧美www | 98视频在线| 91第一页| 性欧美大战久久久久久久 | 国产白浆在线观看 | 在线视频二区 | 欧美久久综合网 | 国产一级黄色av | 亚洲免费婷婷 | 精品国模一区二区三区欧美 | 欧美高清视频一区二区 | 欧美一级久久久 | 午夜视频福利在线观看 | www.香蕉网| 少妇捆绑紧缚av | 亚洲乱妇 | 黄色片视频 | 精品人妻一区二 | 一区二区三区视频网 | 男人天堂2020 | 丝袜制服影音先锋 | 国产精品传媒 | 日韩欧洲亚洲AV无码精品 | 成年人午夜免费视频 | 四虎影视库 |