欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Oracle中大對象(LOB)處理方法

 更新時(shí)間:2022年05月07日 10:21:10   作者:springsnow  
這篇文章介紹了Oracle中大對象(LOB)的處理方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、LOB數(shù)據(jù)類型分類

1、按存儲數(shù)據(jù)的類型分

  • 字符類型: 
    CLOB:存儲大量 單字節(jié) 字符數(shù)據(jù)。 
    NLOB:存儲定寬 多字節(jié) 字符數(shù)據(jù)。
  • 二進(jìn)制類型: 
    BLOB:存儲較大無結(jié)構(gòu)的二進(jìn)制數(shù)據(jù)。
  • 二進(jìn)制文件類型: 
    BFILE:將二進(jìn)制文件存儲在數(shù)據(jù)庫外部的操作系統(tǒng)文件中。存放文件路徑。

2、按存儲方式分

  • 存儲在內(nèi)部表空間: 
    CLOB,NLOB和BLOB
  • 指向外部操作系統(tǒng)文件: 
    BFILE

3、Null LOBs與Empty LOBs

DECLARE
    some_clob CLOB;
BEGIN
    IF some_clob IS NULL THEN
        dbms_output.put_line('a'); --NULL 表示該 LOB 字段或變量中連 LOB 指針都沒有
    ELSIF dbms_lob.getlength(some_clob) = 0 THEN
        dbms_output.put_line('b'); --empty LOB 是指該 LOB 字段或變量中保存了一個(gè) LOB 指針,但這個(gè)指針并沒有指向任何 LOB 數(shù)據(jù)
    ELSE
        dbms_output.put_line('c'); --指針有實(shí)際內(nèi)容
    END IF;
END;

二、LOB寫入

Blob數(shù)據(jù)不能象其它類型數(shù)據(jù)一樣直接插入(INSERT)。插入前必須先插入一個(gè)空的Blob對象,BLOB類型的空對象為EMPTY_BLOB(),之后通過SELECT命令查詢得到先前插入的記錄并鎖定,繼而將空對象修改為所要插入的Blob對象。

當(dāng)獲取到一個(gè)可用的 LOB 指針(定位器)后,就可以通過該指針寫入 LOB 數(shù)據(jù)了。有兩種寫入數(shù)據(jù)的系統(tǒng)函數(shù):

  • DBMS_LOB.WRITE :將數(shù)據(jù)隨機(jī)地寫入 LOB 中。
  • DBMS_LOB.WRITEAPPEND :從 LOB 的最后開始寫入數(shù)據(jù)。

運(yùn)用dbms_lob包用dbms_lob.write()寫入只能存儲32k以下的圖片。

注意:這里并不需要使用 UPDATE 來更新列 falls_myclob,因?yàn)檫@個(gè) LOB 指針并沒有發(fā)生變化,我們只是將數(shù)據(jù)寫入它所指向的位置。

declare
  myclob          clob;
  amount          binary_integer;
  offset          integer;
  first_direction varchar2(100);
  more_myclob     varchar2(500);
begin
  --刪除所有“munining Falls”的現(xiàn)有行,然后
  delete from waterfalls   where falls_name =      'Munising Falls';
  
  insert into waterfalls   (falls_name, falls_myclob)  values   ('Munising Falls', EMPTY_CLOB()); --使用EMPTY_CLOB()插入新行來創(chuàng)建LOB定位器
  select falls_myclob   into myclob   from waterfalls  where falls_name = 'Munising Falls'; --檢索由前面的INSERT語句創(chuàng)建的LOB定位器
  --或直接
  INSERT  into waterfalls(falls_name, falls_myclob) values('Munising Falls' EMPTY_CLOB());  returning falls_myclob   into myclob;

  DBMS_LOB.OPEN(myclob, DBMS_LOB.LOB_READWRITE); --打開LOB;不是嚴(yán)格必要的,但是最好打開/關(guān)閉lob。
  
  first_direction := 'Follow I-75 across the Mackinac Bridge.';
  amount          := LENGTH(first_direction); --要寫的字符數(shù)
  offset          := 1; --開始寫CLOB的第一個(gè)字符
  DBMS_LOB.WRITE(myclob, amount, offset, first_direction); --使用DBMS_LOB。開始寫
  
  more_myclob := ' Take US-2 west from St. Ignace to Blaney Park.' ||    ' From Seney, take M-28 west to Munising.'; --使用DBMS_LOB.WRITEAPPEND添加更多的myclob
  DBMS_LOB.WRITEAPPEND(myclob, LENGTH(more_myclob), more_myclob);
  
  more_myclob := ' In front of the paper mill, turn right on H-58.' ||    ' Sand Point Road.'; --添加更多的myclob
  DBMS_LOB.WRITEAPPEND(myclob, LENGTH(more_myclob), more_myclob);
  
  DBMS_LOB.CLOSE(myclob); --關(guān)閉LOB,就完成了。
end;

三、LOB讀取

使用系統(tǒng)函數(shù) DBMS_LOB.READ( ) 來讀取 LOB 中的數(shù)據(jù),當(dāng)然,首先要得到這個(gè) LOB 指針。比如讀取 CLOB 數(shù)據(jù),應(yīng)該指定字符串的偏移量(offset),從指定的偏移量的位置開始讀取數(shù)據(jù)。 
CLOB 的第一個(gè)字符的偏移量是1;也需要指定讀取的字符串長度。如果這個(gè) CLOB 數(shù)據(jù)太大,應(yīng)該多次讀取數(shù)據(jù)。對于 BLOB 數(shù)據(jù),也是這樣處理,唯一的區(qū)別就是它是按字節(jié)存儲的。 
DBMS_LOB.READ 中的第二個(gè)參數(shù) chars_read_1,是 IN OUT 參數(shù)。 
調(diào)用時(shí)按照該參數(shù)指定的長度來讀取數(shù)據(jù),讀取完畢后,將其更新為實(shí)際讀取的字符(字節(jié))長度。 
當(dāng)讀取后,該參數(shù)的值比你原來的值小,則說明已經(jīng)讀取到 LOB 的末尾了。

declare
  myclob   clob;
  myclob_1 varchar2(300);
  myclob_2 varchar2(300);
  chars_read_1 binary_integer;
  chars_read_2 binary_integer;
  offset       integer;
begin
  select falls_myclob into myclob from waterfalls where falls_name = 'Munising Falls'; --檢索之前插入的LOB定位器
  offset := 1;  --從第一個(gè)字符開始閱讀
  chars_read_1 := 229; --嘗試讀取myclob的229個(gè)字符時(shí),chars_read_1將使用實(shí)際讀取的字符數(shù)進(jìn)行更新
  DBMS_LOB.READ(myclob, chars_read_1, offset, myclob_1);

  if chars_read_1 = 229 then  --如果讀取229個(gè)字符,則更新偏移量并嘗試讀取255個(gè)字符。
    offset       := offset + chars_read_1;
    chars_read_2 := 255;
    DBMS_LOB.READ(myclob, chars_read_2, offset, myclob_2);
  else
    chars_read_2 := 0;
    myclob_2 := '';
  end if;
  
  DBMS_OUTPUT.PUT_LINE('Characters read = ' ||  TO_CHAR(chars_read_1 + chars_read_2));  --顯示讀取的字符總數(shù)
  DBMS_OUTPUT.PUT_LINE(myclob_1);  --顯示myclob
  DBMS_OUTPUT.PUT_LINE(myclob_2);
end;

四、BFile文件大對象(存儲在操作系統(tǒng)文件中的數(shù)據(jù))

PL/SQL中的Bfile只能讀取Bfile數(shù)據(jù),而不能寫入。

BLOB,CLOB,NCLOB 存儲在數(shù)據(jù)庫內(nèi),而 BFILE 存儲在數(shù)據(jù)庫外。BFILE 和其他三種大字段類型相比,BFILE 有以下三點(diǎn)不同:

  • BFILE 的數(shù)據(jù)是存儲在操作系統(tǒng)文件中的,而不是在數(shù)據(jù)庫中;
  • BFILE 數(shù)據(jù)不參與事務(wù)處理,也就是說,BFILE 數(shù)據(jù)的改變不能被提交和回滾(但 BFILE 指針的改變是可以提交或回滾的);
  • 從 PL/SQL 中,只能讀取 BFILE 數(shù)據(jù),而不能寫入。必須得在數(shù)據(jù)庫外先創(chuàng)建 BFILE 文件,再創(chuàng)建 BFILE 指針。

在 PL/SQL 中操作 BFILE,其實(shí)也是操作 LOB 指針。只是對于 BFILE 的指針來說,它指向的 BFILE 數(shù)據(jù)在數(shù)據(jù)庫外。 
所以,一個(gè) BFILE 列的兩行,可以存儲指向同一個(gè)文件的 BFILE 指針。

1. 創(chuàng)建

BFILE 指針由目錄(Oracle服務(wù)器上)和文件名組成(而實(shí)際的目錄和文件可以不存在),將這兩部分信息作為參數(shù)傳入 BFILENAME 函數(shù),該函數(shù)會返回一個(gè) BFILE 指針。

create directory BFILE_DATA as 'D:/temp';
declare
 waterfall_picture bfile;
begin
 waterfall_picture := BFILENAME('BFILE_DATA','waterfall.gif'); --調(diào)用BFILENAME來創(chuàng)建BFILE定位器
 insert into waterfalls (falls_name, falls_web_page) values ('my waterfall',waterfall_picture); --保存我們的新定位在waterfalls 
en

2. 讀取

declare
 waterfall bfile;
 piece raw(60);
 amount binary_integer := 60;
 offset integer := 1;
begin
 select falls_web_page into waterfall from waterfalls where falls_name='my waterfall'; --檢索LOB定位器
 DBMS_LOB.OPEN(waterfall); --打開定位器,讀取60個(gè)字節(jié),然后關(guān)閉定位器
 DBMS_LOB.READ(waterfall, amount, 1, piece);
 DBMS_LOB.CLOSE(waterfall);

 DBMS_OUTPUT.PUT_LINE(RAWTOHEX(piece));--十六進(jìn)制顯示結(jié)果
 --將原始結(jié)果轉(zhuǎn)換為我們可以讀取的字符串
 --DBMS_OUTPUT.PUT_LINE(UTL_RAW.CAST_TO_VARCHAR2(piece));
 end;

五、將文件系統(tǒng)數(shù)據(jù)庫通過BFile導(dǎo)入到LOB字段中

BFILE 提供了一種從數(shù)據(jù)庫中訪問文件系統(tǒng)中數(shù)據(jù)的方法??赡苣阆雽⑦@些數(shù)據(jù)保存到 BLOB 或 CLOB 字段中。 
可以使用系統(tǒng)函數(shù)實(shí)現(xiàn):

  • dbms_lob.loadfrombfile
  • dbms_lob.loadclobfrombfile
  • dbms_lob.loadblobfrombfile

下面我們將圖片 watarfall.gif 保存到 BLOB 列中:

declare
  My_Falls_bfile bfile := BFILENAME('BFILE_DATA', 'waterfall.gif');
  photo               blob;
  destination_offset  integer := 1;
  source_offset       integer := 1;
begin
  delete from waterfalls where falls_name = 'my waterfall'; --刪除Tannery Falls的行,所以這個(gè)例子可以運(yùn)行多次。
  insert into waterfalls (falls_name, FALLS_PHOTO) values ('my waterfall', EMPTY_BLOB());--使用EMPTY_BLOB()插入新行來創(chuàng)建LOB定位器
  select FALLS_PHOTO into photo from waterfalls where falls_name = 'my waterfall'; --檢索由前面的INSERT語句創(chuàng)建的LOB定位器
  DBMS_LOB.OPEN(photo, DBMS_LOB.LOB_READWRITE);--打開目標(biāo)BLOB和源BFILE
  DBMS_LOB.OPEN(My_Falls_bfile);
  DBMS_LOB.LOADBLOBFROMFILE(photo,  My_Falls_bfile, DBMS_LOB.LOBMAXSIZE, destination_offset, source_offset);  --Load the contents of the BFILE into the BLOB column
  DBMS_LOB.CLOSE(photo);  --關(guān)閉兩個(gè)lob
  DBMS_LOB.CLOSE(My_Falls_bfile);
end;

六、C#讀寫Oracle BOLB數(shù)據(jù)。

(1)寫入數(shù)據(jù)到Orable Blob字段中。

首先要在BLob字段中插入一個(gè)Empty_blob(),才能寫入下面的數(shù)據(jù)。

* 在調(diào)用此函數(shù)之前需要寫插入一個(gè)字符串到 BLOB 中比如:
*        "CREATE TABLE tablewithlobs (a int, b BLOB, c CLOB, d NCLOB)";
*        "INSERT INTO tablewithlobs values (1, 'AA', 'AAA', N'AAAA')";
* 否則程序會在 OracleLob tempLob    = reader.GetOracleLob(0) 處出錯(cuò)。

寫入:

conn.Open();
OracleCommand cmd = conn.CreateCommand();
OracleTransaction transaction = cmd.Connection.BeginTransaction();      // 利用事務(wù)處理(必須)
cmd.Transaction = transaction;
// 獲得 OracleLob 指針
cmd.CommandText = "select fulls_myblob from waterfalls where fulls_name = 'myabc' FOR UPDATE";
using (OracleDataReader reader = cmd.ExecuteReader())
{
    reader.Read(); //Obtain the first row of data.
    OracleBlob tempLob = reader.GetOracleBlobForUpdate(0);   //Obtain a LOB.        
    FileStream fs = new FileStream("c:\\1.txt", FileMode.Open); // 將文件寫入 BLOB 中
    tempLob.BeginChunkWrite();
    int length = 10485760;
    byte[] Buffer = new byte[length];
    int i;
    while ((i = fs.Read(Buffer, 0, length)) > 0)
    {
        tempLob.Write(Buffer, 0, i);
    }
    fs.Close();
    tempLob.EndChunkWrite();
    cmd.Parameters.Clear();
}
transaction.Commit(); // 提交事務(wù)
conn.Close();

(2)讀取Oracle Blob到文件中。

conn.Open();
OracleCommand cmd = conn.CreateCommand();
OracleTransaction trans = cmd.Connection.BeginTransaction();// 利用事務(wù)處理(必須)
cmd.Transaction = trans;
// 獲得 OracleLob 指針
string sql = "select fulls_myblob from waterfalls where fulls_name = 'myabc'";
cmd.CommandText = sql;
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
OracleBlob tempLob = dr.GetOracleBlob(0);
dr.Close();

// 讀取 BLOB 中數(shù)據(jù),寫入到文件中
FileStream fs = new FileStream("c:\\1.txt", FileMode.Create);
int length = 1048576;
byte[] Buffer = new byte[length];
int i;
while ((i = tempLob.Read(Buffer, 0, length)) > 0)
{
    fs.Write(Buffer, 0, i);
}
fs.Close();
tempLob.Clone();
cmd.Parameters.Clear();
trans.Commit();     // 提交事務(wù)
conn.Close();

到此這篇關(guān)于Oracle中大對象(LOB)處理方法的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論