• <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>

            Prayer

            在一般中尋求卓越
            posts - 1256, comments - 190, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            系統(tǒng)臨時表使用問題

            Posted on 2010-05-13 23:14 Prayer 閱讀(528) 評論(0)  編輯 收藏 引用 所屬分類: 數(shù)據(jù)庫,SQLDB2
            系統(tǒng)臨時表的使用:
            在一些程序中,我們需要一些僅僅在程序中使用的臨時表,但是程序結(jié)束后就不再使用,數(shù)據(jù)庫系統(tǒng)對這些應用提供系統(tǒng)臨時表,關(guān)于系統(tǒng)臨時表的生命存在周期和臨時表的數(shù)據(jù)存在周期說明一下:

            1、生命存在周期:
            A、理論上系統(tǒng)臨時表是不需要顯示的drop的,它是基于會話的,當系統(tǒng)臨時表基于的連接關(guān)閉的時候,系統(tǒng)臨時表將結(jié)束它的生命,這是最普通也是最常用的。

            B、當一個被調(diào)用對象的返回值是一個在臨時表上執(zhí)行的結(jié)果集,這個被調(diào)用對象執(zhí)行完畢的時候,是關(guān)閉連接的,但是,這時候臨時表是不消失的,這時候系統(tǒng)臨時表在調(diào)用者結(jié)束的時候才消失。因為返回的結(jié)果集只是一個相當于指針的東西,指向臨時表內(nèi)存中的地址,指向臨時表的指針還在使用的時候,臨時表是不能drop掉的。這帶來了很復雜的問題,首先:存儲過程中是不能drop臨時表的,而程序中沒有創(chuàng)建臨時表,也應該是不drop的,臨時表什么時間drop呢?其次:我們在一個連接中,無法2次調(diào)用一個存儲過程,他將告訴你臨時表已經(jīng)存在。可以做一個簡單的例子:寫一個帶有臨時表返回結(jié)果的存儲過程,在調(diào)用存儲存儲過程的程序中,我們完全可以訪問這個臨時表。
            簡單例子:
            存儲過程
            /**
            * JDBC 存儲過程 ADMINISTRATOR.P1
            */
            import java.sql.*;                   // JDBC 類

            public class P1
            {
                public static void p1 ( ResultSet[] rs ) throws SQLException, Exception
                {
                    // 獲取與數(shù)據(jù)庫的連接
                    Connection con = DriverManager.getConnection("jdbc:default:connection");
                    PreparedStatement stmt = null;
                    String sql;

                    sql = "declare global temporary table session.temp(cc char(5)) not logged";
                    stmt = con.prepareStatement( sql );
                    stmt.executeUpdate();

                    sql = "insert into  session.temp values ('1'),('2')";
                    stmt = con.prepareStatement( sql );
                    stmt.executeUpdate();
                    
                    sql = "SELECT * from session.temp";
                    stmt = con.prepareStatement( sql );
                    rs[0] = stmt.executeQuery();
                    //關(guān)閉連接(注意,這個地方在rs[0]為臨時表的結(jié)果集返回的時候,stmt是無法關(guān)閉的,臨時表是無法drop的,而con是可以關(guān)閉的,關(guān)閉后臨時表還存在)
                    if (con != null) con.close();
                }
            }                             

            客戶端調(diào)用我直接用命令行調(diào)用的。
            db2 =>; connect to sample

               數(shù)據(jù)庫連接信息

            數(shù)據(jù)庫服務器         = DB2/NT 7.2.1
            SQL 授權(quán)標識         = ADMINIST...
            本地數(shù)據(jù)庫別名       = SAMPLE
            //將自動提交設(shè)為false。
            db2 =>; update command options using c off
            DB20000I  UPDATE COMMAND OPTIONS 命令成功完成。

            //調(diào)用過程
            db2 =>; call p1()

            CC
            1
            2

            "P1" RETURN_STATUS:"0"
            //看看存儲過程中使用的臨時表,數(shù)據(jù)是可以看到的。
            db2 =>; select *  from session.temp

            CC
            -----
            1
            2

              2 條記錄已選擇。
            //一個連接中再次調(diào)用,失敗了
            db2 =>; call p1()
            SQL0601N  要創(chuàng)建的對象名與類型為"DECLARED TEMPORARY TABLE" 的現(xiàn)存名稱 "SESSION.TEMP" 相同。  SQLSTATE=42710
            //drop一下?ok,可以的
            db2 =>; drop table session.temp
            DB20000I  SQL 命令成功完成。
            //看看還有嗎?沒了!
            db2 =>; select *  from session.temp
            SQL0204N  "SESSION.TEMP" 是未定義的名稱。  SQLSTATE=42704
            //再次調(diào)用,成功了
            db2 =>; call p1()

            CC
            1
            2

            "P1" RETURN_STATUS:"0"


            C、Websphere上的程序中使用系統(tǒng)臨時表:因為websphere的連接使用連接池的技術(shù),這帶來了好處,但是同時也帶來了一些讓人容易誤解的地方,我們在程序中要關(guān)閉連接,很多時候看上去是關(guān)閉了數(shù)據(jù)庫的連接,事實上也是這樣的,但是當websphere的連接數(shù)在websphere連接池規(guī)定的連接數(shù)的范圍之內(nèi)的時候,程序中關(guān)閉連接是不能直接關(guān)閉數(shù)據(jù)庫的連接的,連接池使連接繼續(xù)保持,這時候,我們的關(guān)閉連接釋放的是該連接和相關(guān)因素在websphere和java程序中使用的資源,而該連接使用的數(shù)據(jù)庫資源是無法得到釋放的。也就是說,當我們在該連接上使用臨時表的時候,我們在程序中關(guān)閉了連接,但是臨時表是還存在的,連接池中把這個連接分配給其他程序使用的時候,其他程序還可以使用這個臨時表,這并不是我們想要的。這要求我們在程序的中顯式的drop掉臨時表。(這是在南寧解決系統(tǒng)臨時表使用問題中,碰到的一個問題,大家可以很容易的模擬出來)

            同時這也讓我們注意,一些設(shè)置,應該采取人為控制的方式,而不要采取默認,比如autoCommit,我們不能覺得程序結(jié)束了,就提交了,因為默認是程序結(jié)束提交的,如果錯了就都回滾了,但是如果連接上設(shè)定的是autoCommit為true的話,程序出錯就只能回滾你的出錯前最后一次未提交事務,也許你還在為你程序中出現(xiàn)的這種錯誤頭疼,他為什么前面的會提交呢?
            一段代碼,應盡可能的保持它的獨立性,執(zhí)行不要過多依賴于環(huán)境和其他的代碼,我想這是應該考慮的。就象在oracle數(shù)據(jù)庫上執(zhí)行sql和在db2數(shù)據(jù)庫上執(zhí)行sql有很明顯的區(qū)別一樣,oracle默認是不提交的,而db2默認是提交的,這樣在不主動控制事務的情況下,一個sql執(zhí)行的結(jié)果是完全不同的。

            2、數(shù)據(jù)存在周期
            臨時表的數(shù)據(jù)是在內(nèi)存中的,當你向一個臨時表插入數(shù)據(jù)的時候,他同時是直接的寫到硬盤中的,如果你的緩沖池可以滿足臨時表的數(shù)據(jù)都存在內(nèi)存中,它在使用的時候是不需要讀硬盤上的數(shù)據(jù)的,除非你的緩沖池不能滿足,這樣會降低臨時表的性能。我們知道,事務的提交和回滾是對數(shù)據(jù)庫的更改做永久化,從內(nèi)存中的更改到硬盤上的更改或者放棄更改(在更改實現(xiàn)的同時,是回收曾經(jīng)占用的內(nèi)存資源的)。對一個永久表,插入數(shù)據(jù),就是在你提交之前,別的程序訪問不了你插入的數(shù)據(jù),在你提交之后,所有的程序都可以訪問你插入的數(shù)據(jù);而臨時表不是這樣的,無論執(zhí)行提交還是回滾,臨時表數(shù)據(jù)占用的內(nèi)存資源都將被釋放,同時臨時表寫到硬盤上的數(shù)據(jù)也全部刪除。
            也就是說,無論執(zhí)行提交還是回滾,臨時表的數(shù)據(jù)都沒了,但是臨時表還是存在的,這一點需要大家注意,在使用的過程中說插入了數(shù)據(jù),但是沒有數(shù)據(jù),為什么呢??
            看一個簡單的命令行模擬的例子:
            db2 =>; connect to sample

               數(shù)據(jù)庫連接信息

            數(shù)據(jù)庫服務器         = DB2/NT 7.2.1
            SQL 授權(quán)標識         = ADMINIST...
            本地數(shù)據(jù)庫別名       = SAMPLE
            //創(chuàng)建臨時表
            db2 =>; declare global temporary table session.test(col1 char(5)) not logged
            DB20000I  SQL 命令成功完成。
            //插入數(shù)據(jù)
            db2 =>; insert into session.test values('5')
            DB20000I  SQL 命令成功完成。
            //選擇數(shù)據(jù),沒有數(shù)據(jù)?是的!
            db2 =>; select * from session.test

            COL1
            -----

              0 條記錄已選擇。
            //我們把提交方式改為默認不提交
            db2 =>; update command options using c off
            DB20000I  UPDATE COMMAND OPTIONS 命令成功完成。
            //再次插入數(shù)據(jù)
            db2 =>; insert into session.test values('5')
            DB20000I  SQL 命令成功完成。
            //選擇數(shù)據(jù),ok,我們看到數(shù)據(jù)了!
            db2 =>; select * from session.test

            COL1
            -----
            5

              1 條記錄已選擇。
            //提交一下,或者執(zhí)行rollback也可以  
            db2 =>; commit
            DB20000I  SQL 命令成功完成。
            //數(shù)據(jù)沒了
            db2 =>; select * from session.test

            COL1
            -----

              0 條記錄已選擇。
              
              
            以上是系統(tǒng)臨時表使用的過程中我們程序開發(fā)者需要注意的可能出現(xiàn)的問題,知道問題是怎么出現(xiàn)的,我們應該如何解決出現(xiàn)的問題和如何更好的使用臨時表,這是我們的目標。
            蜜桃麻豆www久久国产精品| 久久国产亚洲高清观看| 精品综合久久久久久88小说| 久久久久人妻一区精品果冻| 久久亚洲精品无码aⅴ大香| 亚洲AV无码久久| 国产精品免费久久久久久久久 | 亚洲AV伊人久久青青草原| 无码人妻久久一区二区三区蜜桃| 亚洲国产精品无码久久久秋霞2 | 久久er国产精品免费观看8| 久久久久国产视频电影| 亚洲国产美女精品久久久久∴| 狠狠色丁香婷婷综合久久来来去 | 99久久婷婷国产综合亚洲| 久久93精品国产91久久综合| 中文字幕日本人妻久久久免费| 国产精品99久久久久久www| 麻豆成人久久精品二区三区免费 | 久久国产精品免费一区| 人妻久久久一区二区三区| 久久久久亚洲AV成人网人人软件| 久久丫精品国产亚洲av| 欧美日韩精品久久久久| 欧美一区二区精品久久| 久久久久久人妻无码| 97精品国产97久久久久久免费| 久久精品一区二区三区中文字幕| 国产V综合V亚洲欧美久久| 一本色道久久综合狠狠躁| 久久久亚洲裙底偷窥综合 | 久久伊人精品一区二区三区| 久久99精品久久久久久9蜜桃| 99久久中文字幕| 狠狠狠色丁香婷婷综合久久五月| 久久久精品人妻一区二区三区四| 久久福利资源国产精品999| 一本综合久久国产二区| 思思久久99热只有频精品66| 久久笫一福利免费导航| 久久久久久无码国产精品中文字幕 |