Oracle LOB數據類型專題

Oracle LOB數據類型專題


一、概述
LOB數據類型專門用於存儲大對象的數據,不超過4G字節,包括大文本、圖像圖像、視頻剪切等。
Oracle8之前使用LONG、LOBG RAW來實現,現慢慢淘汰,8開始使用LOB實現。




二、LOB的分類
分爲內部LOB和外部LOB。內部LOB包括CLOB、BLOB、NCOLB;外部LOB包括BFILE
內部LOB的數據存儲在數據庫中,並且支持事務操作(提交、回退、保持點);外部LOB的數據存儲在OS文件中,並且不支持事務操作


CLOB(存放大字符數據)用於存儲大批量字符數據,
BLOB(存放大二進制數據)用於存放音頻、圖像、圖像,
NCLOB(存放大字符數據)用於存儲大批量字符數據,
BFILE(存儲指向OS文件的指針)用於存儲電影文件。




三、LOB和LONG的比較
兩者都可以大批量字符數據和二進制數據。


1、LONG\LONG ROW
1)、一個表只能有一個LONG或LONG RAW列
2)、數據最大長度2G字節
3)、select返回數據
4)、數據存儲在行內
5)、不支持對象類型
6)、數據順序訪問


2、LOB
1)、一個表可以有多個LOB列
2)、數據最大長度4G字節
3)、select返回LOB定位符
4)、數據存儲在行內或行外
5)、支持對象類型
6)、數據隨機訪問


3、注意
LONG\LONG ROW列的數據域與其它列的數據相鄰存放;
而用LOB列時,如果數據小於4000字節,則與其它列相鄰存放(行內),大於則數據存放到專門的LOB段中(行內)。


4、臨時LOB
說明:臨時LOB相當於局部變量,與數據庫表無關,並且只能由當前應用程序建立和使用。
當SQL語句中使用臨時LOB時,它們只能作爲輸入宿主變量使用,可在where子句,values子句和set子句中使用臨時LOB,而不能在into子句中使用。




四、DBMS_LOB包
DBMS_LOB是Oracle提供的、專門用於處理LOB類型數據的PL/SQL包,該包定義了一些變量、過程、函數,下面逐一講述。


1.常量
說明:包中定義了6個常量,可以在PL/SQL中直接引用,方法爲包名.常量名
file_readonly constant binary_integer:=0;
lob_readonly contant binary_integer:=0;
lob_readwrite constant binaty_integer:=1;
lobmaxsize constant integer:=4294967295;
call constant pls_integer:=12;
session constant pls_integer:=10;


2、過程APPEND
說明:用於將源LOB變量的內容添加到目標LOB變量的尾部。只適用於內部LOB類型的blob和clob。
語法:
DBMS_LOB.APPEND(dest_lob in out nocopy blob,src_lob in blob);
DBMS_LOB.APPEND(dest_lob in out nocopy blob character set any_cs,src_lob in clob character set dest_lob%charset);
其中,dest_lob指定目標LOB變量,src_lob指定源LOB變量。
例子:
declare
dest_lob clob;
sec_lob clob;
begin
src_lob:='中國';
desc_lob:='你好';
dbms_lob.append(dest_lob,src_lob);
dbms_output.put_line(dest_lob);
end;


3、過程close
說明:用於關閉已經打開的LOB,全適用。
語法:DBMS_LOB.CLOSE(lob_loc in out nocopy blob/clob/bfile);


4、函數compare
說明:用於比較2個LOB的全部內容或者部分內容,但只能用於比較同類型的LOB變量。全適用。
語法:
DBMS_LOB.COMPARE(
lob_1 in blob/clob/bfile,
lob_2 in blob/clob/bfile,
amount in integer:=4294967295,
offset_1 in integer:=1,
offset_1 in integer:=1);
其中,lob_1指定第一個lob變量;lob_2指定第二個lob變量;amount指定字符個數(clob)或字節數(blob);
offser_1指定第一個lob的初始位置;offser_2指定第二個lob的初始位置;比較結果返回0則結果相同;反之則不相同。
例子:
declare
  dest_lob clob;
  src_lob clob;
begin
sec_lob:='中國';
dest_lob:='中國';
if dbms_lob.compare(sec_lob,dest_lob)=0 then
 dbms_output.put_line('內容相同');
else
 dbms_output.put_line('內容不同');
end if;
end;
 
5、過程copy
說明:將源lob變量的部分或者全部內容複製到目標lob變量中,只使用內部LOB類型。
語法:
DBMS_LOB.copy(dest_lob in out bocopy blob/clob/nclob,src_lob in blob/clob/nclob,
amount in integer,dest_offset in integer:=1,src_offset in integer:=1);
其中,將src_lob複製到dest_lob,dest_offset用於指定要複製到目標lob變量的起始位置,src_offset用於指定源lob變量中開始複製的起始位置。
例子:
declare
  dest_lob clob;
  src_lob clob;
  amount int;
begin
sec_lob:='中國';
dest_lob:='你好,';
amount:=dbms_lob.getlength(sec_lob);
dbms_lob.copy(dest_lob,src_lob,amount,3);
dbms_output.put_line(dest_lob);
end;


6、過程createtemporary
說明:用於建立臨時lob,Oracle會將臨時lob建立在用戶的臨時表空間,只使用與內部LOB類型
語法:
DBMS_LOB.createtemporary(
lob_loc in out nocopy blob/clob/nclob,
cache in boolean,
dur in pls_integer:=10
);
其中,lob_loc指向lob定位符;cache指向是否要將lob讀取到緩衝區;dur指向何時清除臨時lob(10:會話結束時清除;12:調用結束時清除)
例如:
declare
  src_loh clob;
begin
DBMS_LOB.createtemporary(src_lob,true);
end;


7、過程erase
說明:用於刪除lob變量的全部或部分內容,只適用內部lob。
語法:
dbms_lob.erase(lob_Loc in out nocopy blob/clob/nclob,amount in out nocopy integer,offset in integer:=1);
其中,offset指定開始刪除內容的起始位置,length指定個數。
例子:
declare
  src_Lob clob;
  offset int;
  amount int;
begin
src_lob:='歡迎使用Oracle';
amount:=10;
offset:=5;
dbms_lob.erase(src_lob,amount,offset);
dbms_output.put_line(src_lob);
end;


8、過程fileclose
說明:用於關閉已經打開的bfile定位符所指向的os文件。
語法:
dbms_lob.fileclose(file_Loc in out ncopy bfile);
其中,file_loc指定bfile定位符。


9、過程filecloseall
說明:用於關閉當前會話已經打開的所有bfile文件。
語法:dbms_lob.filecloseall


10.函數fileexists
說明:用於確定bfile定位符所指向的os文件是否存在。
語法:dbms_lob.fileexists(file_Loc in bfile) return integer;
其中,存在則返回1,不存在返回0。
例子:
declare
  file1 bfile;
begin
file1:=bfilename('G','readme.doc');
if dbms_lob.fileexists(file1)=0 then
 dbms_output.put_line('文件不存在');
else
 dbms_output.put_line('文件存在');
end if;
end;


11、過程filegetname
說明:用於取得bfile定位符所對應的目錄別名和文件名。
語法:
dbms_Lob.filegetname(file_loc in bfile,dir_alias out varchar2,filename out varchar2);
其中,dir_alias用於取得bfile定位符所對應的目錄別名;filename用於取得bfile定位符所對應的文件名。
例子:
declare
  dir_alias varchar2(20);
  filename varchar2(50);
  file_Loc bfile;
begin
select filename into file_loc from bfile_table where fno=1;
dbms_lob.filegetname(file_Loc,fir_alias,filename);
dbms_output.put_line('目錄'||dir_alias||'文件名'||filename);
end;


12、函數fileisopen
說明:用於確定bfile所對應的os文件是否已經打開。
語法:dbms_lob.fileisopen(file_loc in bfile) return integer;
其中文件被打開了返回1,否則返回0.
例子:
declare
  file1 bfile;
begin
file1:=bfilename('G','readme.doc');
if dbms_lob.fileisopen(file1)=0 then
 dbms_output.put_line('文件未打開');
else
 dbms_output.put_line('文件已打開');
end if;
end;


13、過程fileopen
說明:打開bfile所對應的os文件。
語法:dbms_Lob in out nocopy bfile,open_mode in binary_integer:=file_readonly);
其中,open_mode指定文件的打開模式。注意os文件只能以只讀方式打開。
例子:
declare
  file1 bfile;
begin
file1:=bfilename('G','readme.doc');
if dbms_lob.fileexists(file1)=1 then
 dbms_Lob.fileopen(file1);
 dbms_output.put_line('文件已經打開');
end if;
dbms_lob.fileclose(file1);
end;


14、過程freetemporary
說明:用於釋放在魔人臨時表空間中的臨時lob。
語法:dbsm_lob.freetemporary(lob_loc in out nocopy blob/clob/nclob);
其中lob_loc用於指定lob定位符。
declare
  src_lob clob;
begin
dbms_lob.createtemporary(src_lob,true);
sec_lob:='中華人民共和國';
dbms_lob.freetemporary(src_lob);
end;


15、函數getchunksize
說明:當建立包含clob列或blob列的表時,通過指定chunk參數可以指定操作lob需要分配的字節數(該值是數據塊尺寸的整數倍),
如果不指定該參數,其魔人值爲數據塊的尺寸。通過使用函數getchunksize,可以取得chunk參數所對應的值。
語法:dbms_lob.getchunksize(lob_loc in blob/clob/nclob) return integer;
例子:
declare
  src_lob clob;
  chunksize int;
begin
  src_lob:='中華人民共和國';
  chunksize:=dbms_lob.getchunksize(src_lob);
  dbms_output.put_line('chunk'||chunksize);
end;


16、函數getlength
說明:用於取得lob數據的實際長度,適用於clob\blob\bfile。
語法:dbms_lob.getlength(lob_loc in blob/clob/nclob) return integer;
例子:
declare
  file1 bfile;
  length int;
begin
file1:=bfilename('G','readme.doc');
length:=dbms_lob.getlength(file1);
dbms_output.put_line(length);
end;


17、函數instr
說明:返回特定樣式數據在lob中從某偏移位置開始第n次出現是的具體位置,適用於blob/clob/bfile。
語法:dbms_lob.instr(lob_loc in blob/clob/nclob/bfile,pattern in raw/varchar2,offset in integer:=1,nth in integer:=1) return integer;
其中pattern指定要搜索的字符串或者二進制數據,offset指定搜索的起始位置,nth指定第n次的出現次數。
例子:
declare
  src_lob clob;
  location int;
  offset int;
  occurence int;
begin
src_lob:='祖國、祖國,偉大的祖國';
offset:=2;
occurence:=2;
location:=dbms_lob.instr(src_lob,'祖國',offset,occurence);
dbms_output.put_line('從第'||offset||'字符開始,祖國第'||occurence||'次出現位置爲'||location);
end;


18、函數isopen
說明:用於確定lob是否已經被打開,如果打開了則返回1,反之0,適用於blob/clob/bfile。
語法:dbms_lob.isopen(lob_loc in blob/clob/bfile) return integer;
例子:
declare
  src_lob clob;
begin
src_lob:='祖國、祖國,偉大的祖國';
if dbms_lob.isopen(src_lob)=0 then
 dbms_Lob.open(src_lob,1);
end if;
dbms_lob.colse(src_lob);
end;


19、函數istemporary
說明:用於確定lob定位符是否爲臨時lob,是則返回1,反之0。
語法:dbms_lob.istemporary(lob_loc in blob/clob/nclob) return integer;
例子:
declare
  src_lob clob;
begin
if dbms_lob.istemporary(src_lob)=1 then
 dbms_output.put_line('已經是臨時lob');
else
 dbms_output.put_line('臨時LOB需要建立');
 dbms_lob.createtemporary(src_lob,true);
end if;
dbms_lob.freetemporary(src_lob);
end;


20、過程loadfromfile
說明:用於將bfile的部分或者全部內容複製到目標lob變量(clob或者blob)中。
語法:dbms_lob.loadfromfile(
dest_lob in nocopy blob/clob,
src_file in bfile,amount in integer,
dest_offset in integer:=1,
src_offset in integer:=1);
其中,src_file指定bfile定位符,當bfile數據裝載到clob中時,不會進行字符集轉換,因此要確保bfile數據與數據庫具有相同字符集,否則裝載後的數據爲亂碼。
例子:
declare
  src_lob bfile;
  dest_lob clob;
  amount int;
begin
  src_lob:=bfilename('G','a.txt');
  dbms_lob.createtemporary(dest_lob,true);
  dbms_lob.fileopen(src_lob,0);
  amount:=dbms_lob.getlength(src_lob);
  dbms_lob.loadfromfile(dest_lob,src_lob,amount);
  dbms_lob.fileclose(src_lob);
  dbms_lob.freetemporary(dest_lob);
end;


21、過程loadblobfromfile
說明:將bfile數據裝載到blob中,並且在裝載後可以取得新的偏移位置
語法:
dbms_lob.loadblobfromfile(
dest_lob in out nocopy blob,src_bfile in bfile,
amount in integer,dest_offset in out integer,
src_offset in out integer);
其中,src_bfile指定bfile定位符,dest_offset(in)指定目標lob的起始位置,dest_offset(out)用於取得裝載完成後的偏移位置,
src_offset(in)指定bfile定位符的起始位置,src_offset(out)用於取得bfile讀取完成後的偏移位置。
例子:
declare
  src_lob bfile;
  dest_lob blob;
  amount int;
  src_offset int:=1;
  dest_offset int:=1;
begin
src_lob:=bfilename('G','a.txt');
dbms_lob.createtemporary(dest_lob,true);
dbms_lob.fileopen(src_lob,0);
amount:=dbms_lob.getlength(src_lob);
dbms_lob.loadblobfromfile(dest_lob,src_lob,amount,dest_offset,src_offset);
dbms_lob.fileclose(src_lob);
  dbms_lob.freetemporary(dest_lob);
  dbms_output.put_line(dest_offset);
end;


22、過程loadclobfromfile
說明:用於將bfile數據裝載到clob中,可以指定字符集id號,並進行字符集裝換。
語法:
dbms_lob.loadclobfromfile(dest_lob in out nocopy clob,
src_bfile in bfile,amount in integer,
dest_offset in out integer,src_offset in out integer,
src_csid in number,lang_context in out integer,warning out integer);
其中,src_csid指定源文件的字符集id號,lang_context(in)指定語言上下文,
lang_context(out)用於取得先前裝載的語言上下文,warning用於取得警告消息。
例子:
declare
  src_lob bfile;
  dest_lob clob;
  amount int;
  src_offset int:=1;
  dest_offset int:=1;
  csid int:=0;
  lc int:=0;
  warning int;
begin
src_lob:=bfilename('G','a.txt');
dbms_lob.createtemporary(dest_lob,true);
dbms_lob.fileopen(src_lob,0);
amount:=dbms_lob.getlength(src_lob);
dbms_lob.loadclobfromfile(dest_lob,src_lob,amount,dest_offset,src_offset,csid,lc,waring);
dbms_lob.fileclose(src_lob);
dbms_output.put_line(dest_lob);
dbms_lob.freetemporary(dest_lob);
end;


23、過程open
說明:該過程用於打開lob時指定lob的讀寫模式:只讀(dbms_lob.lob_readonly)、讀寫(dbms_lob.lob_readwrite),適用於blob\clob\bfile。
語法:
dbms_lob.open(lob_loc in out nocopy blob/clob/bfile,open_mode in binary_integer);
其中,open_mode指定lob的讀寫模式。
例子:
declare
  src_lob clob;
  v1 varchar2(100):='中華人民共和國';
  amount in;
begin
amount:=length(v1);
dbms_lob.createtemporary(src_lob,true);
dbms_lob.open(src_lob,dbms_lob,lob_readwrite);
dbms_lob.write(src_lob,amount,1,v1);
dbms_lob.close(src_lob);
dbms_output.put_line(src_lob);
dbms_lob.freetemporary(src_lob);
end;


24、過程read
說明:用於將lob數據讀取到緩衝區中,適用於blob\clob\bfile。
語法:
dbms_lob.read(lob_loc in blob/clob/bfile,amount in out nocopy binary_integer,offset in integer,buffer out raw/varchar2);
其中,從lob_loc中開始偏移offset,讀取amount個;
amount(in)指定要讀取的字節個數(blob)或字符個數(clob),amount(out)用於取得實際讀取的字節個數或字符個數。
例子:
declare
  src_lob clob:='偉大的祖國';
  amount int;
  buffer varchar2(200);
  offset int:=1;
begin
amount:=dbms_lob.getlength(src_lob);
dbms_lob.open(src_lob,dbms_lob.lob_readonly);
dbms_lob.read(src_lob,amount,offset,buffer);
dbms_output.put_line(buffer);
dbms_lob.close(src_lob);
end;


25、函數substr
說明:用於返回lob中從指定位置開始的部分內容,適用於blob\clob\bfile.
語法:dbms_lob.substr(lob_loc in blob/clob/bfile,amount in integer :=32767,offset in integer:=1);
其中始於offset,長度爲amount。
例子:
declare
  src_lob clob:='中國,中國,偉大的中國';
  amount int;
  v1 varchar2(200);
  offset int;
begin
amount:=10;
offset:=4;
v1:=dbms_lob.substr(src_lob,amount,offset);
dbms_output.put_line(v1);
end;


26、過程trim
說明:用於截斷lob內容到指定長度,適用於blob\clob/nclob。
語法:dbms_lob.trim(lob_loc in out nocopy blob/clob/nclob,newlen in integer);
例子:
declare
  src_lob clob:='中國,中國,偉大的中國';
  amount int;
begin
amount:=5;
dbms_lob.trim(src_lob,amount);
dbms_output.put_line(src_lob);
end;


27、過程write
說明:用於將緩衝區數據寫入到lob中的特定位置,適用於blob和clob。
語法:dbms_lob.write(lob_loc in out nocopy blob/clob,amount in binary_integer,offset in integer,buffer in raw/varchar2);
其中,buffer指定要寫入的內容,讀取amount到lob_loc,開始位置爲offset.
例子:
declare
  src_lob clob:='我的祖國';
  amount int;
  offset int;
  buffer varchar2(100):='偉大的中國';
begin
offset:=dbms_lob.getlength(src_lob)+1;
amount:=length(buffer);
dbms_lob.write(src_lob,amount,offset,buffer);
  dbms_output.put_line(src_lob);
end;


28、過程writeappend
說明:用於將緩衝區數據寫入到lob尾部,適用於blob\clob\nclob。
語法:
dbms_lob.writeappend(
lob loc in out nocopy blob/clob/nclob,
amount in binary_integer,buffer in raw);
例子:
declare
  src_lob clob:='我的祖國';
  amount int;
  buffer varchar2(100):=',偉大的祖國';
begin
amount:=length(buffer);
dbms_lob.writeappend(src_lob,amount,buffer);
dbms_output.put_line(src_lob);
end;




五、內部LOB(CLOB/BLOB)的使用
說明:clob存放不超過4g的文本數據;blob存放不超過4g的二進制數據(例如圖片)。


1、建表
create table lob_example1(id number(6) primary key,name varchar2(10),resume clob);
create table lob_example2(id number(6) primary key,name varchar2(10),photo blob);


2、插入
說明:使用函數empty_clob()初始化clob列,函數empty_blob()初始化blob列
注意:函數empty_clob()/empty_blob()與null不同,儘管該函數沒有提供任何數據,但卻分配了lob定位符。
insert into lob_example1 values(1,'王鳴',empty_clob());
insert into lob_example1 values(2,'馬麗',empty_clob());
insert into lob_example2 values(1,'王鳴',empty_blob());
insert into lob_example2 values(2,'馬麗',empty_blob());


3、更新
說明:爲clob列追加數據使用dbms_lob中的write或writeappend來完成。
declare
  lob_loc clob;
  text varchar2(200);
  amount int;
  offset int;
begin
select resume into lob_loc from lob_example1 where id=1 for update;
offset:=dbms_lob.getlength(lob_loc)+1;
text:='哈工大';
amount:=length(text);
dbms_lob.write(lob_loc,amount,offset,text);
commit;
end;


4、查詢
說明:這裏查詢針對數據不大於2000字節的情況,使用dbms_lob.read讀取數據。如果大於2000字節使用循環方式讀取。
例子:
declare
  lob_loc clob;
  lobloc blob;
  buffer varchar2(200);
  buffer2 raw(2000);
  amount int;
  offset int:=1;
begin
--clob
select resume into lob_loc from lob_example1 where id=1;
amount:=dbms_lob.getlength(lob_loc);
dbms_lob.read(lob_loc,amount,offset,buffer);--從第1個字符開始的所有數據
dbms_output.put_line(buffer);
--blob
select photo into lobloc from lob_example2 where id=1;
amount:=dbms_lob.gerlength(lobloc);
dbms_lob.read(lob_loc,amount,offset,buffer);
end;


5、將文本文件內容寫入到clob列/將二進制文件內容寫入到blob列
說明:將文本文件內容寫入到clob中需要使用過程dbms_lob.loadfromfile或dbms_lob.loadclobfromfile,爲了避免字符集問題建議使用loadclobfromfile。
將二進制文件內容寫入到blob中使用dbms_lob.loadblobfromfile。
例子:
declare
  lobloc clob;
  lobloc2 blob;
  fileloc bfile;
  amount int;
  src_offset int:=1;
  dest_offset int:=1;
  csid int:=0;
  lc int:=0;
  waring int;
begin
--clob
fileloc:=bfilename('G','馬麗.txt');
dbms_lob.fileopen(fileloc,0);
amount:=dbms_lob.getlength(fileloc);
select sesume into lobloc from lob_example1 where id=2 for update;
dbms_lob.loadclobfromfile(lobloc,fileloc,amount,dest_offset,src_offset,csid,lc,waring);
dbms_lob.fileclose(fileloc);
commit;
--bloc
select photo into lobloc2 from lob_example2 where id=1 for update;
fileloc:=bfilename('G','馬麗.bmp');
dbms_lob.fileopen(fileloc,0);
amount:=dbms_lob.getlength(fileloc);
dbms_lob.loadblobfromfile(lobloc2,fileloc,amount,dest_offset,src_offset);
dbms_lob.fileclose(fileloc);
commit;
end;


6、將clob列內容寫入到文本文件/將blob列內容寫入到二進制文件
說明:不僅需要使用dbms_lob包讀取clob列的內容,而且需要使用utl_file包建立文本文件並寫入內容。
例子:
declare
  lobloc clob;
  lobloc2 blob;
  amount int;
  offset int:=1
  buffer varchar2(2000);
  buffer2 raw(1000);
  handle utl_file.file_type;
begin
--clob
select resume into lobloc from lob_example1 where id=1;
amount:=dbms_lob.getlength(lobloc);
dbms_lob.read(lobloc,amount,offset,buffer);
handle:=utl_file.fopen('user_dir','a.txt','w',2000);
utl_file.put_line(bandle,buffer);
utl_file.fclose(handle);
--blob
select photo into lobloc2 from lob_example2 where id=1;
amount:=dbms_lob.getlength(lobloc2);
dbms_lob.read(lobloc2,amount,offset,buffer);
handle:=utl_file.fopen('user_dir','a.bmp','w',1000);
utl_file.put_rwa(bandle,buffer);
utl_file.fclose(handle);
end;




六、外部LOB(BFILE)的使用
說明:爲了在數據庫中訪問OS文件的數據,需要使用bfile類型。需要注意,bfile所對應的OS文件內容只能讀取,不能修改。
使用bfile類型訪問OS文件是,必須首先建立directory對象,而建立此對象要求用戶有create any directory權限。
例子:
conn system/manager
grant create any directory to scott;
conn scott/tiger
create directory bfile_dir as 'G:\BFILE_EXAMPLE';
當建立directory對象時,一定要確保OS目錄已經存在。如果目錄不存在建立時不會顯示錯誤,當依據該directory對象訪問OS文件時纔會報錯誤。
建立了directory對象後,就可以使用bfile類型訪問OS文件了。


1、建表
說明:在表中訪問OS文件需要使用bfile。
create table lob_example3(id number(6) primary key,name varchar2(10),resume bfile);


2、插入
說明:使用bfilename()來初始化bfile列。當使用此函數時,directory對象必須使用大寫。
insert into lob_example3 values(1,'王鳴',bfilename('BFILE_DIR','王鳴.TXT'));
insert into lob_example3 values(2,'馬麗',bfilename('BFILE_DIR','馬麗.TXT'));


3、查詢
說明:使用dbms_lob.read讀取,用raw變量接收。
declare
  buffer raw(2000);
  amount int;
  offset int;
  lobloc bfile;
begin
select resume into lobloc from lob_example3 where id=2;
dbms_lob.fileopen(lobloc,0);
amount:=dbms_lob.getlength(lobloc);
offset:=1;
dbms_lob.read(lobloc,amount,offset,buffer);
dbms_lob.fileclose(lobloc);
end;






發佈了65 篇原創文章 · 獲贊 24 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章