• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            Update操作一定是先Delete再Insert嗎?

            轉載:http://www.cnblogs.com/liuxinhuahao/archive/2010/01/15/1648749.html

            Update操作一定是先DeleteInsert嗎?

            Update在數據庫中的執行是怎么樣的?“Update操作是先把數據刪除,然后再插入數據”。在網上看了很多也都是這么認為的。但在查閱到一些不同看法的時候我進行了一些驗證,發現還有其它的情況。

            這里我分三種情況來講:

            1、更改沒有索引列的字段,更改前和更改后的字符串長度一樣;
            2
            更改沒有索引列的字段,更改后比更改前的字符串長;
            3
            、更改聚集索引字段。

            一、 創建表、索引和數據:

            --創建表MyTable1

            IF EXISTS(SELECT * FROM sysobjects WHERE [name]='MyTable1' AND [type]='u')

                DROP TABLE MyTable1

            GO

            CREATE TABLE MyTable1

            (

                ID     INT,

                SName  VARCHAR(20)  

            );

            --創建索引

            CREATE UNIQUE CLUSTERED INDEX IX_ID ON MyTable1(ID);

             

            INSERT INTO MyTable1 values( 1,'aaaa')

            INSERT INTO MyTable1 values( 2,'bbbb')

            INSERT INTO MyTable1 values( 3,'cccc')

            GO

             

            SELECT * FROM MyTable1 mt

            GO

             

            --創建表MyTable2

            IF EXISTS(SELECT * FROM sysobjects WHERE [name]='MyTable2' AND [type]='u')

                DROP TABLE MyTable2

            GO

            CREATE TABLE MyTable2

            (

                ID     INT,

                SName  VARCHAR(20)  

            );

            --創建索引

            CREATE UNIQUE CLUSTERED INDEX IX_ID ON MyTable2(ID);

             

            INSERT INTO MyTable2 VALUES ( 1,'aaaa')

            INSERT INTO MyTable2 VALUES ( 2,'bbbb')

            INSERT INTO MyTable2 VALUES ( 3,'cccc')

             

            SELECT * FROM MyTable2 mt

            二、 查看數據庫的ID號以及兩個表對應的ID

            --查看數據庫的ID號以及兩個表對應的ID

            select db_id() AS '數據庫ID',object_id('MyTable1')as 'MyTable1_ID',object_id('MyTable2')as 'MyTable2_ID'

             

             

             

            查詢結果如下:

            三、 查看數據頁的頁碼

            --查看數據頁的ID

            DBCC extentinfo(6,213575799)--這里是剛剛查出來的數據庫的ID,是表MyTable1ID

            DBCC extentinfo(6,229575856)--這里是剛剛查出來的數據庫的ID,是表MyTable2ID

            查詢結果如下:

            表示MyTable1的數據存儲在第45頁,MyTable2的數據存儲在第94頁。

            四、 查看2個表所在頁面上每條記錄的存儲情況:

            DBCC traceon(3604) WITH NO_INFOMSGS              --打開跟蹤

            DBCC IND('TestDB','MyTable1',0)               --列出所有頁和索引。

                                                          --參數說明,:數據庫名;:表名;:索引的ID,表示堆,-1 表示顯示所有索引和IAMs, -2表示只顯示IAMs

             

            DBCC PAGE(TestDB,1,45,1)                  --查看數據頁和索引

                                                         --參數說明,:數據庫名;:數據頁文件文件組編號;:數據頁ID;:數據顯示類型(,)

            語句執行后我們得到下面的結果:

            1.   MyTable1Row – Offset

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 115 (0x73)                

            0 (0x0) - 96 (0x60)                        

             

             

            2.   MyTable2Row – Offset

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                 

            1 (0x1) - 115 (0x73)                

            0 (0x0) - 96 (0x60)                   

             

                可以看到兩個表的存儲在數據庫中數據頁的位置是一樣的。這是因為一個頁只能放一個對象。

            五、 下面我們來看第一種情況:更改沒有索引列的字段,更改前和更改后的字符串長度一樣;

            UPDATE MyTable1 SET  SName = 'dddd' WHERE ID=2

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 115 (0x73)                

            0 (0x0) - 96 (0x60)                        

             

            發現他的存儲位置沒有發生改變。

            再來看MyTable2

            --先刪除后插入

            DELETE FROM MyTable2 WHERE ID=2

            INSERT INTO MyTable2(ID,SName)VALUES(2,   'dddd')

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 153 (0x99)                

            0 (0x0) - 96 (0x60)                             

             

            MyTable2的存儲發生變化了,原先在115134之間存儲的是第二條記錄,現在這條記錄卻存儲到了153個字節以后了,而原來115134之間什么也沒存儲,這樣這里就形成了內部碎片。對于這種update后數據的存儲位置不發生變化的更新稱為現場更新,如果位置發生了改變就稱為非現場更新。

            所以對于這種情形來說:update操作并不是先deleteinsert的。

            六、 下面我們再來測試第二種情況:更改沒有索引列的字段,更改后比更改前的字符串長;

            先更新表MyTable1,再查看數據頁的存儲情況:

            UPDATE MyTable1 SET SName='aaaaaa' WHERE ID=2

            DBCC PAGE(TestDB,1,45,1)

            存儲結果如下:

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 153 (0x99)                

            0 (0x0) - 96 (0x60)  

            這時我們看到他的存儲和先DeleteInsert一樣了。

            七、 我們再來看第三種情況:更改聚集索引字段

            為了避免對數據庫的操作影響查看的難度,再執行一下創建表的語句。

            數據更新之前的結果如下:

            MyTable1

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 115 (0x73)                

            0 (0x0) - 96 (0x60)  

             

            MyTable2

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 115 (0x73)                

            0 (0x0) - 96 (0x60)                 

             

            先對表MyTable1操作:更新ID

            UPDATE MyTable1 SET ID = 0 WHERE ID=2

            DBCC PAGE(TestDB,1,94,1)   --數據頁的位置已經發生改變

            存儲結果如下:

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 153 (0x99)                

            0 (0x0) - 96 (0x60)                 

            再來對MyTable2操作:

            DELETE FROM MyTable2 WHERE ID = 2

            INSERT INTO MyTable2(ID,SName)VALUES(2,   'bbbb')

            DBCC PAGE(TestDB,1,126,1)  --數據頁的位置已經發生改變

            存儲結果如下:

            OFFSET TABLE:

             

            Row - Offset                        

            2 (0x2) - 134 (0x86)                

            1 (0x1) - 153 (0x99)                

            0 (0x0) - 96 (0x60)        

            發現此時upadte為非現場更新,數據的存儲位置已經發生了改變。和我們所想的先DeleteInsert是一樣的。

            其實在更改聚集索引鍵列的時候,也可能發生現場更新。比如有3條記錄分別為12、5,我們把其中的2更改為了3,由于3是在15之間的數字,所以在更改為3后,這條記錄還是會存儲在15之間,所以就是現場更新了。


            posted on 2011-03-30 15:48 楊粼波 閱讀(932) 評論(0)  編輯 收藏 引用

            亚洲色大成网站WWW久久九九| 亚洲中文字幕无码久久2017| 97久久国产亚洲精品超碰热| 久久婷婷成人综合色综合| 久久久久AV综合网成人| 国产精品久久精品| 久久久久亚洲AV综合波多野结衣| 少妇久久久久久被弄到高潮 | 国产A三级久久精品| 久久精品水蜜桃av综合天堂 | 久久精品国产99久久丝袜| 久久强奷乱码老熟女网站| 99久久精品国内| 久久久久亚洲国产| 韩国三级大全久久网站| 热久久国产欧美一区二区精品| 99久久国产热无码精品免费 | 久久亚洲中文字幕精品有坂深雪 | 亚洲精品国产综合久久一线| 日韩精品久久无码人妻中文字幕| 色综合久久中文色婷婷| 天天爽天天狠久久久综合麻豆 | 麻豆久久| 国产精品成人99久久久久91gav| 伊色综合久久之综合久久| 免费精品99久久国产综合精品| 亚洲精品无码成人片久久| 久久男人中文字幕资源站| 中文字幕亚洲综合久久2| 久久精品国产网红主播| 午夜精品久久久久久中宇| 狠狠色丁香久久婷婷综合蜜芽五月 | 久久婷婷五月综合97色直播| 久久亚洲欧美日本精品| 久久99精品久久只有精品| 性欧美大战久久久久久久久| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 国产69精品久久久久99| 久久福利青草精品资源站| 久久96国产精品久久久| 久久精品成人免费网站|