<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    JAVA—咖啡館

    ——歡迎訪問rogerfan的博客,常來《JAVA——咖啡館》坐坐,喝杯濃香的咖啡,彼此探討一下JAVA技術,交流工作經驗,分享JAVA帶來的快樂!本網站部分轉載文章,如果有版權問題請與我聯系。

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      447 Posts :: 145 Stories :: 368 Comments :: 0 Trackbacks

    13-4 Lob類型
            13.4.1 基本介紹
            Oracle和plsql都支持lob(large object) 類型,用來存儲大數量數據,如圖像文件,聲音文件等。Oracle 9i realse2支持存儲最大為4g的數據,oracle 10g realse1支持最大8到128萬億字節的數據存儲,依賴于你的db的block size。
            在plsql中可以申明的lob類型的變量如下:
    類型        描述
    BFILE        二進制文件,存儲在數據庫外的操作系統文件,只讀的。把此文件當二進制處理。
    BLOB        二進制大對象。存儲在數據庫里的大對象,一般是圖像聲音等文件。
    CLOB        字符型大對象。一般存儲大數量文本信息。存儲單字節,固定寬度的數據。
    NCLOB        字節字符大對象。存儲單字節大塊,多字節固定寬度,多字節變寬度數據。
    Oracle將lob分類為兩種:
    1.存儲在數據庫里的,參與數據庫的事務。BLOB,CLOB,NCCLOB。
    2.存儲在數據庫外的BFILE,不參與數據庫的事務,也就是不能rollback或commit等,它依賴于文件系統的數據完整性。
    LONG和LONG RAW這兩種數據類型也是存儲字符的,但是有系列的問題,不建議使用,這里也就不討論了。
    13.4.2 LOB的使用
    本部分不討論lob的所有細節,只討論lob的基本原理和在plsql中的基本使用,為plsql開發使用lob提供一個基礎性指導。
    本部分使用的表是:
    /**
    table script
    **/
    CREATE TABLE waterfalls (
           falls_name VARCHAR2(80),--name
           falls_photo BLOB,--照片
           falls_directions CLOB,--文字
           falls_description NCLOB,--文字
           falls_web_page BFILE);--指向外部的html頁面
    /      
            這個表我們并不需要clob和nclob兩個,只取一就可以,這里全部定義只是為了演示使用。
    1.        理解LOB的Locator
    表中的Lob類型的列中存儲的只是存儲指向數據庫中實際存儲lob數據的一個指針。
    在plsql中申明了一個lob類型的變量,然后從數據庫中查詢一個lob類型的值分配給變量,也只是將指針復制給了它,那么這個變量也會指向數據庫中實際存放lob數據的地方。如:
    --understanding lob locators
    DECLARE
           photo BLOB;
        BEGIN
           SELECT falls_photo
             INTO photo
             FROM waterfalls
            WHERE falls_name='Dryer Hose';
    見下圖:
    Lob工作原理圖解
            從上面的圖可以看出,要處理lob數據,必須先獲得lob locators。我們可以通過一個select語句獲取,當賦值給lob變量的時候,它也獲得同樣的lob locators。我們在plsql中處理可以使用dbms_lob包,里面內置了很多過程和函數來讀取和修改我們的lob數據。下面給出處理lob數據的一般方法。
    1.        通過select語句獲取一個lob locator。
    2.        通過調用dbms_lob.open打開lob。
    3.        調用dbms_lob.getchunksize獲得最佳讀寫lob值。
    4.        調用dbms_lob.getlength獲取lob數據的字節值。
    5.        調用dbms_lob.read獲取lob數據。
    6.        調用dbms_lob.close關閉lob。       
    2.        Empty lob and Null lob
    Empty的意思是我們已經獲取了一個lob locator,但是沒有指向任何lob數據。Null是定義了一個變量,但是沒有獲得lob locator。對lob類型的處理和其他類型不一樣。如下面的例子:
    /* null lob example*/
    declare
           directions clob;--定義了,但是沒有分配值,為null
           begin
               if directions is null then
                  dbms_output.put_line('directions is null');
               else
                  dbms_output.put_line('directions is not null');
               end if;      
           end;
    /
    DECLARE
           directions CLOB;--定義一個,并且分配值
        BEGIN
           --刪除一行
           DELETE
             FROM waterfalls
            WHERE falls_name='Munising Falls';
           --插入一行通過使用 EMPTY_CLOB( ) to 建立一個lob locator
           INSERT INTO waterfalls
                     (falls_name,falls_directions)
              VALUES ('Munising Falls',EMPTY_CLOB( ));
           --獲得lob locator,上面插入的數據,因為我們插入的是一個empty_clob(),那么lob locator不指向任何數據,雖然給變量分配了只
          SELECT falls_directions
            INTO directions
            FROM waterfalls
           WHERE falls_name='Munising Falls';
          IF directions IS NULL THEN
             DBMS_OUTPUT.PUT_LINE('directions is NULL');
          ELSE
             DBMS_OUTPUT.PUT_LINE('directions is not NULL');--打印此句
          END IF;
          DBMS_OUTPUT.PUT_LINE('Length = '
                               || DBMS_LOB.GETLENGTH(directions));--結果為o
       END;
    注意:
    1.        上面例子中的empty_clob()是oracle的內置函數,創建了一個lob locator。但是我們沒有讓它指向任何數據,所以是empty。而且通過select語句給變量directions分配了lob locator,所以不是null,但是length為0,故為empty。
    2.        在基本類型中,我們判斷一個變量是不是有數據,只要is null就可以了。但是在lob類型中我們從以上的例子看出來是不正確的。Lob首先必須判斷is null看是否分配lob locator,如果分配了還需要進一步檢查length是否為0,看是否是empty,所以完整的是下面這樣:
    IF some_clob IS NULL THEN
          --如果is null為true表示未分配,肯定沒有數據
       ELSEIF DBMS_LOB.GETLENGTH(some_clob) = 0 THEN
          --分配了length為0,也沒有數據
       ELSE
          --有數據
       END IF;
    3.建立LOB
            在上面我們使用empty_clob()建立了一個空的clob,lob locator只是一個指針,真正的數據是存儲在磁盤中或數據庫文件中。我們先建立一個空的clob,然后我們可以update來讓變量真正指向有數據的lob。Empty_clob()可以用來處理clob和nclob。在oracle 8i中可以使用temporary lob達到同樣的效果。

     

    4.向LOB里寫入數據
            當獲得一個有效的lob locator之后,就可以使用dbms_lob包的下列procedure向lob中寫入數據。
            DBMS_LOB.WRITE:允許自動寫入數據到lob中。
            DBMS_LOB.WRITEAPPEND:向lob的末尾寫入數據。
    --write lob
    DECLARE
           directions CLOB;
           amount BINARY_INTEGER;
           offset INTEGER;
           first_direction VARCHAR2(100);
           more_directions VARCHAR2(500);
        BEGIN
           --Delete any existing rows for 'Munising Falls' so that this
           --example can be executed multiple times
           DELETE
             FROM waterfalls
            WHERE falls_name='Munising Falls';
           --Insert a new row using EMPTY_CLOB( ) to create a LOB locator
           INSERT INTO waterfalls
                     (falls_name,falls_directions)
              VALUES ('Munising Falls',EMPTY_CLOB( ));
           --Retrieve the LOB locator created by the previous INSERT statement
           SELECT falls_directions
             INTO directions
             FROM waterfalls
            WHERE falls_name='Munising Falls';
           --Open the LOB; not strictly necessary, but best to open/close LOBs.
           DBMS_LOB.OPEN(directions, DBMS_LOB.LOB_READWRITE);
           --Use DBMS_LOB.WRITE to begin
           first_direction := 'Follow I-75 across the Mackinac Bridge.';
           amount := LENGTH(first_direction); --number of characters to write
           offset := 1; --begin writing to the first character of the CLOB
           DBMS_LOB.WRITE(directions, amount, offset, first_direction);
           --Add some more directions using DBMS_LOB.WRITEAPPEND
           more_directions := ' Take US-2 west from St. Ignace to Blaney Park.'
                           || ' Turn north on M-77 and drive to Seney.'
                           || ' From Seney, take M-28 west to Munising.';
           DBMS_LOB.WRITEAPPEND(directions,
                                LENGTH(more_directions), more_directions);
           --Add yet more directions
           more_directions := ' In front of the paper mill, turn right on H-58.'
                           || ' Follow H-58 to Washington Street. Veer left onto'
                           || ' Washington Street. You''ll find the Munising'
                           || ' Falls visitor center across from the hospital at'
                           || ' the point where Washington Street becomes'
                           || ' Sand Point Road.';
           DBMS_LOB.WRITEAPPEND(directions,
                                LENGTH(more_directions), more_directions);
           --Close the LOB, and we are done.
           DBMS_LOB.CLOSE(directions);
        END;
    /
    在這個例子里,我們使用了write 和writeappend這兩個過程來插入數據到lob中。因為開始的時候,我們插入了一個空的lob locator。要注意一點,我們最后使用了dbms_lob.close方法關閉lob。這是一個好的方法,特別是在處理oracle text的時候,任何oracle text domain和function-based indexes被update是在wirte和writeappend的時候調用的,而不是在close的時候被update的。       
    我們向lob中寫入數據的時候,沒有必要更新表中的列。因為它保存的只是一個locator,我們的變量也獲得同樣的locator,當我們寫入數據去lob的時候,locator并沒有改變。改變的只是locator指向的物理數據。
    在sqlplus中顯示上面的例子:
            SQL> SET LONG 2000           
        SQL> COLUMN falls_directions WORD_WRAPPED FORMAT A70
        SQL> SELECT falls_directions
          2 FROM waterfalls
          3 WHERE falls_name='Munising Falls';
    其中set long 2000是顯示2000個字符。Word_wrappend是自動換行。
    5.從lob中讀取數據
    步驟:a.通過select查詢獲得lob locator初始化lob變量。2.調用dbms_lob.read過程讀取lob數據。
    下面是dbms_lob.read過程的定義,注意參數.  
    PROCEDURE read(lob_loc IN            BLOB, --初始化后的lob變量lob locator
                    amount IN OUT NOCOPY INTEGER,--讀取的數量(clob為字符數,blob,bfile是字節數)
                    offset IN            INTEGER,--開始讀取位置
                    buffer OUT           RAW);--讀到的數據,raw要顯示用轉換函數,見bfile
    PROCEDURE read(lob_loc IN            CLOB     CHARACTER SET ANY_CS,
                    amount IN OUT NOCOPY INTEGER,
                    offset IN            INTEGER,
                    buffer OUT           VARCHAR2 CHARACTER SET lob_loc%CHARSET);
    PROCEDURE read(file_loc IN             BFILE,
                     amount   IN OUT NOCOPY INTEGER,
                     offset   IN             INTEGER,
                     buffer   OUT            RAW);
    下面是一個讀取clob的例子:
    --從lob中讀取數據
    DECLARE
           directions CLOB;
           directions_1 VARCHAR2(300);
           directions_2 VARCHAR2(300);
           chars_read_1 BINARY_INTEGER;
           chars_read_2 BINARY_INTEGER;
           offset INTEGER;
        BEGIN
           --首先獲得一個lob locator
           SELECT falls_directions
             INTO directions
             FROM waterfalls
            WHERE falls_name='Munising Falls';
           --記錄開始讀取位置
           offset := 1;
           --嘗試讀取229個字符,chars_read_1將被實際讀取的字符數更新
           chars_read_1 := 229;
           DBMS_LOB.READ(directions, chars_read_1, offset, directions_1);
           --當讀取229個字符之后,更新offset,再讀取225個字符
           IF chars_read_1 = 229 THEN
              offset := offset + chars_read_1;--offset變為offset+chars_read_1,也就是從300開始
              chars_read_2 := 255;
              DBMS_LOB.READ(directions, chars_read_2, offset, directions_2);
           ELSE
              chars_read_2 := 0;--否則后面不在讀取
              directions_2 := '';
           END IF;
           --顯示讀取的字符數
           DBMS_OUTPUT.PUT_LINE('Characters read = ' ||
                               TO_CHAR(chars_read_1+chars_read_2));
          --顯示結果
          DBMS_OUTPUT.PUT_LINE(directions_1);
          dbms_output.put_line(length(directions_1));
          DBMS_OUTPUT.PUT_LINE(directions_2);
          dbms_output.put_line(length(directions_2));
       END;
       /
    Dbms_lob.read的第2個參數是傳遞要讀取的數量。對于clob是字符數,blob和bfile都是字節數。它是隨著讀取的數目自動更新的,offset不會更新。所以分布讀取需要手動更新offset,下個offset是上一個offset+讀取的數量。我們可以通過dbms_lob.get_length(lob_locator)獲得這個lob的長度,結果clob是字符數,blob和bfile是字節數,然后分布讀取。
    13.4.3 使用Bfile
            Bfile和clob,nclob,blob是不同的。Bfile是外部的lob類型,其他三個是oracle內部的lob類型,它們至少有三點主要不同的地方:
    1.        bfile的值是存在操作系統的文件中,而不是數據庫中。
    2.        bfile不參與數據庫事務操作。也就是改變bifle不能commit或rollback。但是改變bfile的locator可以commit或rollback。
    3.        bfile在plsql和oracle中是只讀的,不允許寫。你必須生成一個外部的操作系統文件讓bfile locator能夠完全指向它。
    在plsql中使用bifle,仍然需要lob locator,只不過是一個目錄和文件的別名,你可以使用biflename函數獲得一個bfile locator。使用create or replace directory [alias] as ‘file locator directory’,你必須具有CREATE ANY DIRECTORY權限才能使用。如:
    CREATE DIRECTORY bfile_data AS 'c:PLSQL BookCh12_Misc_Datatypes';
        GRANT READ ON DIRECTORY bfile_data TO gennick; --讀的權限給這個用戶。
    通過all_directory查找目錄信息。

    posted on 2009-06-02 16:02 rogerfan 閱讀(1719) 評論(0)  編輯  收藏 所屬分類: 【數據庫】
    主站蜘蛛池模板: 99久久婷婷国产综合亚洲| 18禁网站免费无遮挡无码中文| 亚洲不卡影院午夜在线观看| 亚洲码国产精品高潮在线| 国产真人无遮挡作爱免费视频| 免费看片在线观看| 久久亚洲免费视频| 成av免费大片黄在线观看| 美女裸免费观看网站| 99亚偷拍自图区亚洲| 亚洲一区二区三区高清视频| 亚洲人成电影在在线观看网色| 成人亚洲性情网站WWW在线观看| 国产成人无码a区在线观看视频免费| 亚洲人成在线免费观看| 亚洲一区免费观看| 暖暖免费在线中文日本| 叮咚影视在线观看免费完整版| 一个人看的在线免费视频| 农村寡妇一级毛片免费看视频| 久久亚洲色WWW成人欧美| 亚洲熟妇AV一区二区三区浪潮 | 香蕉国产在线观看免费| 亚洲AV无码精品国产成人| 亚洲午夜精品一区二区麻豆| 亚洲天堂免费在线| 亚洲精品456人成在线| 亚洲a级成人片在线观看| 亚洲伊人久久大香线蕉在观| 亚洲国产成人精品无码区在线网站| 亚洲人成依人成综合网| 亚洲高清在线mv| 亚洲系列中文字幕| 亚洲国产超清无码专区| youjizz亚洲| 亚洲男同gay片| 国产精品手机在线亚洲| 午夜成人无码福利免费视频| 中文字幕免费在线观看动作大片| 中国毛片免费观看| 国产成人精品无码免费看|